浏览代码

修复json path识别的问题

zxlie 5 月之前
父节点
当前提交
12a86042d9
共有 7 个文件被更改,包括 233 次插入73 次删除
  1. 1 1
      apps/chrome.json
  2. 162 38
      apps/code-beautify/index.js
  3. 1 1
      apps/edge.json
  4. 1 1
      apps/firefox.json
  5. 60 24
      apps/json-format/format-lib.js
  6. 7 7
      apps/json-format/json-worker.js
  7. 1 1
      apps/manifest.json

+ 1 - 1
apps/chrome.json

@@ -1,7 +1,7 @@
 {
   "name": "FeHelper(前端助手)-Dev",
   "short_name": "FeHelper",
-  "version": "2025.6.1021",
+  "version": "2025.6.2023",
   "manifest_version": 3,
   "description": "JSON自动格式化、手动格式化,支持排序、解码、下载等,更多功能可在配置页按需安装!",
   "icons": {

+ 162 - 38
apps/code-beautify/index.js

@@ -41,9 +41,9 @@ new Vue({
     methods: {
         format: function () {
             if (!this.sourceContent.trim()) {
-                return alert('内容为空,不需要美化处理!');
+                return this.toast('内容为空,不需要美化处理!', 'warning');
             }else{
-                this.toast('格式化进行中...');
+                this.toast('格式化进行中...', 'info');
             }
 
             let beauty = (result) => {
@@ -55,51 +55,71 @@ new Vue({
                 this.$nextTick(() => {
                     Prism.highlightAll();
                     this.showCopyBtn = true;
-                    this.toast('格式化完成!');
+                    this.toast('格式化完成!', 'success');
                 });
             };
 
             switch (this.selectedType) {
                 case 'Javascript':
-                    let opts = {
-                        brace_style: "collapse",
-                        break_chained_methods: false,
-                        indent_char: " ",
-                        indent_scripts: "keep",
-                        indent_size: "4",
-                        keep_array_indentation: true,
-                        preserve_newlines: true,
-                        space_after_anon_function: true,
-                        space_before_conditional: true,
-                        unescape_strings: false,
-                        wrap_line_length: "120",
-                        "max_preserve_newlines": "5",
-                        "jslint_happy": false,
-                        "end_with_newline": false,
-                        "indent_inner_html": false,
-                        "comma_first": false,
-                        "e4x": false
-                    };
-                    beauty(js_beautify(this.sourceContent, opts));
+                    try {
+                        let opts = {
+                            brace_style: "collapse",
+                            break_chained_methods: false,
+                            indent_char: " ",
+                            indent_scripts: "keep",
+                            indent_size: "4",
+                            keep_array_indentation: true,
+                            preserve_newlines: true,
+                            space_after_anon_function: true,
+                            space_before_conditional: true,
+                            unescape_strings: false,
+                            wrap_line_length: "120",
+                            "max_preserve_newlines": "5",
+                            "jslint_happy": false,
+                            "end_with_newline": false,
+                            "indent_inner_html": false,
+                            "comma_first": false,
+                            "e4x": false
+                        };
+                        beauty(js_beautify(this.sourceContent, opts));
+                    } catch (error) {
+                        this.toast('JavaScript格式化失败,请检查代码语法!', 'error');
+                    }
                     break;
                 case 'CSS':
-                    css_beautify(this.sourceContent, {}, result => beauty(result));
+                    try {
+                        css_beautify(this.sourceContent, {}, result => beauty(result));
+                    } catch (error) {
+                        this.toast('CSS格式化失败,请检查代码语法!', 'error');
+                    }
                     break;
                 case 'HTML':
-                    beauty(html_beautify(this.sourceContent,{indent_size:4}));
+                    try {
+                        beauty(html_beautify(this.sourceContent,{indent_size:4}));
+                    } catch (error) {
+                        this.toast('HTML格式化失败,请检查代码语法!', 'error');
+                    }
                     break;
                 case 'SQL':
-                    beauty(vkbeautify.sql(this.sourceContent, 4));
+                    try {
+                        beauty(vkbeautify.sql(this.sourceContent, 4));
+                    } catch (error) {
+                        this.toast('SQL格式化失败,请检查代码语法!', 'error');
+                    }
                     break;
                 default:
-                    beauty(vkbeautify.xml(this.sourceContent));
+                    try {
+                        beauty(vkbeautify.xml(this.sourceContent));
+                    } catch (error) {
+                        this.toast('XML格式化失败,请检查代码语法!', 'error');
+                    }
             }
 
         },
 
         copy: function () {
 
-            let _copyToClipboard = function (text) {
+            let _copyToClipboard = (text) => {
                 let input = document.createElement('textarea');
                 input.style.position = 'fixed';
                 input.style.opacity = 0;
@@ -109,7 +129,7 @@ new Vue({
                 document.execCommand('Copy');
                 document.body.removeChild(input);
 
-                alert('复制成功,随处粘贴可用!')
+                this.toast('复制成功,随处粘贴可用!', 'success')
             };
 
             let txt = this.$refs.jfContentBox.textContent;
@@ -117,26 +137,129 @@ new Vue({
         },
 
         /**
-         * 自动消失的Alert弹窗
-         * @param content
+         * 自动消失的通知弹窗,仿Notification效果
+         * @param content 通知内容
+         * @param type 通知类型:success、error、warning、info(默认)
          */
-        toast (content) {
+        toast (content, type = 'info') {
             window.clearTimeout(window.feHelperAlertMsgTid);
             let elAlertMsg = document.querySelector("#fehelper_alertmsg");
+            
+            // 根据类型配置样式
+            const typeConfig = {
+                info: {
+                    background: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',
+                    borderColor: '#4ade80',
+                    icon: 'ℹ'
+                },
+                success: {
+                    background: 'linear-gradient(135deg, #4ade80 0%, #16a34a 100%)',
+                    borderColor: '#22c55e',
+                    icon: '✓'
+                },
+                error: {
+                    background: 'linear-gradient(135deg, #ef4444 0%, #dc2626 100%)',
+                    borderColor: '#f87171',
+                    icon: '✕'
+                },
+                warning: {
+                    background: 'linear-gradient(135deg, #f59e0b 0%, #d97706 100%)',
+                    borderColor: '#fbbf24',
+                    icon: '⚠'
+                }
+            };
+            
+            const config = typeConfig[type] || typeConfig.info;
+            
             if (!elAlertMsg) {
                 let elWrapper = document.createElement('div');
-                elWrapper.innerHTML = '<div id="fehelper_alertmsg" style="position:fixed;bottom:5px;left:5px;z-index:1000000">' +
-                    '<p style="background:#000;display:inline-block;color:#fff;text-align:center;' +
-                    'padding:10px 10px;margin:0 auto;font-size:14px;border-radius:4px;">' + content + '</p></div>';
-                elAlertMsg = elWrapper.childNodes[0];
+                elWrapper.innerHTML = `
+                    <div id="fehelper_alertmsg" style="
+                        position: fixed;
+                        top: 20px;
+                        right: 20px;
+                        z-index: 10000000;
+                        min-width: 300px;
+                        max-width: 400px;
+                        opacity: 0;
+                        transform: translateX(100%);
+                        transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
+                    ">
+                        <div class="toast-inner" style="
+                            background: ${config.background};
+                            color: #fff;
+                            padding: 16px 20px;
+                            border-radius: 8px;
+                            box-shadow: 0 10px 25px rgba(0, 0, 0, 0.2), 0 4px 10px rgba(0, 0, 0, 0.1);
+                            font-size: 14px;
+                            font-weight: 500;
+                            line-height: 1.4;
+                            position: relative;
+                            overflow: hidden;
+                        ">
+                            <div class="toast-border" style="
+                                position: absolute;
+                                top: 0;
+                                left: 0;
+                                width: 4px;
+                                height: 100%;
+                                background: ${config.borderColor};
+                            "></div>
+                            <div style="
+                                display: flex;
+                                align-items: center;
+                                gap: 12px;
+                            ">
+                                <div class="toast-icon" style="
+                                    flex-shrink: 0;
+                                    width: 20px;
+                                    height: 20px;
+                                    background: rgba(255, 255, 255, 0.2);
+                                    border-radius: 50%;
+                                    display: flex;
+                                    align-items: center;
+                                    justify-content: center;
+                                    font-size: 12px;
+                                ">${config.icon}</div>
+                                <div class="toast-content" style="flex: 1;">${content}</div>
+                            </div>
+                        </div>
+                    </div>
+                `;
+                elAlertMsg = elWrapper.childNodes[1]; // 第一个是文本节点,第二个才是div
                 document.body.appendChild(elAlertMsg);
+                
+                // 触发动画
+                setTimeout(() => {
+                    elAlertMsg.style.opacity = '1';
+                    elAlertMsg.style.transform = 'translateX(0)';
+                }, 10);
             } else {
-                elAlertMsg.querySelector('p').innerHTML = content;
+                // 更新现有通知的内容和样式
+                const toastInner = elAlertMsg.querySelector('.toast-inner');
+                const toastBorder = elAlertMsg.querySelector('.toast-border');
+                const toastIcon = elAlertMsg.querySelector('.toast-icon');
+                const toastContent = elAlertMsg.querySelector('.toast-content');
+                
+                toastInner.style.background = config.background;
+                toastBorder.style.background = config.borderColor;
+                toastIcon.innerHTML = config.icon;
+                toastContent.innerHTML = content;
+                
                 elAlertMsg.style.display = 'block';
+                elAlertMsg.style.opacity = '1';
+                elAlertMsg.style.transform = 'translateX(0)';
             }
 
             window.feHelperAlertMsgTid = window.setTimeout(function () {
-                elAlertMsg.style.display = 'none';
+                // 淡出动画
+                elAlertMsg.style.opacity = '0';
+                elAlertMsg.style.transform = 'translateX(100%)';
+                
+                // 动画完成后隐藏
+                setTimeout(() => {
+                    elAlertMsg.style.display = 'none';
+                }, 300);
             }, 3000);
         },
 
@@ -154,6 +277,7 @@ new Vue({
             
             this.sourceContent = this.examples[type];
             this.selectedType = typeMap[type];
+            this.toast(`已加载${typeMap[type]}示例代码`, 'info');
             this.$nextTick(() => {
                 this.format();
             });

+ 1 - 1
apps/edge.json

@@ -1,7 +1,7 @@
 {
   "name": "FeHelper(前端助手)-Dev",
   "short_name": "FeHelper",
-  "version": "2025.6.1020",
+  "version": "2025.6.2023",
   "manifest_version": 3,
   "description": "JSON自动格式化、手动格式化,支持排序、解码、下载等,更多功能可在配置页按需安装!",
   "icons": {

+ 1 - 1
apps/firefox.json

@@ -1,7 +1,7 @@
 {
   "name": "FeHelper(前端助手)-Dev",
   "short_name": "FeHelper",
-  "version": "2025.5.2014",
+  "version": "2025.6.2023",
   "manifest_version": 3,
   "description": "FE助手:前端开发必备工具集,涵盖JSON格式化、代码美化与压缩、二维码生成、网页定制、便签笔记等数十种实用功能。界面现代、响应式设计,极致性能优化,国内可用,助力高效开发!",
   "icons": {

+ 60 - 24
apps/json-format/format-lib.js

@@ -230,39 +230,80 @@ window.Formatter = (function () {
     // 添加json路径
     let _showJsonPath = function (curEl) {
         let keys = [];
-        do {
-            if (curEl.hasClass('item-block')) {
-                if (!curEl.hasClass('rootItem')) {
-                    keys.unshift('[' + curEl.prevAll('.item').length + ']');
-                } else {
-                    break;
+        let current = curEl;
+        
+        // 处理当前节点
+        if (current.hasClass('item') && !current.hasClass('rootItem')) {
+            if (current.hasClass('item-array-element')) {
+                // 这是数组元素,使用data-array-index属性
+                let index = current.attr('data-array-index');
+                if (index !== undefined) {
+                    keys.unshift('[' + index + ']');
                 }
             } else {
-                keys.unshift(curEl.find('>.key').text());
+                // 这是对象属性,获取key
+                let keyText = current.find('>.key').text();
+                if (keyText) {
+                    keys.unshift(keyText);
+                }
             }
-
-            if (curEl.parent().hasClass('rootItem') || curEl.parent().parent().hasClass('rootItem')) {
-                break;
+        }
+        
+        // 向上遍历所有祖先节点
+        current.parents('.item').each(function() {
+            let $this = $(this);
+            
+            // 跳过根节点
+            if ($this.hasClass('rootItem')) {
+                return false; // 终止遍历
             }
+            
+            if ($this.hasClass('item-array-element')) {
+                // 这是数组元素,使用data-array-index属性
+                let index = $this.attr('data-array-index');
+                if (index !== undefined) {
+                    keys.unshift('[' + index + ']');
+                }
+            } else if ($this.hasClass('item-object') || $this.hasClass('item-array')) {
+                // 这是容器节点,寻找它的key
+                let $container = $this.parent().parent(); // 跳过 .kv-list
+                if ($container.length && !$container.hasClass('rootItem')) {
+                    if ($container.hasClass('item-array-element')) {
+                        // 容器本身是数组元素
+                        let index = $container.attr('data-array-index');
+                        if (index !== undefined) {
+                            keys.unshift('[' + index + ']');
+                        }
+                    } else {
+                        // 容器是对象属性
+                        let keyText = $container.find('>.key').text();
+                        if (keyText) {
+                            keys.unshift(keyText);
+                        }
+                    }
+                }
+            } else {
+                // 普通item节点,获取key
+                let keyText = $this.find('>.key').text();
+                if (keyText) {
+                    keys.unshift(keyText);
+                }
+            }
+        });
 
-            curEl = curEl.parent().parent();
-
-        } while (curEl.length && !curEl.hasClass('rootItem'));
-
-        // 过滤掉空值和无效的key,避免产生多余的点号
+        // 过滤掉空值和无效的key
         let validKeys = keys.filter(key => key && key.trim() !== '');
         
-        // 构建路径:正确处理对象属性和数组索引的连接
+        // 构建路径
         let path = '';
         for (let i = 0; i < validKeys.length; i++) {
             let key = validKeys[i];
             if (key.startsWith('[') && key.endsWith(']')) {
-                // 数组索引,直接拼接(前面永远不需要点号)
+                // 数组索引,直接拼接
                 path += key;
             } else {
                 // 对象属性
                 if (i > 0) {
-                    // 对象属性前面需要点号(数组索引后面的属性也需要点号)
                     path += '.';
                 }
                 path += key;
@@ -738,9 +779,4 @@ window.Formatter = (function () {
         format: format,
         formatSync: formatSync
     }
-})();
-
-
-
-
-
+})();

+ 7 - 7
apps/json-format/json-worker.js

@@ -240,12 +240,12 @@ function createNode(value) {
                 '<span class="expand"></span>' +
                 '<span class="brace">[</span>' +
                 '<span class="ellipsis"></span>' +
-                '<div class="kv-list">';
+                '<div class="kv-list item-array-container">';
                 
             this.value.forEach((item, index) => {
                 let childNode = createNode(item);
                 
-                html += '<div class="item item-block">';
+                html += '<div class="item item-block item-array-element" data-array-index="' + index + '">';
                 
                 // 如果数组元素是对象或数组,在前面添加展开按钮
                 if (childNode.type === 'object' || childNode.type === 'array') {
@@ -335,12 +335,12 @@ function createNode(value) {
             let html = '<span class="brace">[</span>' +
                 '<span class="expand"></span>' +
                 '<span class="ellipsis"></span>' +
-                '<div class="kv-list">';
+                '<div class="kv-list item-array-container">';
                 
             this.value.forEach((item, index) => {
                 let childNode = createNode(item);
                 
-                html += '<div class="item item-block">';
+                html += '<div class="item item-block item-array-element" data-array-index="' + index + '">';
                 
                 // 如果数组元素是对象或数组,在前面添加展开按钮
                 if (childNode.type === 'object' || childNode.type === 'array') {
@@ -404,14 +404,14 @@ function createNode(value) {
             
             let html = '<span class="brace">[</span>' +
                 '<span class="ellipsis"></span>' +
-                '<div class="kv-list">';
+                '<div class="kv-list item-array-container">';
                 
             this.value.forEach((item, index) => {
                 let childNode = createNode(item);
                 
-                html += '<div class="item item-block">';
+                html += '<div class="item item-block item-array-element" data-array-index="' + index + '">';
                 
-                // 如果数组元素是对象或数组,在前面添加展开按钮
+                // 确保所有类型的数组元素都能正确处理
                 if (childNode.type === 'object' || childNode.type === 'array') {
                     html += '<span class="expand"></span>';
                     html += childNode.getInlineHTMLWithoutExpand();

+ 1 - 1
apps/manifest.json

@@ -1,7 +1,7 @@
 {
   "name": "FeHelper(前端助手)-Dev",
   "short_name": "FeHelper",
-  "version": "2025.6.1021",
+  "version": "2025.6.2023",
   "manifest_version": 3,
   "description": "JSON自动格式化、手动格式化,支持排序、解码、下载等,更多功能可在配置页按需安装!",
   "icons": {