index.js 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258
  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. cm.mDisabled = !!cm.mDisabled;
  92. return true;
  93. }
  94. });
  95. }
  96. chrome.runtime.sendMessage({
  97. type: MSG_TYPE.SAVE_PAGE_MODIFIER_CONFIG,
  98. params: this.cachedModifiers
  99. }, () => {
  100. alert('数据操作成功!');
  101. this.editCM = this.getANewCM();
  102. this.editing = false;
  103. this.$refs.mForm.reset();
  104. $('.m-mask').slideDown();
  105. $('.m-form').addClass('x-masked');
  106. });
  107. },
  108. // 导入配置
  109. importModifier: function () {
  110. let that = this;
  111. let fileInput = document.getElementById('fileInput');
  112. if (!fileInput) {
  113. fileInput = document.createElement('input');
  114. fileInput.id = 'fileInput';
  115. fileInput.type = 'file';
  116. fileInput.accept = 'application/json';
  117. fileInput.style.cssText = 'position:relative;top:-1000px;left:-1000px;';
  118. fileInput.onchange = function (event) {
  119. let reader = new FileReader();
  120. reader.readAsText(fileInput.files[0], 'utf-8');
  121. reader.onload = (evt) => {
  122. let content = evt.target.result;
  123. try {
  124. // 过滤掉文件头部所有注释,然后转化成json
  125. let list = JSON.parse(content.replace(/^\/\*[^\*]*\*\//, ''));
  126. if (list && Array.isArray(list) && list.length) {
  127. let keys = 'id,mName,mPattern,mFilter,mRefresh,mScript,mDisabled'.split(',');
  128. let result = list.filter(item => {
  129. if (typeof item === 'object') {
  130. Object.keys(item).forEach(k => {
  131. !keys.includes(k) && delete(item[k]);
  132. });
  133. if (Object.keys(item).length) {
  134. return true;
  135. }
  136. }
  137. return false;
  138. });
  139. if (result.length) {
  140. let merge = null;
  141. // 配置合并,如果有重复的,则弹框确认
  142. result.forEach(r => {
  143. let found = that.cachedModifiers.some(cm => {
  144. if (r.id === cm.id || r.mName === cm.mName || r.mPattern === cm.mPattern) {
  145. if (merge === null) {
  146. merge = confirm('发现有相同名称或规则的精灵,是否选择覆盖?');
  147. }
  148. if (merge) {
  149. cm = r;
  150. } else {
  151. r.id += '_';
  152. }
  153. return merge;
  154. }
  155. });
  156. if (!found) {
  157. that.cachedModifiers.push(r);
  158. }
  159. });
  160. return that.saveModifier();
  161. }
  162. }
  163. throw new Error();
  164. } catch (e) {
  165. alert('当前选择的JSON配置文件格式不正确!');
  166. }
  167. };
  168. };
  169. document.body.appendChild(fileInput);
  170. }
  171. fileInput.click();
  172. },
  173. // 导出配置
  174. exportModifier: function () {
  175. chrome.runtime.sendMessage({
  176. type: MSG_TYPE.GET_PAGE_MODIFIER_CONFIG
  177. }, (cmList) => {
  178. if (cmList && cmList.length) {
  179. let timestamp = new Date() * 1;
  180. let exportPrefix = '/* Page modifier config, exported from FeHelper, timestamp:' + timestamp + ' */\n\n';
  181. let exportContent = JSON.stringify(cmList, null, 4);
  182. let blob = new Blob([exportPrefix + exportContent], {type: 'application/octet-stream'});
  183. // 请求权限
  184. chrome.permissions.request({
  185. permissions: ['downloads']
  186. }, (granted) => {
  187. if (granted) {
  188. chrome.downloads.download({
  189. url: URL.createObjectURL(blob),
  190. saveAs: true,
  191. conflictAction: 'overwrite',
  192. filename: 'FeHelper-PM-' + timestamp + '.json'
  193. }, () => {
  194. alert('数据导出成功!');
  195. });
  196. } else {
  197. alert('必须接受授权,才能正常导出!');
  198. }
  199. });
  200. } else {
  201. alert('没有已保存/可使用的精灵,不可导出!');
  202. }
  203. });
  204. },
  205. // 清空精灵
  206. removeModifier: function (theCM) {
  207. if (confirm('你确定要删除所有的精灵吗,此操作不可撤销!')) {
  208. if (theCM) {
  209. this.cachedModifiers = this.cachedModifiers.filter(cm => {
  210. return cm.id !== theCM.id;
  211. });
  212. } else {
  213. this.cachedModifiers = [];
  214. }
  215. this.saveModifier();
  216. }
  217. },
  218. // 停用精灵
  219. disableModifier: function (theCM) {
  220. if (theCM) {
  221. if (confirm('请再次确认是否需要' + (theCM.mDisabled ? '启用' : '停用') + '此精灵?')) {
  222. this.editCM.mDisabled = !theCM.mDisabled;
  223. this.saveModifier(true);
  224. }
  225. } else {
  226. if (confirm('停用精灵后,可单独编辑启用;是否继续此操作?')) {
  227. this.cachedModifiers.forEach(cm => {
  228. cm.mDisabled = true;
  229. });
  230. this.saveModifier();
  231. }
  232. }
  233. }
  234. }
  235. });