index.js 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257
  1. /**
  2. * 网页涂鸦精灵:可以针对任何网页进行任何涂鸦
  3. * @author zhaoxianlie
  4. */
  5. let editor = null;
  6. new Vue({
  7. el: '#pageContainer',
  8. data: {
  9. editing: false,
  10. editCM: {},
  11. unSavedCMID: 0,
  12. cachedModifiers: []
  13. },
  14. mounted: function () {
  15. this.editCM = this.getANewCM();
  16. // 编辑器初始化
  17. editor = CodeMirror.fromTextArea(this.$refs.mScript, {
  18. mode: "text/javascript",
  19. lineNumbers: true,
  20. matchBrackets: true,
  21. styleActiveLine: true,
  22. lineWrapping: true
  23. });
  24. // 退出的时候检测是否有未保存的数据
  25. window.onbeforeunload = function (e) {
  26. if (this.editing) {
  27. (e || window.event).returnValue = '当前还有未保存的数据,确定要离开么?';
  28. }
  29. };
  30. // 初始化获取数据
  31. chrome.runtime.sendMessage({
  32. type: MSG_TYPE.GET_PAGE_MODIFIER_CONFIG
  33. }, (cmList) => {
  34. this.cachedModifiers = cmList || [];
  35. });
  36. },
  37. methods: {
  38. getANewCM: function () {
  39. return {
  40. mName: '',
  41. mPattern: '',
  42. mFilter: '0',
  43. mScript: '',
  44. mRefresh: 0,
  45. mDisabled: null
  46. };
  47. },
  48. createModifier: function () {
  49. if (this.editing) {
  50. return alert('当前还有未保存的数据,无法继续创建!');
  51. }
  52. this.editing = true;
  53. this.editCM = this.getANewCM();
  54. this.editCM.id = 'mf_' + new Date() * 1;
  55. this.cachedModifiers.push(this.editCM);
  56. // 右侧面板,进行表单项编辑
  57. this.$refs.mForm.reset();
  58. $('.m-mask').slideUp();
  59. $('.m-form').removeClass('x-masked');
  60. },
  61. selectModifier: function (cm) {
  62. // 在编辑中,并且确定还要当前这个数据,就设定为选择无效
  63. if (this.editing) {
  64. if (confirm('当前还有未保存的数据,确定不要这个数据了吗?')) {
  65. this.editing = false;
  66. this.cachedModifiers.pop();
  67. } else {
  68. return false;
  69. }
  70. }
  71. // 如果当前数据还没保存,也点击无效
  72. if (this.editCM.id === cm.id) {
  73. return false;
  74. }
  75. // 把数据呈现到编辑面板
  76. this.editCM = cm;
  77. editor.setValue(cm.mScript);
  78. $('.m-mask').slideUp();
  79. $('.m-form').removeClass('x-masked');
  80. },
  81. saveModifier: function (isEditMode) {
  82. if (isEditMode) {
  83. this.mScript = editor.getValue();
  84. this.cachedModifiers.some(cm => {
  85. if (cm.id === this.editCM.id) {
  86. cm.mName = this.editCM.mName;
  87. cm.mPattern = this.editCM.mPattern;
  88. cm.mFilter = this.editCM.mFilter;
  89. cm.mRefresh = this.editCM.mRefresh;
  90. cm.mScript = editor.getValue();
  91. return true;
  92. }
  93. });
  94. }
  95. chrome.runtime.sendMessage({
  96. type: MSG_TYPE.SAVE_PAGE_MODIFIER_CONFIG,
  97. params: this.cachedModifiers
  98. }, () => {
  99. alert('数据操作成功!');
  100. this.editCM = this.getANewCM();
  101. this.editing = false;
  102. this.$refs.mForm.reset();
  103. $('.m-mask').slideDown();
  104. $('.m-form').addClass('x-masked');
  105. });
  106. },
  107. // 导入配置
  108. importModifier: function () {
  109. let that = this;
  110. let fileInput = document.getElementById('fileInput');
  111. if (!fileInput) {
  112. fileInput = document.createElement('input');
  113. fileInput.id = 'fileInput';
  114. fileInput.type = 'file';
  115. fileInput.accept = 'application/json';
  116. fileInput.style.cssText = 'position:relative;top:-1000px;left:-1000px;';
  117. fileInput.onchange = function (event) {
  118. let reader = new FileReader();
  119. reader.readAsText(fileInput.files[0], 'utf-8');
  120. reader.onload = (evt) => {
  121. let content = evt.target.result;
  122. try {
  123. // 过滤掉文件头部所有注释,然后转化成json
  124. let list = JSON.parse(content.replace(/^\/\*[^\*]*\*\//, ''));
  125. if (list && Array.isArray(list) && list.length) {
  126. let keys = 'id,mName,mPattern,mFilter,mRefresh,mScript,mDisabled'.split(',');
  127. let result = list.filter(item => {
  128. if (typeof item === 'object') {
  129. Object.keys(item).forEach(k => {
  130. !keys.includes(k) && delete(item[k]);
  131. });
  132. if (Object.keys(item).length) {
  133. return true;
  134. }
  135. }
  136. return false;
  137. });
  138. if (result.length) {
  139. let merge = null;
  140. // 配置合并,如果有重复的,则弹框确认
  141. result.forEach(r => {
  142. let found = that.cachedModifiers.some(cm => {
  143. if (r.id === cm.id || r.mName === cm.mName || r.mPattern === cm.mPattern) {
  144. if (merge === null) {
  145. merge = confirm('发现有相同名称或规则的精灵,是否选择覆盖?');
  146. }
  147. if (merge) {
  148. cm = r;
  149. } else {
  150. r.id += '_';
  151. }
  152. return merge;
  153. }
  154. });
  155. if (!found) {
  156. that.cachedModifiers.push(r);
  157. }
  158. });
  159. return that.saveModifier();
  160. }
  161. }
  162. throw new Error();
  163. } catch (e) {
  164. alert('当前选择的JSON配置文件格式不正确!');
  165. }
  166. };
  167. };
  168. document.body.appendChild(fileInput);
  169. }
  170. fileInput.click();
  171. },
  172. // 导出配置
  173. exportModifier: function () {
  174. chrome.runtime.sendMessage({
  175. type: MSG_TYPE.GET_PAGE_MODIFIER_CONFIG
  176. }, (cmList) => {
  177. if (cmList && cmList.length) {
  178. let timestamp = new Date() * 1;
  179. let exportPrefix = '/* Page modifier config, exported from FeHelper, timestamp:' + timestamp + ' */\n\n';
  180. let exportContent = JSON.stringify(cmList, null, 4);
  181. let blob = new Blob([exportPrefix + exportContent], {type: 'application/octet-stream'});
  182. // 请求权限
  183. chrome.permissions.request({
  184. permissions: ['downloads']
  185. }, (granted) => {
  186. if (granted) {
  187. chrome.downloads.download({
  188. url: URL.createObjectURL(blob),
  189. saveAs: true,
  190. conflictAction: 'overwrite',
  191. filename: 'FeHelper-PM-' + timestamp + '.json'
  192. }, () => {
  193. alert('数据导出成功!');
  194. });
  195. } else {
  196. alert('必须接受授权,才能正常导出!');
  197. }
  198. });
  199. } else {
  200. alert('没有已保存/可使用的精灵,不可导出!');
  201. }
  202. });
  203. },
  204. // 清空精灵
  205. removeModifier: function (theCM) {
  206. if (confirm('你确定要删除所有的精灵吗,此操作不可撤销!')) {
  207. if (theCM) {
  208. this.cachedModifiers = this.cachedModifiers.filter(cm => {
  209. return cm.id !== theCM.id;
  210. });
  211. } else {
  212. this.cachedModifiers = [];
  213. }
  214. this.saveModifier();
  215. }
  216. },
  217. // 停用精灵
  218. disableModifier: function (theCM) {
  219. if (theCM) {
  220. if (confirm('请再次确认是否需要' + (theCM.mDisabled ? '启用' : '停用') + '此精灵?')) {
  221. this.editCM.mDisabled = !theCM.mDisabled;
  222. this.saveModifier(true);
  223. }
  224. } else {
  225. if (confirm('停用精灵后,可单独编辑启用;是否继续此操作?')) {
  226. this.cachedModifiers.forEach(cm => {
  227. cm.mDisabled = true;
  228. });
  229. this.saveModifier();
  230. }
  231. }
  232. }
  233. }
  234. });