
// 简单 JSON.stringify 兼容
if (typeof JSON === "undefined") {
    JSON = {};
}

var inputPath1 = '${inputPath1}';
// 载入XMP扩展支持（全局调用一次即可）
if (!ExternalObject.AdobeXMPScript) {
    ExternalObject.AdobeXMPScript = new ExternalObject('lib:AdobeXMPScript');
}
JSON.stringify = function (obj, replacer, space) {
    if (typeof space === "number") {
        space = new Array(space + 1).join(" ");
    }
    function format(value, indent) {
        var type = typeof value;
        if (value === null) return "null";
        if (type === "string") return '"' + value + '"';
        if (type === "number" || type === "boolean") return String(value);
        if (type === "object") {
            var isArray = (value instanceof Array);
            var items = [];
            var pad = indent + (space || "");
            for (var key in value) {
                if (value.hasOwnProperty(key)) {
                    var val = format(value[key], pad);
                    if (!isArray) {
                        val = '"' + key + '": ' + val;
                    }
                    items.push(val);
                }
            }
            if (isArray) {
                return "[\n" + pad + items.join(",\n" + pad) + "\n" + indent + "]";
            } else {
                return "{\n" + pad + items.join(",\n" + pad) + "\n" + indent + "}";
            }
        }
        return "null";
    }
    return format(obj, "");
};




// 递归遍历所有图层（包括图层组）
function processLayers(layers, resultArray) {
    for (var i = 0; i < layers.length; i++) {
        var layer = layers[i];
        app.activeDocument.activeLayer = layer;

        var info = {};

        // 先保存锁定状态
        var wasLocked = layer.allLocked;
        if (wasLocked) {
            try {
                layer.allLocked = false; // 临时解锁
            } catch (e) {
                // 有些锁可能无法解除，忽略异常
            }
        }
        info["图层名"] = layer.name;
        info["类型"] = getLayerKindName(layer.kind);
        if (layer.visible === true) {
            info["可见"] = true;
        }

        if (layer.allLocked === true) {
            info["锁定"] = true;
        }

        // 文字图层特殊信息
        if (layer.kind === LayerKind.TEXT) {
            var t = layer.textItem;
            try {
                info["文字内容"] = t.contents;
            } catch (e) {

            }
            try {
                var font = t.font;
                var fontMap = {
                    "SimSun": "宋体",
                    "SimHei": "黑体",
                    "FangSong_GB2312": "仿宋",
                    "KaiTi_GB2312": "楷体",
                    "MicrosoftYaHei": "微软雅黑",
                    "MicrosoftJhengHei": "微软正黑体",
                    "NSimSun": "新宋体",
                    "PMingLiU": "新细明体",
                    "MingLiU": "细明体",
                    "DFKai-SB": "标楷体",
                    "STKaiti": "华文楷体",
                    "STSong": "华文宋体",
                    "STHeiti": "华文黑体",
                    "STFangsong": "华文仿宋",
                    "STXihei": "华文细黑",
                    "STZhongsong": "华文中宋",
                    "STXinwei": "华文新魏",
                    "STLiti": "华文隶书",
                    "STHupo": "华文琥珀",
                    "STCaiyun": "华文彩云",
                    "STXingkai": "华文行楷",
                    "Arial": "Arial（英文字体）",
                    "TimesNewRomanPSMT": "Times New Roman",
                    "CourierNewPSMT": "Courier New",
                    "Georgia": "Georgia",
                    "Tahoma": "Tahoma",
                    "Verdana": "Verdana"
                };

                if (fontMap.hasOwnProperty(font)) {
                    info["字体"] = fontMap[font];
                } else {
                    info["字体"] = font;
                }
            } catch (e) {
                info["字体"] = "未知";
            }

            try {
                info["字号"] = t.size.toString(); }// 修正这里
            catch (e) {
            }

            try {
                info["颜色"] = getSolidColorHex(t.color);}
            catch (e) {

            }
            try {
                info["字距"] = t.tracking;}
            catch (e) {

            }
            try {
                if ('fauxItalic' in t && t.fauxItalic === true) {
                    info["仿斜体"] = true;
                }
            } catch (e) {}

            try {
                if ('fauxBold' in t && t.fauxBold === true) {
                    info["仿粗体"] = true;
                }
            } catch (e) {}

            var transformProps = getWarpTextProps();
            if (
                transformProps &&
                typeof transformProps === "object" &&
                (function(obj) {
                    for (var key in obj) {
                        if (obj.hasOwnProperty(key)) {
                            return true;  // 有至少一个属性，不为空
                        }
                    }
                    return false;  // 没有属性，为空
                })(transformProps)
            ) {
                info["变形"] = transformProps;
            }

        }

        // 读取图层样式
        var styles = getLayerStyles(layer);
        if (styles && !isEmptyObject(styles)) {
            info["图层样式"] = styles;
        }

        var filterInfo = detectFilters(layer.name);
        if (filterInfo && !isEmptyObject(filterInfo)) {
            info["滤镜信息"] = filterInfo;
        }
        //蒙版
        //蒙版操作 执行动作 创建 图层蒙版、 矢量蒙版、 剪切蒙版
        // 🔹 蒙版
        var maskInfo = getMaskInfo(layer);
        if (maskInfo && !isEmptyObject(maskInfo)) {
            info["蒙版类型"] = maskInfo;
        }

        // 选中当前图层为智能对象后
        var soLayer = app.activeDocument.activeLayer;

        // 确保它是智能对象
        // if (soLayer.kind == LayerKind.SMARTOBJECT) {
        //     // 打开智能对象
        //     var openedDoc = soLayer.smartObject.open();

        //     // 现在 activeDocument 是智能对象内容，可以像普通文档一样读取图层
        //     var internalLayer = openedDoc.artLayers[0]; // 你可以遍历所有图层
        //     var styles = getLayerStyles(internalLayer);
        //     alert(JSON.stringify(styles));

        //     // 读取完后关闭文档（不保存）
        //     openedDoc.close(SaveOptions.DONOTSAVECHANGES);
        // }



        // 如果是图层组，递归遍历组内图层
        if (layer.typename === "LayerSet") {
            info["子图层"] = [];
            processLayers(layer.layers, info["子图层"]);
        }

        resultArray.push(info);

        // 还原锁定状态
        if (wasLocked) {
            try {
                layer.allLocked = true;
            } catch (e) {}
        }
    }
}
function unlockLayer(layer) {
    // 如果图层被完全锁定
    if (layer.allLocked) {
        layer.allLocked = false;
    }
    // 如果是背景图层（通常无法直接操作）
    if (layer.isBackgroundLayer) {
        // 将背景图层转换为普通图层
        layer.name = "解锁背景图层";
        layer.isBackgroundLayer = false;
    }

    // 分别检查并解锁其他锁定项
    if (layer.pixelsLocked) layer.pixelsLocked = false;
    if (layer.positionLocked) layer.positionLocked = false;
    if (layer.transparentPixelsLocked) layer.transparentPixelsLocked = false;
}


function openSmartObjectDocument(layer) {
    try {
        app.activeDocument.activeLayer = layer; // 先激活图层
        var idplacedLayerEditContents = stringIDToTypeID("placedLayerEditContents");
        var desc = new ActionDescriptor();
        var ref = new ActionReference();
        ref.putIdentifier(charIDToTypeID("Lyr "), layer.id);
        desc.putReference(charIDToTypeID("null"), ref);
        executeAction(idplacedLayerEditContents, desc, DialogModes.NO);

        return app.activeDocument; // 返回智能对象内部文档
    } catch (e) {
        $.writeln("打开智能对象内部文档失败：" + e.message);
        return null;
    }
}

function openSmartObjectDocumentEvenIfLocked(layer) {
    var wasLocked = layer.allLocked;
    try {
        if (wasLocked) {
            try { layer.allLocked = false; } catch(e) {}
            try { layer.pixelsLocked = false; } catch(e) {}
            try { layer.positionLocked = false; } catch(e) {}
            try { layer.transparentPixelsLocked = false; } catch(e) {}
        }

        var idPlacedLayerEditContents = stringIDToTypeID("placedLayerEditContents");
        var desc = new ActionDescriptor();
        var ref = new ActionReference();
        ref.putIdentifier(charIDToTypeID("Lyr "), layer.id);
        desc.putReference(charIDToTypeID("null"), ref);
        executeAction(idPlacedLayerEditContents, desc, DialogModes.NO);

        return app.activeDocument;
    } catch (e) {
        // alert("打开智能对象内部文档失败：" + e.message);
        return null;
    } finally {
        if (wasLocked) {
            try { layer.allLocked = true; } catch(e) {}
        }
    }
}



function getSmartObjectType(layer) {
    try {
        var ref = new ActionReference();
        ref.putIdentifier(charIDToTypeID("Lyr "), layer.id);
        var desc = executeActionGet(ref);
        if (desc.hasKey(stringIDToTypeID("smartObject"))) {
            var smObj = desc.getObjectValue(stringIDToTypeID("smartObject"));
            if (smObj.hasKey(stringIDToTypeID("linked"))) {
                var isLinked = smObj.getBoolean(stringIDToTypeID("linked"));
                return isLinked ? "链接智能对象" : "嵌入智能对象";
            }
        }
    } catch (e) {
        return "未知类型";
    }
    return "未知类型";
}

function processFile(path) {
    var fileRef = new File(path);
    if (!fileRef.exists) {
        // alert("PSD文件不存在: " + path);
        throw new Error("PSD文件不存在");
    }


    var doc = app.open(fileRef);

    var result = {};

    result["颜色模式"] = getColorModeName(doc.mode);
    result["颜色深度"] = getBitsPerChannelLabel(doc.bitsPerChannel);
    result["图像宽度"] = doc.width.as('px') + " 像素";
    result["图像高度"] = doc.height.as('px') + " 像素";
    result["画布宽度"] = doc.width.as('px') + " 像素";
    result["画布高度"] = doc.height.as('px') + " 像素";
    result["分辨率"] = doc.resolution + " dpi";

    // 使用递归遍历所有顶层图层和图层组
    result["图层信息"] = [];
    processLayers(doc.layers, result["图层信息"]);

    // 获取智能对象图层数（递归计算）
    // result["智能对象图层数"] = countSmartObjectsRecursive(doc.layers);

    // 写入 JSON 文件
    var baseName = fileRef.name.replace(/\.psd$/i, "");
    var jsonFilePath = fileRef.path + "/" + baseName + ".json";
    var jsonFile = new File(jsonFilePath);

    if (jsonFile.open("w")) {
        jsonFile.encoding = "UTF8";
        jsonFile.write(JSON.stringify(result, null, 2));
        jsonFile.close();
        // alert("JSON 文件已生成: " + jsonFilePath);
    } else {
        // alert("无法打开文件进行写入");
    }

    doc.close(SaveOptions.DONOTSAVECHANGES);
}

// 递归计算智能对象图层数
function countSmartObjectsRecursive(layers) {
    var count = 0;
    for (var i = 0; i < layers.length; i++) {
        var layer = layers[i];
        if (layer.kind === LayerKind.SMARTOBJECT) count++;
        if (layer.typename === "LayerSet") {
            count += countSmartObjectsRecursive(layer.layers);
        }
    }
    return count;
}

// 运行两个 PSD 的处理
processFile(inputPath1);


//////////////////////////////////////////////

/////////////////////////////////////////////

// 辅助函数 - 颜色模式
function getColorModeName(mode) {
    switch (mode) {
        case DocumentMode.RGB: return "RGB";
        case DocumentMode.CMYK: return "CMYK";
        case DocumentMode.GRAYSCALE: return "灰度";
        case DocumentMode.BITMAP: return "位图";
        case DocumentMode.INDEXEDCOLOR: return "索引颜色";
        default: return "未知";
    }
}
function getBitsPerChannelLabel(bits) {
    switch (bits) {
        case BitsPerChannelType.ONE: return "1 位/通道";
        case BitsPerChannelType.EIGHT: return "8 位/通道";
        case BitsPerChannelType.SIXTEEN: return "16 位/通道";
        case BitsPerChannelType.THIRTYTWO: return "32 位/通道";
        default: return "未知";
    }
}

// 辅助函数 - 图层类型名
function getLayerKindName(kind) {
    switch (kind) {
        case LayerKind.NORMAL: return "普通图层";
        case LayerKind.TEXT: return "文字图层";
        case LayerKind.SMARTOBJECT: return "智能对象图层";
        case LayerKind.SOLIDFILL: return "纯色填充图层";
        case LayerKind.GRADIENTFILL: return "渐变填充图层";
        case LayerKind.PATTERNFILL: return "图案填充图层";
        case LayerKind.BRIGHTNESSCONTRAST: return "亮度/对比度调整层";
        case LayerKind.LEVELS: return "色阶调整层";
        case LayerKind.CURVES: return "曲线调整层";
        case LayerKind.EXPOSURE: return "曝光度调整层";
        case LayerKind.VIBRANCE: return "自然饱和度调整层";
        case LayerKind.HUESATURATION: return "色相/饱和度调整层";
        case LayerKind.COLORBALANCE: return "色彩平衡调整层";
        case LayerKind.BLACKANDWHITE: return "黑白调整层";
        case LayerKind.PHOTOFILTER: return "照片滤镜调整层";
        case LayerKind.CHANNELMIXER: return "通道混合器调整层";
        case LayerKind.COLORLOOKUP: return "颜色查找调整层";
        case LayerKind.INVERSION: return "反相调整层";
        case LayerKind.POSTERIZE: return "色调分离调整层";
        case LayerKind.THRESHOLD: return "阈值调整层";
        case LayerKind.GRADIENTMAP: return "渐变映射调整层";
        case LayerKind.SELECTIVECOLOR: return "可选颜色调整层";
        default: return "未知类型";
    }
}

// 读取颜色为HEX
function getSolidColorHex(color) {
    if (!color) return null;
    if (color.typename === "SolidColor") {
        if (color.rgb) {
            var r = Math.round(color.rgb.red);
            var g = Math.round(color.rgb.green);
            var b = Math.round(color.rgb.blue);
            return "#" + toHex(r) + toHex(g) + toHex(b);
        }
    }
    return null;
}
function toHex(c) {
    var h = c.toString(16);
    return h.length == 1 ? "0" + h : h;
}

// 统计智能对象图层数量
function countSmartObjects(doc) {
    var count = 0;
    for (var i = 0; i < doc.artLayers.length; i++) {
        if (doc.artLayers[i].kind === LayerKind.SMARTOBJECT) {
            count++;
        }
    }
    return count;
}

function getWarpTextProps() {
    var ref = new ActionReference();
    ref.putEnumerated(charIDToTypeID("Lyr "), charIDToTypeID("Ordn"), charIDToTypeID("Trgt"));
    var desc = executeActionGet(ref);

    if (!desc.hasKey(stringIDToTypeID("textKey"))) return null;

    var textDesc = desc.getObjectValue(stringIDToTypeID("textKey"));
    if (!textDesc.hasKey(stringIDToTypeID("warp"))) return null;

    var warpDesc = textDesc.getObjectValue(stringIDToTypeID("warp"));

    // 样式汉化映射
    var warpStyleMap = {
        "warpNone":"无","warpArc":"弧形","warpArcLower":"下弧形","warpArcUpper":"上弧形",
        "warpArch":"拱形","warpBulge":"凸出","warpShellLower":"下壳形","warpShellUpper":"上壳形",
        "warpFlag":"旗帜","warpWave":"波浪","warpFish":"鱼形","warpRise":"上升",
        "warpFisheye":"鱼眼","warpInflate":"膨胀","warpSqueeze":"挤压","warpTwist":"扭曲"
    };
    var warpStyleEn = warpDesc.hasKey(stringIDToTypeID("warpStyle")) ? typeIDToStringID(warpDesc.getEnumerationValue(stringIDToTypeID("warpStyle"))) : "warpNone";
    var warpStyleCn = warpStyleMap[warpStyleEn] || warpStyleEn;

    var warpBend = warpDesc.hasKey(stringIDToTypeID("warpValue")) ? warpDesc.getDouble(stringIDToTypeID("warpValue")) + "%" : "0%";

    var horizontalKeys = ["horizontalDistortion", "horizontalDistortionValue","warpPerspective"];
    var warpHorizontal = "0%";
    for (var i=0;i<horizontalKeys.length;i++) {
        if (warpDesc.hasKey(stringIDToTypeID(horizontalKeys[i]))) {
            warpHorizontal = warpDesc.getDouble(stringIDToTypeID(horizontalKeys[i])) + "%";
            break;
        }
    }

    var verticalKeys = ["verticalDistortion", "verticalDistortionValue","warpPerspectiveOther"];
    var warpVertical = "0%";
    for (var i=0;i<verticalKeys.length;i++) {
        if (warpDesc.hasKey(stringIDToTypeID(verticalKeys[i]))) {
            warpVertical = warpDesc.getDouble(stringIDToTypeID(verticalKeys[i])) + "%";
            break;
        }
    }

    // 如果都是默认值，说明没有实际变形，返回 null
    if (warpStyleCn === "无" && warpBend === "0%" && warpHorizontal === "0%" && warpVertical === "0%") {
        return null;
    }

    return {
        "样式": warpStyleCn,
        "弯曲": warpBend,
        "水平扭曲": warpHorizontal,
        "垂直扭曲": warpVertical
    };
}



function dumpDescriptor(desc, indent) {
    indent = indent || "";
    for (var i = 0; i < desc.count; i++) {
        var key = desc.getKey(i);
        var type = desc.getType(key);
        var keyName = typeIDToStringID(key);
        $.writeln(indent + keyName + " (" + type + ")");
        try {
            if (type == DescValueType.OBJECTTYPE) {
                dumpDescriptor(desc.getObjectValue(key), indent + "  ");
            } else if (type == DescValueType.ENUMERATEDTYPE) {
                $.writeln(indent + "  value: " + typeIDToStringID(desc.getEnumerationValue(key)));
            } else if (type == DescValueType.BOOLEANTYPE) {
                $.writeln(indent + "  value: " + desc.getBoolean(key));
            } else if (type == DescValueType.DOUBLETYPE) {
                $.writeln(indent + "  value: " + desc.getDouble(key));
            } else if (type == DescValueType.UNITDOUBLE) {
                $.writeln(indent + "  value: " + desc.getUnitDoubleValue(key));
            } else if (type == DescValueType.STRINGTYPE) {
                $.writeln(indent + "  value: " + desc.getString(key));
            } else if (type == DescValueType.INTEGERTYPE) {
                $.writeln(indent + "  value: " + desc.getInteger(key));
            }
        } catch(e) {
            $.writeln(indent + "  (无法读取: " + e + ")");
        }
    }
}


function dumpDescriptor(desc, indent) {
    indent = indent || "";
    for (var i = 0; i < desc.count; i++) {
        var key = desc.getKey(i);
        var type = desc.getType(key);
        var keyName = typeIDToStringID(key);
        $.writeln(indent + keyName + " (" + type + ")");
        try {
            if (type == DescValueType.OBJECTTYPE) {
                dumpDescriptor(desc.getObjectValue(key), indent + "  ");
            } else if (type == DescValueType.ENUMERATEDTYPE) {
                $.writeln(indent + "  value: " + typeIDToStringID(desc.getEnumerationValue(key)));
            } else if (type == DescValueType.BOOLEANTYPE) {
                $.writeln(indent + "  value: " + desc.getBoolean(key));
            } else if (type == DescValueType.DOUBLETYPE) {
                $.writeln(indent + "  value: " + desc.getDouble(key));
            } else if (type == DescValueType.UNITDOUBLE) {
                $.writeln(indent + "  value: " + desc.getUnitDoubleValue(key));
            } else if (type == DescValueType.STRINGTYPE) {
                $.writeln(indent + "  value: " + desc.getString(key));
            } else if (type == DescValueType.INTEGERTYPE) {
                $.writeln(indent + "  value: " + desc.getInteger(key));
            }
        } catch(e) {
            $.writeln(indent + "  (无法读取: " + e + ")");
        }
    }
}




function getLayerStyles(layer) {
    var styles = {};

    // ---- 激活图层 ----
    app.activeDocument.activeLayer = layer;


    // ---- 获取 ActionDescriptor ----
    var desc;
    try {
        // 尝试 CC/2025 方法
        var ref = new ActionReference();
        if (layer.id !== undefined) {
            ref.putIdentifier(charIDToTypeID("Lyr "), layer.id);
        } else {
            throw "CS6 fallback";
        }
        desc = executeActionGet(ref);
    } catch (e) {
        // CS6 fallback
        var ref2 = new ActionReference();
        ref2.putEnumerated(charIDToTypeID("Lyr "), charIDToTypeID("Ordn"), charIDToTypeID("Trgt"));
        desc = executeActionGet(ref2);
    }

    // ---- 判断 layerEffects 是否存在 ----
    if (!desc.hasKey(stringIDToTypeID("layerEffects"))) {
        $.writeln("图层 " + layer.name + " 没有 layerEffects");
        return styles; // 空对象
    }
    try {
        var effects = desc.getObjectValue(stringIDToTypeID("layerEffects"));
// 用法：
        if (effects.hasKey(stringIDToTypeID("bevelEmboss"))) {
            var bevel = effects.getObjectValue(stringIDToTypeID("bevelEmboss"));
            dumpDescriptor(bevel, ">> ");
        }

        // ---- 描边 ----
        if (effects.hasKey(stringIDToTypeID("frameFX"))) {
            var frameFX = effects.getObjectValue(stringIDToTypeID("frameFX"));
            if (frameFX.hasKey(stringIDToTypeID("enabled"))) {
                var enabled = frameFX.getBoolean(stringIDToTypeID("enabled"));
                if (enabled) {
                    if (frameFX.hasKey(stringIDToTypeID("size"))) {
                        styles["描边_大小"] = frameFX.getUnitDoubleValue(stringIDToTypeID("size")) + " 像素";
                    }
                    if (frameFX.hasKey(stringIDToTypeID("color"))) {
                        styles["描边_颜色"] = colorDescToHex(frameFX.getObjectValue(stringIDToTypeID("color")));
                    }
                    if (frameFX.hasKey(stringIDToTypeID("style"))) {
                        var posEnum = frameFX.getEnumerationValue(stringIDToTypeID("style"));
                        var posStringID = typeIDToStringID(posEnum);
                        styles["描边_位置"] = getStrokePositionName(posStringID);
                    } else {
                        styles["描边_位置"] = "未知";
                    }
                    if (frameFX.hasKey(stringIDToTypeID("opacity"))) {
                        styles["描边_不透明度"] = Math.round(frameFX.getUnitDoubleValue(stringIDToTypeID("opacity"))) + "%";
                    }
                    if (frameFX.hasKey(stringIDToTypeID("mode"))) {
                        styles["描边_混合模式"] = getBlendModeName(frameFX.getEnumerationValue(stringIDToTypeID("mode")));
                    }
                }
            }
        }

        // ---- 内发光 ----
        if (effects.hasKey(stringIDToTypeID("innerGlow"))) {
            var innerGlow = effects.getObjectValue(stringIDToTypeID("innerGlow"));
            if (innerGlow.hasKey(stringIDToTypeID("enabled"))) {
                var enabled = innerGlow.getBoolean(stringIDToTypeID("enabled"));
                if (enabled) {
                    if (innerGlow.hasKey(stringIDToTypeID("opacity"))) {
                        styles["内发光_不透明度"] = Math.round(innerGlow.getUnitDoubleValue(stringIDToTypeID("opacity"))) + "%";
                    }
                    if (innerGlow.hasKey(stringIDToTypeID("color"))) {
                        styles["内发光_颜色"] = colorDescToHex(innerGlow.getObjectValue(stringIDToTypeID("color")));
                    }
                    if (innerGlow.hasKey(stringIDToTypeID("blur"))) {
                        styles["内发光_大小"] = innerGlow.getUnitDoubleValue(stringIDToTypeID("blur")) + " 像素";
                    }
                    if (innerGlow.hasKey(stringIDToTypeID("mode"))) {
                        var modeID = innerGlow.getEnumerationValue(stringIDToTypeID("mode"));
                        styles["内发光_混合模式"] = getBlendModeName(modeID);
                    }
                    if (innerGlow.hasKey(stringIDToTypeID("source"))) {
                        var source = innerGlow.getEnumerationValue(stringIDToTypeID("source"));
                        styles["内发光_来源"] = getInnerGlowSourceName(source);
                    }
                }
            }
        }

        // ---- 斜面和浮雕 ----
        if (effects.hasKey(stringIDToTypeID("bevelEmboss"))) {
            var bevel = effects.getObjectValue(stringIDToTypeID("bevelEmboss"));
            if (bevel.hasKey(stringIDToTypeID("enabled"))) {
                var enabled = bevel.getBoolean(stringIDToTypeID("enabled"));
                if (enabled) {
                    var styleID = null;
                    if (bevel.hasKey(stringIDToTypeID("style"))) styleID = bevel.getEnumerationValue(stringIDToTypeID("style"));
                    else if (bevel.hasKey(stringIDToTypeID("bevelStyle"))) styleID = bevel.getEnumerationValue(stringIDToTypeID("bevelStyle"));


                    else if (bevel.hasKey(stringIDToTypeID("bevelTechnique"))) techniqueID = bevel.getEnumerationValue(stringIDToTypeID("bevelTechnique"));

                    if (styleID) styles["斜面和浮雕_样式"] = getBevelStyleName(typeIDToStringID(styleID));

                    // 读取斜面和浮雕方法
                    var techniqueID = null;
                    if (bevel.hasKey(stringIDToTypeID("technique"))) {
                        techniqueID = bevel.getEnumerationValue(stringIDToTypeID("technique"));
                    } else if (bevel.hasKey(stringIDToTypeID("bevelTechnique"))) {
                        techniqueID = bevel.getEnumerationValue(stringIDToTypeID("bevelTechnique"));
                    }

                    if (techniqueID) {
                        styles["斜面和浮雕_方法"] = getBevelTechniqueName(typeIDToStringID(techniqueID));
                    } else {
                        styles["斜面和浮雕_方法"] = "未知";
                    }

                    // 深度
                    if (bevel.hasKey(stringIDToTypeID("depth"))) {
                        styles["斜面和浮雕_深度"] = Math.round(bevel.getDouble(stringIDToTypeID("depth")) * 100) + "%";
                    } else if (bevel.hasKey(stringIDToTypeID("strengthRatio"))) {
                        styles["斜面和浮雕_深度"] = Math.round(bevel.getUnitDoubleValue(stringIDToTypeID("strengthRatio"))) + "%";
                    }

                    // 方向
                    if (bevel.hasKey(stringIDToTypeID("direction")) || bevel.hasKey(stringIDToTypeID("bevelDirection"))) {
                        var dir = bevel.hasKey(stringIDToTypeID("direction"))
                            ? typeIDToStringID(bevel.getEnumerationValue(stringIDToTypeID("direction")))
                            : typeIDToStringID(bevel.getEnumerationValue(stringIDToTypeID("bevelDirection")));
                        styles["斜面和浮雕_方向"] = (dir === "up") ? "向上" : "向下";
                    }

                    // 大小
                    if (bevel.hasKey(stringIDToTypeID("size"))) {
                        styles["斜面和浮雕_大小"] = bevel.getUnitDoubleValue(stringIDToTypeID("size")) + " 像素";
                    } else if (bevel.hasKey(stringIDToTypeID("blur"))) {
                        styles["斜面和浮雕_大小"] = bevel.getUnitDoubleValue(stringIDToTypeID("blur")) + " 像素";
                    }

                    // 软化
                    if (bevel.hasKey(stringIDToTypeID("soften")) || bevel.hasKey(stringIDToTypeID("softness"))) {
                        styles["斜面和浮雕_软化"] = bevel.hasKey(stringIDToTypeID("soften"))
                            ? bevel.getUnitDoubleValue(stringIDToTypeID("soften")) + " 像素"
                            : bevel.getUnitDoubleValue(stringIDToTypeID("softness")) + " 像素";
                    }

                    // 使用全局光
                    if (bevel.hasKey(stringIDToTypeID("useGlobalAngle"))) {
                        styles["斜面和浮雕_使用全局光"] = bevel.getBoolean(stringIDToTypeID("useGlobalAngle")) ? "是" : "否";
                    }

                    // 角度
                    if (bevel.hasKey(stringIDToTypeID("localLightingAngle"))) {
                        styles["斜面和浮雕_角度"] = bevel.getInteger(stringIDToTypeID("localLightingAngle")) + "°";
                    }

                    // 高度
                    if (bevel.hasKey(stringIDToTypeID("localLightingAltitude"))) {
                        styles["斜面和浮雕_高度"] = bevel.getInteger(stringIDToTypeID("localLightingAltitude")) + "°";
                    }

                    // 等高线
                    if (bevel.hasKey(stringIDToTypeID("transparencyShape")) || bevel.hasKey(stringIDToTypeID("transferSpec"))) {
                        var contour = bevel.hasKey(stringIDToTypeID("transparencyShape"))
                            ? bevel.getObjectValue(stringIDToTypeID("transparencyShape"))
                            : bevel.getObjectValue(stringIDToTypeID("transferSpec"));
                        styles["斜面和浮雕_等高线"] = contour.hasKey(stringIDToTypeID("name")) ? contour.getString(stringIDToTypeID("name")) : "未知";
                    } else {
                        styles["斜面和浮雕_等高线"] = "未知";
                    }


                    // 高光
                    if (bevel.hasKey(stringIDToTypeID("highlightMode"))) {
                        styles["斜面和浮雕_高光模式"] = getBlendModeName(bevel.getEnumerationValue(stringIDToTypeID("highlightMode")));
                    }
                    if (bevel.hasKey(stringIDToTypeID("highlightColor"))) {
                        styles["斜面和浮雕_高光颜色"] = colorDescToHex(bevel.getObjectValue(stringIDToTypeID("highlightColor")));
                    }
                    if (bevel.hasKey(stringIDToTypeID("highlightOpacity"))) {
                        styles["斜面和浮雕_高光不透明度"] = Math.round(bevel.getUnitDoubleValue(stringIDToTypeID("highlightOpacity"))) + "%";
                    }

                    // 阴影
                    if (bevel.hasKey(stringIDToTypeID("shadowMode"))) {
                        styles["斜面和浮雕_阴影模式"] = getBlendModeName(bevel.getEnumerationValue(stringIDToTypeID("shadowMode")));
                    }
                    if (bevel.hasKey(stringIDToTypeID("shadowColor"))) {
                        styles["斜面和浮雕_阴影颜色"] = colorDescToHex(bevel.getObjectValue(stringIDToTypeID("shadowColor")));
                    }
                    if (bevel.hasKey(stringIDToTypeID("shadowOpacity"))) {
                        styles["斜面和浮雕_阴影不透明度"] = Math.round(bevel.getUnitDoubleValue(stringIDToTypeID("shadowOpacity"))) + "%";
                    }
                }
            }
        }



        // ---- 外发光 ----
        if (effects.hasKey(stringIDToTypeID("outerGlow"))) {
            var outerGlow = effects.getObjectValue(stringIDToTypeID("outerGlow"));
            if (outerGlow.hasKey(stringIDToTypeID("enabled"))) {
                var enabled = outerGlow.getBoolean(stringIDToTypeID("enabled"));
                if (enabled) {

                    // 不透明度
                    if (outerGlow.hasKey(stringIDToTypeID("opacity"))) {
                        styles["外发光_不透明度"] = Math.round(outerGlow.getUnitDoubleValue(stringIDToTypeID("opacity"))) + "%";
                    }

                    // 方法（精确 / 平滑）
                    if (outerGlow.hasKey(stringIDToTypeID("glowTechnique"))) {
                        var techEnum = outerGlow.getEnumerationValue(stringIDToTypeID("glowTechnique"));
                        styles["外发光_图素方法"] = getOuterGlowTechniqueName(typeIDToStringID(techEnum));
                    }
                    // 颜色（单色模式）
                    if (outerGlow.hasKey(stringIDToTypeID("color"))) {
                        styles["外发光_颜色"] = colorDescToHex(outerGlow.getObjectValue(stringIDToTypeID("color")));
                    }
                    // 大小
                    if (outerGlow.hasKey(stringIDToTypeID("blur"))) {
                        styles["外发光_大小"] = outerGlow.getUnitDoubleValue(stringIDToTypeID("blur")) + " 像素";
                    }

                    // 阻塞
                    if (outerGlow.hasKey(stringIDToTypeID("chokeMatte"))) {
                        styles["外发光_阻塞"] = outerGlow.getUnitDoubleValue(stringIDToTypeID("chokeMatte")) + " 像素";
                    }

                    // 混合模式
                    if (outerGlow.hasKey(stringIDToTypeID("mode"))) {
                        styles["外发光_混合模式"] = getBlendModeName(outerGlow.getEnumerationValue(stringIDToTypeID("mode")));
                    }

                    // ---- 渐变信息 ----
                    if (outerGlow.hasKey(stringIDToTypeID("gradient"))) {
                        var gradient = outerGlow.getObjectValue(stringIDToTypeID("gradient"));

                        // 内部渐变名 ID
                        var gradientID = gradient.getString(stringIDToTypeID("name"));

                        // 常用渐变 ID -> 中文名映射表
                        var gradientNameMap = {
                            // 2025 版本直接英文名
                            "Chrome": "铬黄渐变",
                            "Black, White": "黑白渐变",
                            "Blue, Red": "蓝红渐变",
                            "Gold": "金色渐变",
                            "Silver": "银色渐变",
                            "Copper": "铜色渐变",
                            "Red, Yellow": "红黄渐变",
                            "Yellow, Green": "黄绿渐变",
                            "Green, Cyan": "绿青渐变",
                            "Cyan, Blue": "青蓝渐变",
                            "Magenta, Purple": "品紫渐变",
                            "Orange, Red": "橙红渐变",
                            "Blue, Purple": "蓝紫渐变",
                            "Foreground to Background": "前景到背景渐变",
                            "Black, Foreground": "黑到前景色渐变",
                            "Foreground to Transparent": "前景到透明渐变",
                            "Neutral Density": "中性密度渐变",
                            "Noise": "噪点渐变",
                            "Blue, Green": "蓝到绿渐变",
                            "Green, Yellow": "绿到黄渐变",
                            "Red, Blue": "红到蓝渐变",
                            "Yellow, Orange": "黄到橙渐变",
                            "Purple, Red": "紫到红渐变",
                            "White, Black": "白到黑渐变",

                            // CS6 及旧版 $$$ ID 格式
                            "$$$/DefaultGradient/Chrome=Chrome": "铬黄渐变",
                            "$$$/DefaultGradient/Black, White=Black, White": "黑白渐变",
                            "$$$/DefaultGradient/Blue, Red=Blue, Red": "蓝红渐变",
                            "$$$/DefaultGradient/Gold=Gold": "金色渐变",
                            "$$$/DefaultGradient/Silver=Silver": "银色渐变",
                            "$$$/DefaultGradient/Copper=Copper": "铜色渐变",
                            "$$$/DefaultGradient/Red, Yellow=Red, Yellow": "红黄渐变",
                            "$$$/DefaultGradient/Yellow, Green=Yellow, Green": "黄绿渐变",
                            "$$$/DefaultGradient/Green, Cyan=Green, Cyan": "绿青渐变",
                            "$$$/DefaultGradient/Cyan, Blue=Cyan, Blue": "青蓝渐变",
                            "$$$/DefaultGradient/Magenta, Purple=Magenta, Purple": "品紫渐变",
                            "$$$/DefaultGradient/Orange, Red=Orange, Red": "橙红渐变",
                            "$$$/DefaultGradient/Blue, Purple=Blue, Purple": "蓝紫渐变",
                            "$$$/DefaultGradient/Foreground to Background=前景到背景渐变": "前景到背景渐变",
                            "$$$/DefaultGradient/Black, Foreground=黑到前景色渐变": "黑到前景色渐变",
                            "$$$/DefaultGradient/Foreground to Transparent=前景到透明渐变": "前景到透明渐变",
                            "$$$/DefaultGradient/Neutral Density=Neutral Density": "中性密度渐变",
                            "$$$/DefaultGradient/Noise=Noise": "噪点渐变"
                        };



                        styles["外发光_渐变名称"] = gradientNameMap[gradientID] || gradientID;

                        // 颜色 stop
                        if (gradient.hasKey(stringIDToTypeID("colors"))) {
                            var colorsList = gradient.getList(stringIDToTypeID("colors"));
                            var colorHexArr = [];
                            for (var i = 0; i < colorsList.count; i++) {
                                var colorObj = colorsList.getObjectValue(i).getObjectValue(stringIDToTypeID("color"));
                                colorHexArr.push(colorDescToHex(colorObj));
                            }
                            styles["外发光_渐变色"] = colorHexArr;
                        }
                    }

                }
            }
        }


        // ---- 光泽（Satin） ----
        if (effects.hasKey(stringIDToTypeID("satin"))) {
            var satin = effects.getObjectValue(stringIDToTypeID("satin"));
            if (satin.hasKey(stringIDToTypeID("enabled"))) {
                var enabled = satin.getBoolean(stringIDToTypeID("enabled"));
                if (enabled) {
                    if (satin.hasKey(stringIDToTypeID("opacity"))) {
                        styles["光泽_不透明度"] = Math.round(satin.getUnitDoubleValue(stringIDToTypeID("opacity"))) + "%";
                    }
                    if (satin.hasKey(stringIDToTypeID("color"))) {
                        styles["光泽_颜色"] = colorDescToHex(satin.getObjectValue(stringIDToTypeID("color")));
                    }
                    if (satin.hasKey(stringIDToTypeID("mode"))) {
                        styles["光泽_混合模式"] = getBlendModeName(satin.getEnumerationValue(stringIDToTypeID("mode")));
                    }
                    if (satin.hasKey(stringIDToTypeID("angle"))) {
                        styles["光泽_角度"] = satin.getUnitDoubleValue(stringIDToTypeID("angle")) + "°";
                    }
                    if (satin.hasKey(stringIDToTypeID("distance"))) {
                        styles["光泽_距离"] = satin.getUnitDoubleValue(stringIDToTypeID("distance")) + " 像素";
                    }
                    if (satin.hasKey(stringIDToTypeID("size"))) {
                        styles["光泽_大小"] = satin.getUnitDoubleValue(stringIDToTypeID("size")) + " 像素";
                    }
                }
            }
        }

        return hasOwnProperties(styles) ? styles : null;
    } catch (e) {
        return null;
    }

}






// 辅助函数：描边位置
function getStrokePositionName(posStringID) {
    switch(posStringID) {
        case "outsetFrame": return "外侧";
        case "insideFrame": return "内侧";
        case "centeredFrame": return "居中";
        default: return "未知";
    }
}


// 斜面和浮雕 样式名称
function getBevelStyleName(value) {
    switch (value) {
        case stringIDToTypeID("outerBevel"): return "外斜面";
        case stringIDToTypeID("innerBevel"): return "内斜面";
        case stringIDToTypeID("emboss"): return "浮雕";
        case stringIDToTypeID("pillowEmboss"): return "枕头状浮雕";
        default: return "未知";
    }
}


// 斜面和浮雕 方向
function getBevelDirectionName(value) {
    switch (value) {
        case stringIDToTypeID("up"): return "上";
        case stringIDToTypeID("down"): return "下";
        default: return "未知";
    }
}

// 图层混合模式
function getBlendModeName(value) {
    var map = {
        "normal": "正常",
        "multiply": "正片叠底",
        "screen": "滤色",
        "overlay": "叠加",
        "softLight": "柔光",
        "hardLight": "强光",
        "vividLight": "亮光",
        "linearLight": "线性加深/减淡",
        "pinLight": "点光",
        "difference": "差值",
        "exclusion": "排除",
        "colorBurn": "颜色加深",
        "linearBurn": "线性加深",
        "darkerColor": "深色",
        "colorDodge": "颜色减淡",
        "linearDodge": "线性减淡",
        "lighterColor": "浅色",
        "lighten": "变亮",
        "darken": "变暗",
        "dissolve": "溶解",
        "hue": "色相",
        "saturation": "饱和度",
        "color": "颜色",
        "luminosity": "明度",
        "subtract": "减去",
        "blendSubtraction": "减去", // 2025 新增
        "divide": "划分"
    };

    try {
        // 可能是 stringID
        var strID = (typeof value === "number") ? typeIDToStringID(value) : value;
        return map[strID] || strID;
    } catch(e) {
        return value;
    }
}

// 外发光 图素方法
function getOuterGlowTechniqueName(techniqueStr) {
    var map = {
        "softMatte": "柔和",
        "preciseMatte": "精确"
    };
    return map[techniqueStr] || techniqueStr;
}

// 等高线名称（外发光等）
function getContourName(value) {
    switch (value) {
        case stringIDToTypeID("linear"): return "线性";
        case stringIDToTypeID("ring"): return "环形";
        case stringIDToTypeID("cone"): return "锥形";
        case stringIDToTypeID("cove"): return "凹形";
        case stringIDToTypeID("stairs"): return "阶梯";
        case stringIDToTypeID("custom"): return "自定义";
        case stringIDToTypeID("zigZag"): return "锯齿1";
        case stringIDToTypeID("roundedSteps"): return "圆角阶梯";
        default: return "未知";
    }
}
function colorDescToHex(colorDesc) {
    try {
        if (!colorDesc.hasKey(stringIDToTypeID('red')) ||
            !colorDesc.hasKey(stringIDToTypeID('green')) ||
            !colorDesc.hasKey(stringIDToTypeID('blue'))) {
            return null;
        }

        var red = Math.round(colorDesc.getDouble(stringIDToTypeID('red')));
        var green = Math.round(colorDesc.getDouble(stringIDToTypeID('green')));
        var blue = Math.round(colorDesc.getDouble(stringIDToTypeID('blue')));
        return rgbToHex(red, green, blue);
    } catch (e) {
        return null;
    }
}

function getInnerGlowTechniqueName(value) {
    switch(value) {
        case stringIDToTypeID("precise"): return "精确";
        case stringIDToTypeID("softer"): return "柔和";
        default: return "未知";
    }
}
function getInnerGlowSourceName(value) {
    switch(value) {
        case stringIDToTypeID("center"): return "中心";
        case stringIDToTypeID("edge"): return "边缘";
        default: return "未知";
    }
}

function rgbToHex(r, g, b) {
    function toHex(n) {
        return ("0" + n.toString(16)).slice(-2);
    }
    return "#" + toHex(r) + toHex(g) + toHex(b);
}


// 滤镜检测示例（只检测图层名包含的关键词）
// 修改后的detectFilters函数，优先用XMP元数据读取镜头光晕参数
function detectFilters(layerName) {
    var filters = {};
    if (!layerName || typeof layerName !== "string") {
        return null;
    }
    var name = layerName.toLowerCase();

    // 先尝试读取XMP中镜头光晕参数

    var lensFlareMeta = readHistoryFromXMP();
    if (lensFlareMeta) {
        return lensFlareMeta; // 直接返回读取的元数据
    }
    // else {
    //     // 没读到元数据，返回默认提示
    //     filters["滤镜类型"] = "镜头光晕";
    //     filters["亮度"] = "⚠️ 无法读取，建议人工确认";
    //     filters["镜头类型"] = "⚠️ 无法读取，建议人工确认";
    //     return filters;
    // }


}


// 结合你的读取函数用法举例
function readHistoryFromXMP() {
    try {
        if (typeof ExternalObject.AdobeXMPScript === "undefined") {
            ExternalObject.AdobeXMPScript = new ExternalObject("lib:AdobeXMPScript");
        }

        var xmp = new XMPMeta(app.activeDocument.xmpMetadata.rawData);
        var nsMM = "http://ns.adobe.com/xap/1.0/mm/";
        var nsEvt = "http://ns.adobe.com/xap/1.0/sType/ResourceEvent#";

        XMPMeta.registerNamespace(nsMM, "xmpMM");
        XMPMeta.registerNamespace(nsEvt, "stEvt");

        var count = xmp.countArrayItems(nsMM, "History");
        if (count === 0) {
            $.writeln("没有找到历史记录");
            return null;
        }


        for (var i = 1; i <= count; i++) {
            var itemXMP = xmp.getArrayItem(nsMM, "History", i);
            var historyLine = itemXMP.toString();

            $.writeln("历史记录第" + i + "条: " + historyLine);

            if (historyLine.indexOf("镜头光晕") !== -1 || historyLine.toLowerCase().indexOf("lens flare") !== -1) {
                var brightnessMatch = historyLine.match(/亮度[:：]?\s*(\d+%?)/);
                var typeMatch = historyLine.match(/类型[:：]?\s*([^\s]+)/);

                return {
                    "历史":historyLine,
                    "滤镜类型": "镜头光晕",
                    "亮度": brightnessMatch ? brightnessMatch[1] : "未知",
                    "镜头类型": typeMatch ? typeMatch[1] : "未知"
                };
            }
        }




    } catch (e) {
        return {
            "读取XMP历史记录失败：": e.message
        };

    }
}



// 判断对象是否含有自有属性（兼容无Object.keys的环境）
function hasOwnProperties(obj) {
    for (var key in obj) {
        if (obj.hasOwnProperty(key)) {
            return true;
        }
    }
    return false;
}



function isEmptyObject(obj) {
    for (var key in obj) {
        if (obj.hasOwnProperty(key)) return false;
    }
    return true;
}


// ======================
// 获取蒙版信息
// ======================
function getMaskInfo(layer) {
    var maskInfo = {};

    try {
        // 图层蒙版
        if (hasLayerMask(layer)) {
            maskInfo["图层蒙版"] = "存在";
        }

        // 矢量蒙版
        if (hasVectorMask(layer)) {
            maskInfo["矢量蒙版"] = "存在";
        }

        // 剪切蒙版
        if (layer.grouped) { // ExtendScript 属性，true 表示是剪切蒙版
            maskInfo["剪切蒙版"] = "存在";
        }

    } catch (e) {
        maskInfo["错误"] = e.toString();
    }

    return maskInfo;
}

// ======================
// 判断是否有图层蒙版
// ======================
function hasLayerMask(layer) {
    var ref = new ActionReference();
    ref.putEnumerated(charIDToTypeID("Lyr "), charIDToTypeID("Ordn"), charIDToTypeID("Trgt"));
    var desc = executeActionGet(ref);
    return desc.hasKey(stringIDToTypeID("hasUserMask")) && desc.getBoolean(stringIDToTypeID("hasUserMask"));
}

// ======================
// 判断是否有矢量蒙版
// ======================
function hasVectorMask(layer) {
    var ref = new ActionReference();
    ref.putEnumerated(charIDToTypeID("Lyr "), charIDToTypeID("Ordn"), charIDToTypeID("Trgt"));
    var desc = executeActionGet(ref);
    return desc.hasKey(stringIDToTypeID("hasVectorMask")) && desc.getBoolean(stringIDToTypeID("hasVectorMask"));
}
function getBevelStyleName(id) {
    var map = {
        "innerBevel": "内斜面",
        "outerBevel": "外斜面",
        "emboss": "浮雕",
        "pillowEmboss": "枕状浮雕"
    };
    return map[id] || "未知";
}

function getBevelTechniqueName(id) {
    var map = {
        "smooth": "平滑",
        "softMatte": "平滑",          // 别名
        "chiselSoft": "雕刻清晰",
        "preciseMatte": "雕刻清晰",   // 别名
        "chiselHard": "雕刻深"
    };
    return map[id] || id || "未知";
}

