Browse Source

修改项目内容,兼容firefox.json

zxlie 4 tháng trước cách đây
mục cha
commit
544503b7d8

+ 31 - 84
apps/background/awesome.js

@@ -20,6 +20,7 @@ let Awesome = (() => {
      */
      */
     let StorageMgr = (() => {
     let StorageMgr = (() => {
 
 
+        // 获取chrome.storage.local中的内容,返回Promise,可直接await
         let get = keyArr => {
         let get = keyArr => {
             return new Promise((resolve, reject) => {
             return new Promise((resolve, reject) => {
                 chrome.storage.local.get(keyArr, result => {
                 chrome.storage.local.get(keyArr, result => {
@@ -28,15 +29,6 @@ let Awesome = (() => {
             });
             });
         };
         };
 
 
-
-        let getSync = async (keyArr) => {
-            return await (new Promise((resolve, reject) => {
-                chrome.storage.local.get(keyArr, result => {
-                    resolve(typeof keyArr === 'string' ? result[keyArr] : result);
-                });
-            }));
-        };
-
         let set = (items, values) => {
         let set = (items, values) => {
             return new Promise((resolve, reject) => {
             return new Promise((resolve, reject) => {
                 if (typeof items === 'string') {
                 if (typeof items === 'string') {
@@ -59,7 +51,7 @@ let Awesome = (() => {
             });
             });
         };
         };
 
 
-        return {get, set, remove,getSync};
+        return {get, set, remove};
     })();
     })();
 
 
     /**
     /**
@@ -99,7 +91,7 @@ let Awesome = (() => {
     let install = (toolName, fnProgress) => {
     let install = (toolName, fnProgress) => {
         return new Promise((resolve, reject) => {
         return new Promise((resolve, reject) => {
             // 存储html文件
             // 存储html文件
-            StorageMgr.set(TOOL_NAME_TPL.replace('#TOOL-NAME#', toolName), ' ');
+            StorageMgr.set(TOOL_NAME_TPL.replace('#TOOL-NAME#', toolName), new Date().getTime());
             log(toolName + '工具html模板安装/更新成功!');
             log(toolName + '工具html模板安装/更新成功!');
             resolve();
             resolve();
         });
         });
@@ -140,7 +132,7 @@ let Awesome = (() => {
         // 获取本地开发的插件,也拼接进来
         // 获取本地开发的插件,也拼接进来
         try {
         try {
             const DEV_TOOLS_MY_TOOLS = 'DEV-TOOLS:MY-TOOLS';
             const DEV_TOOLS_MY_TOOLS = 'DEV-TOOLS:MY-TOOLS';
-            let _tools = await StorageMgr.getSync(DEV_TOOLS_MY_TOOLS);
+            let _tools = await StorageMgr.get(DEV_TOOLS_MY_TOOLS);
             let localDevTools = JSON.parse(_tools || '{}');
             let localDevTools = JSON.parse(_tools || '{}');
             Object.keys(localDevTools).forEach(tool => {
             Object.keys(localDevTools).forEach(tool => {
                 toolMap[tool] = localDevTools[tool];
                 toolMap[tool] = localDevTools[tool];
@@ -153,8 +145,8 @@ let Awesome = (() => {
         tools.forEach(tool => {
         tools.forEach(tool => {
             promises = promises.concat([detectInstall(tool), detectInstall(tool, true)])
             promises = promises.concat([detectInstall(tool), detectInstall(tool, true)])
         });
         });
-        let pAll = Promise.all(promises).then(values => {
-            values.forEach((v, i) => {
+        return Promise.all(promises).then(values => {
+            (values || []).forEach((v, i) => {
                 let tool = tools[Math.floor(i / 2)];
                 let tool = tools[Math.floor(i / 2)];
                 let key = i % 2 === 0 ? 'installed' : 'menu';
                 let key = i % 2 === 0 ? 'installed' : 'menu';
                 toolMap[tool][key] = v;
                 toolMap[tool][key] = v;
@@ -163,47 +155,45 @@ let Awesome = (() => {
                     toolMap[tool][key] = toolMap[tool][key] && toolMap[tool]._enable;
                     toolMap[tool][key] = toolMap[tool][key] && toolMap[tool]._enable;
                 }
                 }
             });
             });
+
             return toolMap;
             return toolMap;
         });
         });
-        let pSort = SortToolMgr.get();
-
-        return Promise.all([pAll,pSort]).then(vs => {
-            let allTools = vs[0] || {};
-            let sortTools = vs[1] || [];
-
-            if (sortTools && sortTools.length) {
-                let map = {};
-                sortTools.forEach(tool => {
-                    if(allTools[tool]) {
-                        map[tool] = allTools[tool];
-                    }
-                });
-                Object.keys(allTools).forEach(tool => {
-                    if (!map[tool]) {
-                        map[tool] = allTools[tool];
-                    }
-                });
-                return map;
-            }else{
-                return allTools;
-            }
-        });
     };
     };
 
 
     /**
     /**
      * 检查看本地已安装过哪些工具
      * 检查看本地已安装过哪些工具
      * @returns {Promise}
      * @returns {Promise}
      */
      */
-    let getInstalledTools = () => getAllTools().then(tools => {
+    let getInstalledTools = async () => {
+        let tools = await getAllTools();
         if (!tools) return {};
         if (!tools) return {};
         let istTolls = {};
         let istTolls = {};
-        Object.keys(tools).filter(tool => {
+        Object.keys(tools).forEach(tool => {
             if (tools[tool] && tools[tool].installed) {
             if (tools[tool] && tools[tool].installed) {
                 istTolls[tool] = tools[tool];
                 istTolls[tool] = tools[tool];
             }
             }
         });
         });
-        return istTolls;
-    });
+
+        // 先批量获取所有时间戳
+        const toolNames = Object.keys(istTolls);
+        const timeMap = {};
+        await Promise.all(toolNames.map(async tool => {
+            let time = parseInt(await StorageMgr.get(TOOL_NAME_TPL.replace('#TOOL-NAME#', tool))) || 0;
+            timeMap[tool] = time;
+        }));
+        
+        // 用同步sort排序
+        let sortedTools = toolNames.sort((a, b) => {
+            return timeMap[a] - timeMap[b];
+        });
+
+        let sortedToolMap = {};
+        sortedTools.forEach(tool => {
+            sortedToolMap[tool] = istTolls[tool];
+        });
+        
+        return sortedToolMap;
+    };
 
 
     /**
     /**
      * 获取工具的content-script
      * 获取工具的content-script
@@ -257,47 +247,6 @@ let Awesome = (() => {
         }
         }
     };
     };
 
 
-    /**
-     * 远程获取的代码管理器
-     * @type {{get, set}}
-     */
-    let CodeCacheMgr = (() => {
-        const TOOLS_FROM_REMOTE = 'TOOLS_FROM_REMOTE';
-
-        let get = () => {
-            return StorageMgr.getSync(TOOLS_FROM_REMOTE);
-        };
-
-        let set = (remoteCodes) => {
-            let obj = {};
-            obj[TOOLS_FROM_REMOTE]=remoteCodes;
-            chrome.storage.local.set(obj);
-        };
-
-        return {get, set};
-    })();
-
-    /**
-     * 工具排序管理器
-     * @type {{get, set}}
-     */
-    let SortToolMgr = (() => {
-        const TOOLS_CUSTOM_SORT = 'TOOLS_CUSTOM_SORT';
-
-        let get = async () => {
-            let cache = await StorageMgr.getSync(TOOLS_CUSTOM_SORT);
-
-            return [].concat(JSON.parse(cache || '[]')).filter(t => !!t);
-        };
-
-        let set = (newSortArray) => {
-            let obj = {};
-            obj[TOOLS_CUSTOM_SORT] = JSON.stringify([].concat(newSortArray || []).filter(t => !!t));
-            chrome.storage.local.set(obj);
-        };
-
-        return {get, set};
-    })();
 
 
     /**
     /**
      * 采集客户端信息并发送给background
      * 采集客户端信息并发送给background
@@ -366,8 +315,6 @@ let Awesome = (() => {
         getToolTpl,
         getToolTpl,
         gcLocalFiles,
         gcLocalFiles,
         getAllTools,
         getAllTools,
-        SortToolMgr,
-        CodeCacheMgr,
         collectAndSendClientInfo
         collectAndSendClientInfo
     }
     }
 })();
 })();

+ 11 - 0
apps/background/background.js

@@ -529,6 +529,17 @@ let BgPageInstance = (function () {
                         // 埋点:自动触发json-format-auto
                         // 埋点:自动触发json-format-auto
                         Statistics.recordToolUsage(request.params.tool_name,request.params);
                         Statistics.recordToolUsage(request.params.tool_name,request.params);
                         break;
                         break;
+                    case 'fetch-hotfix-json':
+                        // 代理请求 hotfix.json,解决CORS问题
+                        fetch('https://baidufe.com/fehelper/static/js/hotfix.json?v=' + Date.now())
+                            .then(response => response.text())
+                            .then(scriptContent => {
+                                callback && callback({ success: true, content: scriptContent });
+                            })
+                            .catch(error => {
+                                callback && callback({ success: false, error: error.message });
+                            });
+                        return true; // 异步响应必须返回true
                 }
                 }
                 callback && callback(request.params);
                 callback && callback(request.params);
             } else {
             } else {

+ 14 - 1
apps/background/tools.js

@@ -266,5 +266,18 @@ let toolMap = {
     }
     }
 };
 };
 
 
-export default toolMap;
+// 判断是否为Firefox浏览器,如果是则移除特定工具
+if (navigator.userAgent.indexOf('Firefox') !== -1) {
+    delete toolMap['color-picker'];
+    delete toolMap['postman'];
+    delete toolMap['devtools'];
+    delete toolMap['websocket'];
+    delete toolMap['page-timing'];
+    delete toolMap['grid-ruler'];
+    delete toolMap['naotu'];
+    delete toolMap['screenshot'];
+    delete toolMap['page-monkey'];
+    delete toolMap['excel2json'];
+}
 
 
+export default toolMap;

+ 0 - 20
apps/chart-maker/main.js

@@ -123,25 +123,19 @@ document.addEventListener('DOMContentLoaded', function() {
     // 生成图表按钮点击事件 (修改为独立的函数)
     // 生成图表按钮点击事件 (修改为独立的函数)
     function generateChart() {
     function generateChart() {
         try {
         try {
-            console.log('开始生成图表...');
             let parsedData;
             let parsedData;
             const method = document.querySelector('input[name="data-input-method"]:checked').value;
             const method = document.querySelector('input[name="data-input-method"]:checked').value;
-            console.log('数据输入方式:', method);
 
 
             if (method === 'upload-csv' && uploadedData) {
             if (method === 'upload-csv' && uploadedData) {
                 parsedData = uploadedData;
                 parsedData = uploadedData;
-                console.log('使用上传的数据');
             } else if (method === 'manual') {
             } else if (method === 'manual') {
                 parsedData = parseInputData(); // 使用现有的手动数据解析函数
                 parsedData = parseInputData(); // 使用现有的手动数据解析函数
-                console.log('使用手动输入的数据');
             } else if (method === 'upload-csv' && !uploadedData) {
             } else if (method === 'upload-csv' && !uploadedData) {
                 throw new Error('请先上传文件');
                 throw new Error('请先上传文件');
             } else {
             } else {
                 throw new Error('请选择有效的数据输入方式并提供数据');
                 throw new Error('请选择有效的数据输入方式并提供数据');
             }
             }
             
             
-            console.log('解析后的数据:', parsedData);
-            
             if (!parsedData || 
             if (!parsedData || 
                 (parsedData.labels && parsedData.labels.length === 0) || 
                 (parsedData.labels && parsedData.labels.length === 0) || 
                 (parsedData.datasets && parsedData.datasets.length === 0)) {
                 (parsedData.datasets && parsedData.datasets.length === 0)) {
@@ -158,21 +152,17 @@ document.addEventListener('DOMContentLoaded', function() {
                 chartSettings.isSimpleData = true;
                 chartSettings.isSimpleData = true;
             }
             }
             
             
-            console.log('图表设置:', chartSettings);
-            
             // 调用chart-generator.js中的createChart函数
             // 调用chart-generator.js中的createChart函数
             if (typeof createChart !== 'function') {
             if (typeof createChart !== 'function') {
                 throw new Error('createChart函数未定义,请确保chart-generator.js正确加载');
                 throw new Error('createChart函数未定义,请确保chart-generator.js正确加载');
             }
             }
             
             
             createChart(parsedData, chartSettings);
             createChart(parsedData, chartSettings);
-            console.log('图表生成成功');
             
             
             exportPngBtn.disabled = false;
             exportPngBtn.disabled = false;
             exportJpgBtn.disabled = false;
             exportJpgBtn.disabled = false;
             copyImgBtn.disabled = false;
             copyImgBtn.disabled = false;
         } catch (error) {
         } catch (error) {
-            console.error('生成图表时出错:', error);
             showNotification(error.message, true);
             showNotification(error.message, true);
         }
         }
     }
     }
@@ -194,17 +184,13 @@ document.addEventListener('DOMContentLoaded', function() {
     
     
     // 初始化图表类型画廊
     // 初始化图表类型画廊
     function initChartTypeGallery() {
     function initChartTypeGallery() {
-        console.log('初始化图表类型预览画廊...');
-        
         // 获取所有图表类型预览项
         // 获取所有图表类型预览项
         const chartTypeItems = document.querySelectorAll('.chart-type-item');
         const chartTypeItems = document.querySelectorAll('.chart-type-item');
-        console.log(`找到${chartTypeItems.length}个图表类型预览项`);
         
         
         // 为每个预览项添加点击事件
         // 为每个预览项添加点击事件
         chartTypeItems.forEach(item => {
         chartTypeItems.forEach(item => {
             item.addEventListener('click', function() {
             item.addEventListener('click', function() {
                 const chartType = this.getAttribute('data-chart-type');
                 const chartType = this.getAttribute('data-chart-type');
-                console.log('选择了图表类型:', chartType);
                 
                 
                 // 更新活动状态
                 // 更新活动状态
                 chartTypeItems.forEach(item => item.classList.remove('active'));
                 chartTypeItems.forEach(item => item.classList.remove('active'));
@@ -614,7 +600,6 @@ document.addEventListener('DOMContentLoaded', function() {
                 loadingOverlay.remove();
                 loadingOverlay.remove();
                 
                 
                 showNotification('导出图像失败,请重试', true);
                 showNotification('导出图像失败,请重试', true);
-                console.error('导出图像出错:', error);
             });
             });
         }, 100);
         }, 100);
     }
     }
@@ -647,14 +632,12 @@ document.addEventListener('DOMContentLoaded', function() {
                                     showNotification('图表已复制到剪贴板');
                                     showNotification('图表已复制到剪贴板');
                                 })
                                 })
                                 .catch(err => {
                                 .catch(err => {
-                                    console.error('剪贴板API错误:', err);
                                     legacyCopyToClipboard(canvas);
                                     legacyCopyToClipboard(canvas);
                                 });
                                 });
                         } else {
                         } else {
                             legacyCopyToClipboard(canvas);
                             legacyCopyToClipboard(canvas);
                         }
                         }
                     } catch (e) {
                     } catch (e) {
-                        console.error('复制到剪贴板出错:', e);
                         legacyCopyToClipboard(canvas);
                         legacyCopyToClipboard(canvas);
                     }
                     }
                 });
                 });
@@ -663,7 +646,6 @@ document.addEventListener('DOMContentLoaded', function() {
                 loadingOverlay.remove();
                 loadingOverlay.remove();
                 
                 
                 showNotification('复制图像失败,请重试', true);
                 showNotification('复制图像失败,请重试', true);
-                console.error('复制图像出错:', error);
             });
             });
         }, 100);
         }, 100);
     }
     }
@@ -724,7 +706,5 @@ document.addEventListener('DOMContentLoaded', function() {
     // 根据数据格式更新图表类型选项
     // 根据数据格式更新图表类型选项
     function updateChartTypeOptions(dataFormat) {
     function updateChartTypeOptions(dataFormat) {
         // 由于移除了图表类型下拉框,这个函数现在仅记录当前数据格式,不再修改任何选项
         // 由于移除了图表类型下拉框,这个函数现在仅记录当前数据格式,不再修改任何选项
-        console.log('当前数据格式:', dataFormat);
-        // 未来可以根据数据格式来调整图表类型画廊的可见性或提示,但现在不需要操作
     }
     }
 }); 
 }); 

+ 3 - 7
apps/firefox.json

@@ -3,7 +3,7 @@
   "short_name": "FeHelper",
   "short_name": "FeHelper",
   "version": "2025.5.2014",
   "version": "2025.5.2014",
   "manifest_version": 3,
   "manifest_version": 3,
-  "description": "FE助手:JSON工具、代码美化、代码压缩、二维码工具、网页定制工具、便签笔记,等等",
+  "description": "FE助手:前端开发必备工具集,涵盖JSON格式化、代码美化与压缩、二维码生成、网页定制、便签笔记等数十种实用功能。界面现代、响应式设计,极致性能优化,国内可用,助力高效开发!",
   "icons": {
   "icons": {
     "16": "static/img/fe-16.png",
     "16": "static/img/fe-16.png",
     "48": "static/img/fe-48.png",
     "48": "static/img/fe-48.png",
@@ -96,11 +96,7 @@
     }
     }
   ],
   ],
   "content_security_policy": {
   "content_security_policy": {
-    "extension_pages": "script-src 'self' 'wasm-unsafe-eval'; worker-src 'self' blob:; style-src 'self' 'unsafe-inline'; object-src 'self'; connect-src 'self' blob:"
+    "extension_pages": "script-src 'self' 'wasm-unsafe-eval'; worker-src 'self' blob:; style-src 'self' 'unsafe-inline'; object-src 'self'; connect-src 'self' blob: https://chrome.fehelper.com https://api.siliconflow.cn https://baidufe.com https://www.baidufe.com https://img.shields.io;"
   },
   },
   "homepage_url": "https://www.fehelper.com"
   "homepage_url": "https://www.fehelper.com"
-}
-
-
-
-
+}

+ 11 - 9
apps/manifest.json

@@ -1,9 +1,9 @@
 {
 {
   "name": "FeHelper(前端助手)-Dev",
   "name": "FeHelper(前端助手)-Dev",
   "short_name": "FeHelper",
   "short_name": "FeHelper",
-  "version": "2025.05.2014",
+  "version": "2025.5.2014",
   "manifest_version": 3,
   "manifest_version": 3,
-  "description": "JSON自动格式化、手动格式化,支持排序、解码、下载等,更多功能可在配置页按需安装!",
+  "description": "FE助手:前端开发必备工具集,涵盖JSON格式化、代码美化与压缩、二维码生成、网页定制、便签笔记等数十种实用功能。界面现代、响应式设计,极致性能优化,国内可用,助力高效开发!",
   "icons": {
   "icons": {
     "16": "static/img/fe-16.png",
     "16": "static/img/fe-16.png",
     "48": "static/img/fe-48.png",
     "48": "static/img/fe-48.png",
@@ -15,9 +15,15 @@
     "default_popup": "popup/index.html"
     "default_popup": "popup/index.html"
   },
   },
   "background": {
   "background": {
-    "service_worker": "background/background.js",
+    "scripts": ["background/background.js"],
     "type": "module"
     "type": "module"
   },
   },
+  "browser_specific_settings": {
+      "gecko": {
+          "id": "[email protected]",
+          "strict_min_version": "99.0"
+      }
+  },
   "options_ui": {
   "options_ui": {
     "page": "options/index.html",
     "page": "options/index.html",
     "open_in_tab": true
     "open_in_tab": true
@@ -90,11 +96,7 @@
     }
     }
   ],
   ],
   "content_security_policy": {
   "content_security_policy": {
-    "extension_pages": "script-src 'self'; style-src 'self' 'unsafe-inline'; object-src 'self'"
+    "extension_pages": "script-src 'self' 'wasm-unsafe-eval'; worker-src 'self' blob:; style-src 'self' 'unsafe-inline'; object-src 'self'; connect-src 'self' blob: https://chrome.fehelper.com https://api.siliconflow.cn https://baidufe.com https://www.baidufe.com https://img.shields.io;"
   },
   },
-  "update_url": "https://clients2.google.com/service/update2/crx",
   "homepage_url": "https://www.fehelper.com"
   "homepage_url": "https://www.fehelper.com"
-}
-
-
-
+}

+ 10 - 8
apps/options/index.js

@@ -1205,15 +1205,18 @@ new Vue({
         // 加载远程推荐卡片配置
         // 加载远程推荐卡片配置
         async loadRemoteRecommendationCards() {
         async loadRemoteRecommendationCards() {
             try {
             try {
-                // 使用fetch获取远程配置
-                const response = await fetch('https://baidufe.com/fehelper/static/js/hotfix.json?v=' + Date.now());
-                if (!response.ok) {
-                    throw new Error(`获取远程配置失败: ${response.status}`);
+                // 通过background代理请求,解决CORS问题
+                const result = await new Promise((resolve) => {
+                    chrome.runtime.sendMessage({
+                        type: 'fh-dynamic-any-thing',
+                        thing: 'fetch-hotfix-json',
+                    }, resolve);
+                });
+                if (!result || !result.success) {
+                    throw new Error('获取远程配置失败: ' + (result && result.error ? result.error : '未知错误'));
                 }
                 }
-                
                 // 获取脚本内容
                 // 获取脚本内容
-                const scriptContent = await response.text();
-                
+                const scriptContent = result.content;
                 // 解析脚本内容,提取GlobalRecommendationCards变量
                 // 解析脚本内容,提取GlobalRecommendationCards变量
                 let remoteCards = null;
                 let remoteCards = null;
                 try {
                 try {
@@ -1221,7 +1224,6 @@ new Vue({
                 } catch (parseError) {
                 } catch (parseError) {
                     console.error('解析远程推荐卡片配置失败:', parseError);
                     console.error('解析远程推荐卡片配置失败:', parseError);
                 }
                 }
-                
                 // 如果成功解析到配置,则更新本地配置
                 // 如果成功解析到配置,则更新本地配置
                 if (remoteCards && Array.isArray(remoteCards) && remoteCards.length > 0) {
                 if (remoteCards && Array.isArray(remoteCards) && remoteCards.length > 0) {
                     this.recommendationCards = remoteCards;
                     this.recommendationCards = remoteCards;

+ 7 - 2
apps/popup/index.css

@@ -1,11 +1,16 @@
+html, body {
+    height: 100%;
+    margin: 0;
+    padding: 0;
+}
+
 .fe-whole-page {
 .fe-whole-page {
+    width: 152px;
     font-size: 14px;
     font-size: 14px;
     user-select: none;
     user-select: none;
     padding: 0;
     padding: 0;
     margin: 0;
     margin: 0;
-    width: 152px;
     position: relative;
     position: relative;
-    overflow: hidden;
 }
 }
 
 
 .fe-hide {
 .fe-hide {

+ 2 - 2
apps/popup/index.html

@@ -7,8 +7,8 @@
 		<script type="text/javascript" src="../static/vendor/evalCore.min.js"></script>
 		<script type="text/javascript" src="../static/vendor/evalCore.min.js"></script>
 		<script type="text/javascript" src="../static/vendor/vue/vue.js"></script>
 		<script type="text/javascript" src="../static/vendor/vue/vue.js"></script>
     </head>
     </head>
-    <body class="fe-whole-page">
-        <div id="pageContainer">
+    <body>
+        <div id="pageContainer" class="fe-whole-page">
             <div class="fe-function-title">FeHelper<span>({{manifest.version}})</span></div>
             <div class="fe-function-title">FeHelper<span>({{manifest.version}})</span></div>
             <ul class="fe-function-list">
             <ul class="fe-function-list">
                 <li v-for="tool in Object.keys(fhTools)" :class="'-x-' + tool" @click="runHelper(tool)" v-if="fhTools[tool].installed">
                 <li v-for="tool in Object.keys(fhTools)" :class="'-x-' + tool" @click="runHelper(tool)" v-if="fhTools[tool].installed">