From d4f28ba00d41ff0f8e529c923e0d72d93f137dc1 Mon Sep 17 00:00:00 2001 From: "949036910@qq.com" <> Date: Tue, 2 Jun 2026 23:18:05 +0800 Subject: [PATCH] 11 --- src/config/coverTemplateDefaults.js | 10 + src/config/electronCoverTemplates.js | 40 ++++ .../cover-template-人像居中.json | 176 ++++++++++++++++++ .../cover-template-大四字报.json | 164 ++++++++++++++++ .../cover-template-斜黄白.json | 137 ++++++++++++++ .../cover-template-粉红虚白.json | 148 +++++++++++++++ .../cover-template-红黄虚描.json | 176 ++++++++++++++++++ .../cover-template-蓝底白字.json | 139 ++++++++++++++ .../cover-template-青蓝虚描.json | 167 +++++++++++++++++ .../cover-template-黄白实描.json | 176 ++++++++++++++++++ src/services/coverGenerate.js | 19 +- src/services/coverTemplateCatalog.js | 65 ++++++- src/stores/workflow.js | 2 +- src/utils/coverElectronImport.js | 128 +++++++++++++ 14 files changed, 1533 insertions(+), 14 deletions(-) create mode 100644 src/config/electronCoverTemplates.js create mode 100644 src/data/cover-templates/cover-template-人像居中.json create mode 100644 src/data/cover-templates/cover-template-大四字报.json create mode 100644 src/data/cover-templates/cover-template-斜黄白.json create mode 100644 src/data/cover-templates/cover-template-粉红虚白.json create mode 100644 src/data/cover-templates/cover-template-红黄虚描.json create mode 100644 src/data/cover-templates/cover-template-蓝底白字.json create mode 100644 src/data/cover-templates/cover-template-青蓝虚描.json create mode 100644 src/data/cover-templates/cover-template-黄白实描.json create mode 100644 src/utils/coverElectronImport.js diff --git a/src/config/coverTemplateDefaults.js b/src/config/coverTemplateDefaults.js index 0bcc51a..c05f8d8 100644 --- a/src/config/coverTemplateDefaults.js +++ b/src/config/coverTemplateDefaults.js @@ -8,6 +8,16 @@ export const COVER_FONT_OPTIONS = [ { label: "黑体", value: "SimHei" }, { label: "宋体", value: "SimSun" }, { label: "微软雅黑", value: "Microsoft YaHei" }, + { label: "墨趣古风体", value: "墨趣古风体" }, + { label: "泼墨体", value: "泼墨体" }, + { label: "程荣光刻楷", value: "1.程荣光刻楷" }, + { label: "斗鱼追光体", value: "斗鱼追光体2.0" }, + { label: "庞门正道标题体", value: "庞门正道标题体免费版" }, + { label: "方正粗黑宋", value: "方正粗黑宋简体" }, + { label: "千图厚黑体", value: "千图厚黑体" }, + { label: "杨任东竹石体", value: "杨任东竹石体" }, + { label: "猫啃杂糅 Lite", value: "MaokenAssortedSans-Lite" }, + { label: "圆体", value: "USMCCyuanjiantecu" }, { label: "Arial", value: "Arial" }, { label: "Times New Roman", value: "Times New Roman" }, ]; diff --git a/src/config/electronCoverTemplates.js b/src/config/electronCoverTemplates.js new file mode 100644 index 0000000..eaee7e6 --- /dev/null +++ b/src/config/electronCoverTemplates.js @@ -0,0 +1,40 @@ +/** + * Electron 原版 8 款系统封面预设(由 aiclient/templates 导出 JSON 同步) + */ +import { electronCoverItemToTemplate } from "../utils/coverElectronImport.js"; + +const exports = import.meta.glob("../data/cover-templates/cover-template-*.json", { + eager: true, + import: "default", +}); + +/** + * @returns {import('../services/coverTemplateCatalog.js').CoverTemplateItem[]} + */ +export function loadElectronCoverTemplates() { + const items = Object.values(exports) + .map((data) => { + if (!data?.coverTemplate) return null; + return electronCoverItemToTemplate(data.coverTemplate); + }) + .filter(Boolean); + + const order = [ + "cover_electron_portrait_center", + "cover_electron_big_four_chars", + "cover_electron_slant_yellow_white", + "cover_electron_pink_outline_white", + "cover_electron_red_yellow_outline", + "cover_electron_blue_bg_white", + "cover_electron_cyan_blue_outline", + "cover_electron_yellow_white_solid", + ]; + + return items.sort( + (a, b) => order.indexOf(a.id) - order.indexOf(b.id) || 0, + ); +} + +export const ELECTRON_COVER_TEMPLATE_IDS = new Set( + loadElectronCoverTemplates().map((t) => t.id), +); diff --git a/src/data/cover-templates/cover-template-人像居中.json b/src/data/cover-templates/cover-template-人像居中.json new file mode 100644 index 0000000..54ef3f3 --- /dev/null +++ b/src/data/cover-templates/cover-template-人像居中.json @@ -0,0 +1,176 @@ +{ + "version": "1.0.0", + "description": "封面模板导出配置", + "timestamp": "2026-06-02T12:13:49.997Z", + "coverTemplate": { + "id": "v08ezr6v3x-mkdite6i", + "name": "人像居中", + "config": { + "backgroundEnabled": false, + "backgroundImagePath": null, + "backgroundBlurEnabled": true, + "backgroundBlurIntensity": 30, + "backgroundSize": 100, + "backgroundPosition": { + "x": 50, + "y": 50 + }, + "personImagePath": null, + "personSize": 54.99999999999999, + "personPosition": { + "x": 53.935185185185205, + "y": 34.375 + }, + "personRotation": 0, + "personBorderEnabled": true, + "personBorderStyle": "solid", + "personBorderColor": "#FFFFFF", + "personBorderWidth": 8, + "personBorderDashLength": null, + "personBorderGapLength": null, + "autoSplitText": true, + "titleMaxLength": 6, + "subtitleMaxLength": 12, + "titleText": "托德揭秘芒格", + "titleFontFamily": "墨趣古风体", + "titleFontSize": 110, + "titleFontWeight": 100, + "titleColor": "#ffffff", + "titleStrokeColor": "#000000", + "titleStrokeWidth": 0, + "titleShadowColor": "#000000", + "titleShadowOffsetX": 0, + "titleShadowOffsetY": 0, + "titleShadowBlur": 0, + "titleShadowEnabled": false, + "titleShadowLayers": [ + { + "id": 1765435502861.9124, + "offsetX": -2, + "offsetY": -2, + "blur": 12, + "color": "#000000", + "opacity": 100, + "enabled": true + }, + { + "id": 1765435502861.0488, + "offsetX": 2, + "offsetY": 2, + "blur": 16, + "color": "#000000", + "opacity": 100, + "enabled": true + }, + { + "id": 1765435502861.4207, + "offsetX": 0, + "offsetY": 0, + "blur": 14, + "color": "#000000", + "opacity": 100, + "enabled": true + } + ], + "titlePosition": { + "x": 39.814814814814795, + "y": 69.40972222222223 + }, + "titleRotation": 0, + "titleDirection": "horizontal", + "titleCharSpacing": 12, + "titleLineSpacing": 118, + "titleMaxCharsPerLine": 10, + "titleBackgroundEnabled": false, + "titleBackgroundColor": "#000000", + "titleBackgroundOpacity": 70, + "titleBackgroundShape": "rectangle", + "titleBackgroundSize": { + "width": 30, + "height": 10 + }, + "titleBackgroundPosition": { + "x": 50, + "y": 30 + }, + "titleBackgroundPoints": [], + "titleBackgroundRadius": 10, + "titleBackgroundRotation": 0, + "subtitleText": "投资稳的原因", + "subtitleFontFamily": "庞门正道标题体免费版", + "subtitleFontSize": 117, + "subtitleFontWeight": 500, + "subtitleColor": "#eaf273", + "subtitleStrokeColor": "#000000", + "subtitleStrokeWidth": 0, + "subtitleShadowColor": "#000000", + "subtitleShadowOffsetX": 0, + "subtitleShadowOffsetY": 0, + "subtitleShadowBlur": 0, + "subtitleShadowEnabled": false, + "subtitleShadowLayers": [ + { + "id": 1765435591571.2886, + "offsetX": -2, + "offsetY": -2, + "blur": 2, + "color": "#FFFFFF", + "opacity": 60, + "enabled": true + }, + { + "id": 1765435591571.856, + "offsetX": 2, + "offsetY": 2, + "blur": 0, + "color": "#000000", + "opacity": 65, + "enabled": true + }, + { + "id": 1765435591571.3809, + "offsetX": 0, + "offsetY": 0, + "blur": 4, + "color": "#000000", + "opacity": 50, + "enabled": true + } + ], + "subtitlePosition": { + "x": 58.796296296296305, + "y": 77.84722222222221 + }, + "subtitleRotation": 0, + "subtitleDirection": "horizontal", + "subtitleCharSpacing": 12, + "subtitleLineSpacing": 72, + "subtitleMaxCharsPerLine": 15, + "subtitleBackgroundEnabled": false, + "subtitleBackgroundColor": "#000000", + "subtitleBackgroundOpacity": 70, + "subtitleBackgroundShape": "rectangle", + "subtitleBackgroundSize": { + "width": 30, + "height": 10 + }, + "subtitleBackgroundPosition": { + "x": 50, + "y": 60 + }, + "subtitleBackgroundPoints": [], + "subtitleBackgroundRadius": 10, + "subtitleBackgroundRotation": 0, + "maskEnabled": false, + "maskImagePath": null, + "maskSize": 100, + "maskPosition": { + "x": 50, + "y": 50 + }, + "maskColor": null, + "maskOpacity": 100, + "maskShape": "rectangle" + } + } +} \ No newline at end of file diff --git a/src/data/cover-templates/cover-template-大四字报.json b/src/data/cover-templates/cover-template-大四字报.json new file mode 100644 index 0000000..fe6a4ae --- /dev/null +++ b/src/data/cover-templates/cover-template-大四字报.json @@ -0,0 +1,164 @@ +{ + "version": "1.0.0", + "description": "封面模板导出配置", + "timestamp": "2026-06-02T12:13:38.566Z", + "coverTemplate": { + "id": "705fa010-5bf3-4041-b624-0fd364bea5ad", + "name": "大四字报", + "config": { + "backgroundEnabled": true, + "backgroundImagePath": null, + "backgroundBlurEnabled": false, + "backgroundBlurIntensity": 30, + "backgroundSize": 100, + "backgroundPosition": { + "x": 50, + "y": 50 + }, + "personImagePath": null, + "personSize": 33.125, + "personPosition": { + "x": 22.68518518518519, + "y": 78.125 + }, + "personRotation": 0, + "personBorderEnabled": false, + "personBorderStyle": "solid", + "personBorderColor": "#FFFFFF", + "personBorderWidth": 8, + "personBorderDashLength": null, + "personBorderGapLength": null, + "autoSplitText": true, + "titleMaxLength": 4, + "subtitleMaxLength": 30, + "titleText": "礼貌回归", + "titleFontFamily": "USMCCyuanjiantecu", + "titleFontSize": 375, + "titleFontWeight": 400, + "titleColor": "#e6ca19", + "titleStrokeColor": "#000000", + "titleStrokeWidth": 0, + "titleShadowColor": "#000000", + "titleShadowOffsetX": 0, + "titleShadowOffsetY": 0, + "titleShadowBlur": 0, + "titleShadowEnabled": false, + "titleShadowLayers": [ + { + "id": 1765355385133.3418, + "offsetX": 20, + "offsetY": 20, + "blur": 30, + "color": "#000000", + "opacity": 100, + "enabled": true + }, + { + "id": 1765355385133.7036, + "offsetX": -20, + "offsetY": -20, + "blur": 30, + "color": "#000000", + "opacity": 100, + "enabled": true + } + ], + "titlePosition": { + "x": 52.54629629629629, + "y": 48.40277777777778 + }, + "titleRotation": 0, + "titleDirection": "horizontal", + "titleCharSpacing": 58, + "titleLineSpacing": 150, + "titleMaxCharsPerLine": 2, + "titleBackgroundEnabled": false, + "titleBackgroundColor": "#000000", + "titleBackgroundOpacity": 70, + "titleBackgroundShape": "polygon", + "titleBackgroundSize": { + "width": 30, + "height": 10 + }, + "titleBackgroundPosition": { + "x": 95.83333333333333, + "y": 68.88888888888889 + }, + "titleBackgroundPoints": [ + { + "x": -330.24691358024694, + "y": -15.440538194444414 + }, + { + "x": 40, + "y": -40 + }, + { + "x": 40, + "y": 40 + }, + { + "x": -40, + "y": 40 + }, + { + "x": -114.9691358024691, + "y": 36.642795138888864 + }, + { + "x": -96.45061728395058, + "y": -3.2877604166666865 + } + ], + "titleBackgroundRadius": 10, + "titleBackgroundRotation": 0, + "subtitleText": "行动亲爱的观众朋友们", + "subtitleFontFamily": "USMCCyuanjiantecu", + "subtitleFontSize": 122, + "subtitleFontWeight": 500, + "subtitleColor": "#e37a16", + "subtitleStrokeColor": "#000000", + "subtitleStrokeWidth": 5, + "subtitleShadowColor": "#ff0000", + "subtitleShadowOffsetX": 41, + "subtitleShadowOffsetY": 50, + "subtitleShadowBlur": 13, + "subtitleShadowEnabled": false, + "subtitleShadowLayers": [], + "subtitlePosition": { + "x": 51.15740740740741, + "y": 83.75 + }, + "subtitleRotation": 0, + "subtitleDirection": "horizontal", + "subtitleCharSpacing": 0, + "subtitleLineSpacing": 72, + "subtitleMaxCharsPerLine": 8, + "subtitleBackgroundEnabled": false, + "subtitleBackgroundColor": "#000000", + "subtitleBackgroundOpacity": 70, + "subtitleBackgroundShape": "rectangle", + "subtitleBackgroundSize": { + "width": 30, + "height": 10 + }, + "subtitleBackgroundPosition": { + "x": 50, + "y": 60 + }, + "subtitleBackgroundPoints": [], + "subtitleBackgroundRadius": 10, + "subtitleBackgroundRotation": 0, + "maskEnabled": false, + "maskImagePath": null, + "maskSize": 100, + "maskPosition": { + "x": 50, + "y": 50 + }, + "maskColor": null, + "maskOpacity": 100, + "maskShape": "rectangle" + } + } +} \ No newline at end of file diff --git a/src/data/cover-templates/cover-template-斜黄白.json b/src/data/cover-templates/cover-template-斜黄白.json new file mode 100644 index 0000000..d0d5dd7 --- /dev/null +++ b/src/data/cover-templates/cover-template-斜黄白.json @@ -0,0 +1,137 @@ +{ + "version": "1.0.0", + "description": "封面模板导出配置", + "timestamp": "2026-06-02T12:12:07.312Z", + "coverTemplate": { + "id": "8f17c467-c69c-45b2-8011-94a6c3071d16", + "name": "斜黄白", + "config": { + "backgroundEnabled": false, + "backgroundImagePath": null, + "backgroundBlurEnabled": false, + "backgroundBlurIntensity": 10, + "backgroundSize": 100, + "backgroundPosition": { + "x": 50, + "y": 50 + }, + "personImagePath": null, + "personSize": 80, + "personPosition": { + "x": 50, + "y": 50 + }, + "personRotation": 0, + "personBorderEnabled": false, + "personBorderStyle": "solid", + "personBorderColor": "#FFFFFF", + "personBorderWidth": 8, + "personBorderDashLength": null, + "personBorderGapLength": null, + "autoSplitText": true, + "titleMaxLength": 4, + "subtitleMaxLength": 10, + "titleText": "礼貌回归", + "titleFontFamily": "斗鱼追光体2.0", + "titleFontSize": 120, + "titleFontWeight": 700, + "titleColor": "#f5d400", + "titleStrokeColor": "#000000", + "titleStrokeWidth": 3, + "titleShadowColor": "#000000", + "titleShadowOffsetX": 0, + "titleShadowOffsetY": 0, + "titleShadowBlur": 0, + "titleShadowEnabled": false, + "titleShadowLayers": [], + "titlePosition": { + "x": 42.59259259259258, + "y": 56.909722222222214 + }, + "titleRotation": 338, + "titleDirection": "horizontal", + "titleCharSpacing": 24, + "titleLineSpacing": 144, + "titleMaxCharsPerLine": 10, + "titleBackgroundEnabled": true, + "titleBackgroundColor": "#f5f5f5", + "titleBackgroundOpacity": 25, + "titleBackgroundShape": "polygon", + "titleBackgroundSize": { + "width": 30, + "height": 10 + }, + "titleBackgroundPosition": { + "x": 44.21296296296296, + "y": 32.951388888888886 + }, + "titleBackgroundPoints": [ + { + "x": 226.08024691358025, + "y": -79.67664930555557 + }, + { + "x": 250.7716049382716, + "y": 218.93446180555554 + }, + { + "x": -260.8024691358025, + "y": 691.1566840277777 + }, + { + "x": -290.12345679012344, + "y": 366.50390624999994 + } + ], + "titleBackgroundRadius": 10, + "titleBackgroundRotation": 0, + "subtitleText": "行动亲爱的观众朋友们", + "subtitleFontFamily": "斗鱼追光体2.0", + "subtitleFontSize": 82, + "subtitleFontWeight": 500, + "subtitleColor": "#FFFFFF", + "subtitleStrokeColor": "#000000", + "subtitleStrokeWidth": 1, + "subtitleShadowColor": "#000000", + "subtitleShadowOffsetX": 0, + "subtitleShadowOffsetY": 0, + "subtitleShadowBlur": 0, + "subtitleShadowEnabled": false, + "subtitleShadowLayers": [], + "subtitlePosition": { + "x": 45.37037037037037, + "y": 66.5625 + }, + "subtitleRotation": 338, + "subtitleDirection": "horizontal", + "subtitleCharSpacing": 23, + "subtitleLineSpacing": 72, + "subtitleMaxCharsPerLine": 17, + "subtitleBackgroundEnabled": false, + "subtitleBackgroundColor": "#000000", + "subtitleBackgroundOpacity": 70, + "subtitleBackgroundShape": "rectangle", + "subtitleBackgroundSize": { + "width": 30, + "height": 10 + }, + "subtitleBackgroundPosition": { + "x": 50, + "y": 60 + }, + "subtitleBackgroundPoints": [], + "subtitleBackgroundRadius": 10, + "subtitleBackgroundRotation": 0, + "maskEnabled": false, + "maskImagePath": null, + "maskSize": 100, + "maskPosition": { + "x": 50, + "y": 50 + }, + "maskColor": null, + "maskOpacity": 100, + "maskShape": "rectangle" + } + } +} \ No newline at end of file diff --git a/src/data/cover-templates/cover-template-粉红虚白.json b/src/data/cover-templates/cover-template-粉红虚白.json new file mode 100644 index 0000000..05ea2cc --- /dev/null +++ b/src/data/cover-templates/cover-template-粉红虚白.json @@ -0,0 +1,148 @@ +{ + "version": "1.0.0", + "description": "封面模板导出配置", + "timestamp": "2026-06-02T12:13:56.933Z", + "coverTemplate": { + "id": "43t1uykj8zg-mkdite6i", + "name": "粉红虚白", + "config": { + "backgroundEnabled": false, + "backgroundImagePath": null, + "backgroundBlurEnabled": true, + "backgroundBlurIntensity": 50, + "backgroundSize": 100, + "backgroundPosition": { + "x": 50, + "y": 50 + }, + "personImagePath": null, + "personSize": 81.7361111111111, + "personPosition": { + "x": 49.768518518518526, + "y": 60.41666666666666 + }, + "personRotation": 0, + "personBorderEnabled": true, + "personBorderStyle": "dashed", + "personBorderColor": "#ffffff", + "personBorderWidth": 8, + "personBorderDashLength": null, + "personBorderGapLength": null, + "autoSplitText": true, + "titleMaxLength": 4, + "subtitleMaxLength": 11, + "titleText": "长期持有", + "titleFontFamily": "庞门正道标题体免费版", + "titleFontSize": 165, + "titleFontWeight": 100, + "titleColor": "#e8c4df", + "titleStrokeColor": "#e147c0", + "titleStrokeWidth": 6, + "titleShadowColor": "#000000", + "titleShadowOffsetX": 0, + "titleShadowOffsetY": 0, + "titleShadowBlur": 0, + "titleShadowEnabled": false, + "titleShadowLayers": [], + "titlePosition": { + "x": 36.80555555555553, + "y": 11.944444444444452 + }, + "titleRotation": 0, + "titleDirection": "horizontal", + "titleCharSpacing": 11, + "titleLineSpacing": 118, + "titleMaxCharsPerLine": 10, + "titleBackgroundEnabled": false, + "titleBackgroundColor": "#000000", + "titleBackgroundOpacity": 70, + "titleBackgroundShape": "rectangle", + "titleBackgroundSize": { + "width": 30, + "height": 10 + }, + "titleBackgroundPosition": { + "x": 50, + "y": 30 + }, + "titleBackgroundPoints": [], + "titleBackgroundRadius": 10, + "titleBackgroundRotation": 0, + "subtitleText": "才是真省心又赚钱", + "subtitleFontFamily": "方正粗黑宋简体", + "subtitleFontSize": 117, + "subtitleFontWeight": 500, + "subtitleColor": "#FFFFFF", + "subtitleStrokeColor": "#ef62e3", + "subtitleStrokeWidth": 5, + "subtitleShadowColor": "#000000", + "subtitleShadowOffsetX": 0, + "subtitleShadowOffsetY": 0, + "subtitleShadowBlur": 0, + "subtitleShadowEnabled": false, + "subtitleShadowLayers": [ + { + "id": 1765435591571.2886, + "offsetX": -2, + "offsetY": -2, + "blur": 2, + "color": "#FFFFFF", + "opacity": 60, + "enabled": true + }, + { + "id": 1765435591571.856, + "offsetX": 2, + "offsetY": 2, + "blur": 0, + "color": "#000000", + "opacity": 65, + "enabled": true + }, + { + "id": 1765435591571.3809, + "offsetX": 0, + "offsetY": 0, + "blur": 4, + "color": "#000000", + "opacity": 50, + "enabled": true + } + ], + "subtitlePosition": { + "x": 51.3888888888889, + "y": 23.333333333333304 + }, + "subtitleRotation": 0, + "subtitleDirection": "horizontal", + "subtitleCharSpacing": 12, + "subtitleLineSpacing": 72, + "subtitleMaxCharsPerLine": 15, + "subtitleBackgroundEnabled": false, + "subtitleBackgroundColor": "#000000", + "subtitleBackgroundOpacity": 70, + "subtitleBackgroundShape": "rectangle", + "subtitleBackgroundSize": { + "width": 30, + "height": 10 + }, + "subtitleBackgroundPosition": { + "x": 50, + "y": 60 + }, + "subtitleBackgroundPoints": [], + "subtitleBackgroundRadius": 10, + "subtitleBackgroundRotation": 0, + "maskEnabled": false, + "maskImagePath": null, + "maskSize": 100, + "maskPosition": { + "x": 50, + "y": 50 + }, + "maskColor": null, + "maskOpacity": 100, + "maskShape": "rectangle" + } + } +} \ No newline at end of file diff --git a/src/data/cover-templates/cover-template-红黄虚描.json b/src/data/cover-templates/cover-template-红黄虚描.json new file mode 100644 index 0000000..6b48acc --- /dev/null +++ b/src/data/cover-templates/cover-template-红黄虚描.json @@ -0,0 +1,176 @@ +{ + "version": "1.0.0", + "description": "封面模板导出配置", + "timestamp": "2026-06-02T12:14:00.925Z", + "coverTemplate": { + "id": "sb8mm7l4bjf-mkdite6i", + "name": "红黄虚描", + "config": { + "backgroundEnabled": false, + "backgroundImagePath": null, + "backgroundBlurEnabled": true, + "backgroundBlurIntensity": 60, + "backgroundSize": 100, + "backgroundPosition": { + "x": 50, + "y": 50 + }, + "personImagePath": null, + "personSize": 65.06944444444444, + "personPosition": { + "x": 62.73148148148148, + "y": 67.0138888888889 + }, + "personRotation": 0, + "personBorderEnabled": true, + "personBorderStyle": "dashed", + "personBorderColor": "#FFFFFF", + "personBorderWidth": 12, + "personBorderDashLength": null, + "personBorderGapLength": null, + "autoSplitText": true, + "titleMaxLength": 4, + "subtitleMaxLength": 10, + "titleText": "托德揭秘", + "titleFontFamily": "泼墨体", + "titleFontSize": 165, + "titleFontWeight": 100, + "titleColor": "#d4ec74", + "titleStrokeColor": "#000000", + "titleStrokeWidth": 0, + "titleShadowColor": "#000000", + "titleShadowOffsetX": 0, + "titleShadowOffsetY": 0, + "titleShadowBlur": 0, + "titleShadowEnabled": false, + "titleShadowLayers": [ + { + "id": 1765435502861.9124, + "offsetX": -2, + "offsetY": -2, + "blur": 12, + "color": "#000000", + "opacity": 100, + "enabled": true + }, + { + "id": 1765435502861.0488, + "offsetX": 2, + "offsetY": 2, + "blur": 16, + "color": "#000000", + "opacity": 100, + "enabled": true + }, + { + "id": 1765435502861.4207, + "offsetX": 0, + "offsetY": 0, + "blur": 14, + "color": "#000000", + "opacity": 100, + "enabled": true + } + ], + "titlePosition": { + "x": 55.09259259259257, + "y": 15.59027777777779 + }, + "titleRotation": 0, + "titleDirection": "horizontal", + "titleCharSpacing": 19, + "titleLineSpacing": 118, + "titleMaxCharsPerLine": 9, + "titleBackgroundEnabled": false, + "titleBackgroundColor": "#000000", + "titleBackgroundOpacity": 70, + "titleBackgroundShape": "rectangle", + "titleBackgroundSize": { + "width": 30, + "height": 10 + }, + "titleBackgroundPosition": { + "x": 50, + "y": 30 + }, + "titleBackgroundPoints": [], + "titleBackgroundRadius": 10, + "titleBackgroundRotation": 0, + "subtitleText": "芒格投资稳的原因", + "subtitleFontFamily": "MaokenAssortedSans-Lite", + "subtitleFontSize": 117, + "subtitleFontWeight": 500, + "subtitleColor": "#7e1010", + "subtitleStrokeColor": "#ffffff", + "subtitleStrokeWidth": 6, + "subtitleShadowColor": "#000000", + "subtitleShadowOffsetX": 0, + "subtitleShadowOffsetY": 0, + "subtitleShadowBlur": 0, + "subtitleShadowEnabled": false, + "subtitleShadowLayers": [ + { + "id": 1765435591571.2886, + "offsetX": -2, + "offsetY": -2, + "blur": 2, + "color": "#FFFFFF", + "opacity": 60, + "enabled": true + }, + { + "id": 1765435591571.856, + "offsetX": 2, + "offsetY": 2, + "blur": 0, + "color": "#000000", + "opacity": 65, + "enabled": true + }, + { + "id": 1765435591571.3809, + "offsetX": 0, + "offsetY": 0, + "blur": 4, + "color": "#000000", + "opacity": 50, + "enabled": true + } + ], + "subtitlePosition": { + "x": 18.98148148148148, + "y": 64.47916666666667 + }, + "subtitleRotation": 0, + "subtitleDirection": "vertical", + "subtitleCharSpacing": 12, + "subtitleLineSpacing": 72, + "subtitleMaxCharsPerLine": 15, + "subtitleBackgroundEnabled": false, + "subtitleBackgroundColor": "#000000", + "subtitleBackgroundOpacity": 70, + "subtitleBackgroundShape": "rectangle", + "subtitleBackgroundSize": { + "width": 30, + "height": 10 + }, + "subtitleBackgroundPosition": { + "x": 50, + "y": 60 + }, + "subtitleBackgroundPoints": [], + "subtitleBackgroundRadius": 10, + "subtitleBackgroundRotation": 0, + "maskEnabled": false, + "maskImagePath": null, + "maskSize": 100, + "maskPosition": { + "x": 50, + "y": 50 + }, + "maskColor": null, + "maskOpacity": 100, + "maskShape": "rectangle" + } + } +} \ No newline at end of file diff --git a/src/data/cover-templates/cover-template-蓝底白字.json b/src/data/cover-templates/cover-template-蓝底白字.json new file mode 100644 index 0000000..c8d2ab2 --- /dev/null +++ b/src/data/cover-templates/cover-template-蓝底白字.json @@ -0,0 +1,139 @@ +{ + "version": "1.0.0", + "description": "封面模板导出配置", + "timestamp": "2026-06-02T12:13:43.982Z", + "coverTemplate": { + "id": "6404718a-1b1c-4148-9807-ad3c57a53e0c", + "name": "蓝底白字", + "config": { + "backgroundEnabled": false, + "backgroundImagePath": null, + "backgroundBlurEnabled": false, + "backgroundBlurIntensity": 10, + "backgroundSize": 100, + "backgroundPosition": { + "x": 50, + "y": 50 + }, + "personImagePath": null, + "personSize": 80, + "personPosition": { + "x": 50, + "y": 50 + }, + "personRotation": 0, + "personBorderEnabled": false, + "personBorderStyle": "solid", + "personBorderColor": "#FFFFFF", + "personBorderWidth": 8, + "personBorderDashLength": null, + "personBorderGapLength": null, + "autoSplitText": true, + "titleMaxLength": 4, + "subtitleMaxLength": 5, + "titleText": "礼貌回归", + "titleFontFamily": "USMCCyuanjiantecu", + "titleFontSize": 120, + "titleFontWeight": 700, + "titleColor": "#cbcdb1", + "titleStrokeColor": "#000000", + "titleStrokeWidth": 0, + "titleShadowColor": "#000000", + "titleShadowOffsetX": 0, + "titleShadowOffsetY": 0, + "titleShadowBlur": 0, + "titleShadowEnabled": false, + "titleShadowLayers": [ + { + "id": 1765449844664.8303, + "offsetX": 0, + "offsetY": 0, + "blur": 8, + "color": "#000000", + "opacity": 80, + "enabled": true + }, + { + "id": 1765449844664.415, + "offsetX": 0, + "offsetY": 0, + "blur": 16, + "color": "#000000", + "opacity": 40, + "enabled": true + } + ], + "titlePosition": { + "x": 50.694444444444436, + "y": 63.506944444444436 + }, + "titleRotation": 0, + "titleDirection": "horizontal", + "titleCharSpacing": 24, + "titleLineSpacing": 144, + "titleMaxCharsPerLine": 10, + "titleBackgroundEnabled": false, + "titleBackgroundColor": "#000000", + "titleBackgroundOpacity": 70, + "titleBackgroundShape": "rectangle", + "titleBackgroundSize": { + "width": 30, + "height": 10 + }, + "titleBackgroundPosition": { + "x": 50, + "y": 30 + }, + "titleBackgroundPoints": [], + "titleBackgroundRadius": 10, + "titleBackgroundRotation": 0, + "subtitleText": "行动亲爱的", + "subtitleFontFamily": "千图厚黑体", + "subtitleFontSize": 187, + "subtitleFontWeight": 100, + "subtitleColor": "#FFFFFF", + "subtitleStrokeColor": "#000000", + "subtitleStrokeWidth": 10, + "subtitleShadowColor": "#000000", + "subtitleShadowOffsetX": 0, + "subtitleShadowOffsetY": 0, + "subtitleShadowBlur": 0, + "subtitleShadowEnabled": false, + "subtitleShadowLayers": [], + "subtitlePosition": { + "x": 49.53703703703704, + "y": 74.20138888888889 + }, + "subtitleRotation": 0, + "subtitleDirection": "horizontal", + "subtitleCharSpacing": -23, + "subtitleLineSpacing": 72, + "subtitleMaxCharsPerLine": 15, + "subtitleBackgroundEnabled": true, + "subtitleBackgroundColor": "#599dd9", + "subtitleBackgroundOpacity": 25, + "subtitleBackgroundShape": "rectangle", + "subtitleBackgroundSize": { + "width": 161.0185185185185, + "height": 30.48611111111111 + }, + "subtitleBackgroundPosition": { + "x": 50.23148148148148, + "y": 67.11805555555556 + }, + "subtitleBackgroundPoints": [], + "subtitleBackgroundRadius": 10, + "subtitleBackgroundRotation": 0, + "maskEnabled": false, + "maskImagePath": null, + "maskSize": 100, + "maskPosition": { + "x": 50, + "y": 50 + }, + "maskColor": null, + "maskOpacity": 100, + "maskShape": "rectangle" + } + } +} \ No newline at end of file diff --git a/src/data/cover-templates/cover-template-青蓝虚描.json b/src/data/cover-templates/cover-template-青蓝虚描.json new file mode 100644 index 0000000..b201306 --- /dev/null +++ b/src/data/cover-templates/cover-template-青蓝虚描.json @@ -0,0 +1,167 @@ +{ + "version": "1.0.0", + "description": "封面模板导出配置", + "timestamp": "2026-06-02T12:13:52.918Z", + "coverTemplate": { + "id": "1xwrrcvf7a5-mkdite6i", + "name": "青蓝虚描", + "config": { + "backgroundEnabled": false, + "backgroundImagePath": null, + "backgroundBlurEnabled": true, + "backgroundBlurIntensity": 100, + "backgroundSize": 100, + "backgroundPosition": { + "x": 50, + "y": 50 + }, + "personImagePath": null, + "personSize": 56.73611111111111, + "personPosition": { + "x": 35.87962962962963, + "y": 71.52777777777777 + }, + "personRotation": 0, + "personBorderEnabled": true, + "personBorderStyle": "dashed", + "personBorderColor": "#149fc2", + "personBorderWidth": 14, + "personBorderDashLength": null, + "personBorderGapLength": null, + "autoSplitText": true, + "titleMaxLength": 4, + "subtitleMaxLength": 11, + "titleText": "托德揭秘", + "titleFontFamily": "泼墨体", + "titleFontSize": 115, + "titleFontWeight": 350, + "titleColor": "#149fc2", + "titleStrokeColor": "#000000", + "titleStrokeWidth": 7, + "titleShadowColor": "#000000", + "titleShadowOffsetX": 0, + "titleShadowOffsetY": 0, + "titleShadowBlur": 0, + "titleShadowEnabled": false, + "titleShadowLayers": [ + { + "id": 1765435502861.9124, + "offsetX": -2, + "offsetY": -2, + "blur": 12, + "color": "#000000", + "opacity": 100, + "enabled": true + }, + { + "id": 1765435502861.0488, + "offsetX": 2, + "offsetY": 2, + "blur": 16, + "color": "#000000", + "opacity": 100, + "enabled": true + }, + { + "id": 1765435502861.4207, + "offsetX": 0, + "offsetY": 0, + "blur": 14, + "color": "#000000", + "opacity": 100, + "enabled": true + } + ], + "titlePosition": { + "x": 90.9722222222222, + "y": 34.16666666666667 + }, + "titleRotation": 0, + "titleDirection": "vertical", + "titleCharSpacing": 50, + "titleLineSpacing": 118, + "titleMaxCharsPerLine": 10, + "titleBackgroundEnabled": false, + "titleBackgroundColor": "#000000", + "titleBackgroundOpacity": 70, + "titleBackgroundShape": "rectangle", + "titleBackgroundSize": { + "width": 30, + "height": 10 + }, + "titleBackgroundPosition": { + "x": 50, + "y": 30 + }, + "titleBackgroundPoints": [], + "titleBackgroundRadius": 10, + "titleBackgroundRotation": 0, + "subtitleText": "芒格投资稳的原因", + "subtitleFontFamily": "杨任东竹石体", + "subtitleFontSize": 87, + "subtitleFontWeight": 500, + "subtitleColor": "#149fc2", + "subtitleStrokeColor": "#000000", + "subtitleStrokeWidth": 0, + "subtitleShadowColor": "#000000", + "subtitleShadowOffsetX": 0, + "subtitleShadowOffsetY": 0, + "subtitleShadowBlur": 0, + "subtitleShadowEnabled": false, + "subtitleShadowLayers": [ + { + "id": 1768540523070.3923, + "offsetX": 0, + "offsetY": 0, + "blur": 2, + "color": "#000000", + "opacity": 100, + "enabled": true + }, + { + "id": 1768540523070.0796, + "offsetX": 0, + "offsetY": 0, + "blur": 2, + "color": "#000000", + "opacity": 100, + "enabled": true + } + ], + "subtitlePosition": { + "x": 76.85185185185186, + "y": 58.40277777777778 + }, + "subtitleRotation": 0, + "subtitleDirection": "vertical", + "subtitleCharSpacing": 12, + "subtitleLineSpacing": 72, + "subtitleMaxCharsPerLine": 15, + "subtitleBackgroundEnabled": false, + "subtitleBackgroundColor": "#000000", + "subtitleBackgroundOpacity": 70, + "subtitleBackgroundShape": "rectangle", + "subtitleBackgroundSize": { + "width": 30, + "height": 10 + }, + "subtitleBackgroundPosition": { + "x": 50, + "y": 60 + }, + "subtitleBackgroundPoints": [], + "subtitleBackgroundRadius": 10, + "subtitleBackgroundRotation": 0, + "maskEnabled": false, + "maskImagePath": null, + "maskSize": 100, + "maskPosition": { + "x": 50, + "y": 50 + }, + "maskColor": null, + "maskOpacity": 100, + "maskShape": "rectangle" + } + } +} \ No newline at end of file diff --git a/src/data/cover-templates/cover-template-黄白实描.json b/src/data/cover-templates/cover-template-黄白实描.json new file mode 100644 index 0000000..a282baf --- /dev/null +++ b/src/data/cover-templates/cover-template-黄白实描.json @@ -0,0 +1,176 @@ +{ + "version": "1.0.0", + "description": "封面模板导出配置", + "timestamp": "2026-06-02T12:13:46.948Z", + "coverTemplate": { + "id": "485183be-6eed-4eae-b74a-8591f08b69fa", + "name": "黄白实描", + "config": { + "backgroundEnabled": false, + "backgroundImagePath": null, + "backgroundBlurEnabled": true, + "backgroundBlurIntensity": 30, + "backgroundSize": 100, + "backgroundPosition": { + "x": 50, + "y": 50 + }, + "personImagePath": null, + "personSize": 70.27777777777777, + "personPosition": { + "x": 35.87962962962963, + "y": 64.75694444444444 + }, + "personRotation": 0, + "personBorderEnabled": true, + "personBorderStyle": "solid", + "personBorderColor": "#FFFFFF", + "personBorderWidth": 32, + "personBorderDashLength": null, + "personBorderGapLength": null, + "autoSplitText": true, + "titleMaxLength": 4, + "subtitleMaxLength": 6, + "titleText": "置顶96", + "titleFontFamily": "1.程荣光刻楷", + "titleFontSize": 300, + "titleFontWeight": 1000, + "titleColor": "#ffde05", + "titleStrokeColor": "#000000", + "titleStrokeWidth": 0, + "titleShadowColor": "#000000", + "titleShadowOffsetX": 0, + "titleShadowOffsetY": 0, + "titleShadowBlur": 0, + "titleShadowEnabled": false, + "titleShadowLayers": [ + { + "id": 1765435502861.9124, + "offsetX": -2, + "offsetY": -2, + "blur": 12, + "color": "#000000", + "opacity": 100, + "enabled": true + }, + { + "id": 1765435502861.0488, + "offsetX": 2, + "offsetY": 2, + "blur": 16, + "color": "#000000", + "opacity": 100, + "enabled": true + }, + { + "id": 1765435502861.4207, + "offsetX": 0, + "offsetY": 0, + "blur": 14, + "color": "#000000", + "opacity": 100, + "enabled": true + } + ], + "titlePosition": { + "x": 91.89814814814812, + "y": 66.45833333333334 + }, + "titleRotation": 0, + "titleDirection": "vertical", + "titleCharSpacing": -20, + "titleLineSpacing": 118, + "titleMaxCharsPerLine": 10, + "titleBackgroundEnabled": false, + "titleBackgroundColor": "#000000", + "titleBackgroundOpacity": 70, + "titleBackgroundShape": "rectangle", + "titleBackgroundSize": { + "width": 30, + "height": 10 + }, + "titleBackgroundPosition": { + "x": 50, + "y": 30 + }, + "titleBackgroundPoints": [], + "titleBackgroundRadius": 10, + "titleBackgroundRotation": 0, + "subtitleText": "4高丹草新品", + "subtitleFontFamily": "USMCCyuanjiantecu", + "subtitleFontSize": 117, + "subtitleFontWeight": 500, + "subtitleColor": "#FFFFFF", + "subtitleStrokeColor": "#000000", + "subtitleStrokeWidth": 0, + "subtitleShadowColor": "#000000", + "subtitleShadowOffsetX": 0, + "subtitleShadowOffsetY": 0, + "subtitleShadowBlur": 0, + "subtitleShadowEnabled": false, + "subtitleShadowLayers": [ + { + "id": 1765435591571.2886, + "offsetX": -2, + "offsetY": -2, + "blur": 2, + "color": "#FFFFFF", + "opacity": 60, + "enabled": true + }, + { + "id": 1765435591571.856, + "offsetX": 2, + "offsetY": 2, + "blur": 0, + "color": "#000000", + "opacity": 65, + "enabled": true + }, + { + "id": 1765435591571.3809, + "offsetX": 0, + "offsetY": 0, + "blur": 4, + "color": "#000000", + "opacity": 50, + "enabled": true + } + ], + "subtitlePosition": { + "x": 47.45370370370371, + "y": 12.743055555555557 + }, + "subtitleRotation": 0, + "subtitleDirection": "horizontal", + "subtitleCharSpacing": 12, + "subtitleLineSpacing": 72, + "subtitleMaxCharsPerLine": 15, + "subtitleBackgroundEnabled": false, + "subtitleBackgroundColor": "#000000", + "subtitleBackgroundOpacity": 70, + "subtitleBackgroundShape": "rectangle", + "subtitleBackgroundSize": { + "width": 30, + "height": 10 + }, + "subtitleBackgroundPosition": { + "x": 50, + "y": 60 + }, + "subtitleBackgroundPoints": [], + "subtitleBackgroundRadius": 10, + "subtitleBackgroundRotation": 0, + "maskEnabled": false, + "maskImagePath": null, + "maskSize": 100, + "maskPosition": { + "x": 50, + "y": 50 + }, + "maskColor": null, + "maskOpacity": 100, + "maskShape": "rectangle" + } + } +} \ No newline at end of file diff --git a/src/services/coverGenerate.js b/src/services/coverGenerate.js index b29f6c2..c34347c 100644 --- a/src/services/coverGenerate.js +++ b/src/services/coverGenerate.js @@ -83,8 +83,11 @@ export async function executeGenerateCover(store) { } const stored = store.coverTemplate; - const catalogTpl = getCoverTemplateById(store.coverTemplateId || "default"); - const presetTpl = getCoverTemplate(store.coverTemplateId || "default"); + const defaultTplId = "cover_electron_portrait_center"; + const catalogTpl = getCoverTemplateById( + store.coverTemplateId || defaultTplId, + ); + const presetTpl = getCoverTemplate(store.coverTemplateId || defaultTplId); let rawStyle = stored?.config && typeof stored.config === "object" ? { ...stored.config } @@ -96,10 +99,16 @@ export async function executeGenerateCover(store) { titleMaxLength: Number(rawStyle.titleMaxLength) || 14, subtitleMaxLength: Number(rawStyle.subtitleMaxLength) || 16, }); + /** 与 Electron 一致:仅主标题传入生成器,副标题走 subtitleText / titles.sub */ + const mainTitle = + String(rawStyle.titleText || split.title || titleText).trim() || titleText; + const subtitleForCover = String( + rawStyle.subtitleText || split.subtitle || "", + ).trim(); const effectStyle = normalizeCoverConfigForGenerator({ ...rawStyle, - titleText: rawStyle.titleText || split.title || titleText, - subtitleText: rawStyle.subtitleText || split.subtitle, + titleText: mainTitle, + subtitleText: subtitleForCover, customVideoPath: store.coverCustomVideoPath || "", }); @@ -110,7 +119,7 @@ export async function executeGenerateCover(store) { scriptName: COVER_SCRIPT, params: { videoPath, - titleText, + titleText: mainTitle, effectStyle, }, }); diff --git a/src/services/coverTemplateCatalog.js b/src/services/coverTemplateCatalog.js index cb8ebfa..1fba5cd 100644 --- a/src/services/coverTemplateCatalog.js +++ b/src/services/coverTemplateCatalog.js @@ -1,9 +1,17 @@ import { COVER_TEMPLATES } from "../config/coverTemplates.js"; +import { + ELECTRON_COVER_TEMPLATE_IDS, + loadElectronCoverTemplates, +} from "../config/electronCoverTemplates.js"; import { createDefaultCoverTemplateConfig, isFullCoverTemplateConfig, migrateSimpleCoverConfig, } from "../config/coverTemplateDefaults.js"; +import { + normalizeElectronCoverConfig, + parseElectronCoverExport, +} from "../utils/coverElectronImport.js"; const STORAGE_KEY = "aiclient_custom_cover_templates"; @@ -72,7 +80,13 @@ function describeCoverPreset(tpl) { * @returns {CoverTemplateItem[]} */ export function loadSystemCoverTemplates() { - return COVER_TEMPLATES.map(systemTemplateFromPreset); + const electron = loadElectronCoverTemplates(); + const legacyQuick = COVER_TEMPLATES.map(systemTemplateFromPreset).map((t) => ({ + ...t, + id: `cover_quick_${t.id}`, + description: t.description || "ffmpeg/PIL 快速预设", + })); + return [...electron, ...legacyQuick]; } /** @@ -115,7 +129,10 @@ export function getCoverTemplateById(id) { * @param {string} id */ export function isSystemCoverTemplateId(id) { - return COVER_TEMPLATES.some((t) => t.id === id); + return ( + ELECTRON_COVER_TEMPLATE_IDS.has(id) || + COVER_TEMPLATES.some((t) => t.id === id || `cover_quick_${t.id}` === id) + ); } /** @@ -125,9 +142,12 @@ export function isSystemCoverTemplateId(id) { export function upsertCustomCoverTemplate(template) { const custom = loadCustomCoverTemplates(); const now = Date.now(); - const config = isFullCoverTemplateConfig(template.config) - ? template.config - : migrateSimpleCoverConfig(template.config || {}); + let config = template.config || {}; + if (isFullCoverTemplateConfig(config)) { + config = normalizeElectronCoverConfig(config, { keepSampleText: true }); + } else { + config = migrateSimpleCoverConfig(config); + } const item = { ...template, config, @@ -195,11 +215,40 @@ export function downloadCoverTemplatesJson( export async function parseImportedCoverTemplates(file) { const text = await file.text(); const data = JSON.parse(text); - const list = data.coverTemplates || data.templates || data; - if (!Array.isArray(list)) throw new Error("无效的模板文件格式"); + + if (data?.coverTemplate) { + const [one] = parseElectronCoverExport(data); + return [ + { + ...one, + id: `cover_imported_${Date.now()}`, + isSystem: false, + is_system: 0, + createdAt: Date.now(), + updatedAt: Date.now(), + }, + ]; + } + + let list; + try { + list = parseElectronCoverExport(data); + } catch { + const raw = data.coverTemplates || data.templates || data; + if (!Array.isArray(raw)) throw new Error("无效的模板文件格式"); + list = raw.map((t) => ({ + ...t, + config: isFullCoverTemplateConfig(t.config) + ? normalizeElectronCoverConfig(t.config, { keepSampleText: true }) + : migrateSimpleCoverConfig(t.config || {}), + })); + } + return list.map((t, i) => ({ ...t, - id: t.id || `cover_imported_${Date.now()}_${i}`, + id: t.id?.startsWith("cover_electron_") + ? `cover_imported_${Date.now()}_${i}` + : t.id || `cover_imported_${Date.now()}_${i}`, isSystem: false, is_system: 0, createdAt: t.createdAt || Date.now(), diff --git a/src/stores/workflow.js b/src/stores/workflow.js index c237fe5..e91cf5c 100644 --- a/src/stores/workflow.js +++ b/src/stores/workflow.js @@ -299,7 +299,7 @@ export const useWorkflowStore = defineStore("workflow", { /** 高级封面步骤预览图路径列表(Python 返回) */ coverPreviewImages: [], - coverTemplateId: "default", + coverTemplateId: "cover_electron_portrait_center", /** 当前选中的完整封面模板(封面设置弹窗应用后写入) */ coverTemplate: null, diff --git a/src/utils/coverElectronImport.js b/src/utils/coverElectronImport.js new file mode 100644 index 0000000..ada13b1 --- /dev/null +++ b/src/utils/coverElectronImport.js @@ -0,0 +1,128 @@ +/** + * Electron 封面模板导出格式适配(cover-template-*.json / coverTemplate 单条导出) + */ +import { createDefaultCoverTemplateConfig } from "../config/coverTemplateDefaults.js"; + +/** Electron 模板名 → 稳定 id */ +const ELECTRON_TEMPLATE_IDS = { + 人像居中: "cover_electron_portrait_center", + 大四字报: "cover_electron_big_four_chars", + 斜黄白: "cover_electron_slant_yellow_white", + 粉红虚白: "cover_electron_pink_outline_white", + 红黄虚描: "cover_electron_red_yellow_outline", + 蓝底白字: "cover_electron_blue_bg_white", + 青蓝虚描: "cover_electron_cyan_blue_outline", + 黄白实描: "cover_electron_yellow_white_solid", +}; + +/** + * 规范化 Electron config,供编辑器 / Python 高级生成器使用 + * @param {Record} raw + * @param {{ keepSampleText?: boolean }} [opts] + */ +export function normalizeElectronCoverConfig(raw, opts = {}) { + if (!raw || typeof raw !== "object") { + return createDefaultCoverTemplateConfig(); + } + + const c = createDefaultCoverTemplateConfig({ ...raw }); + + const blurOn = Boolean( + c.backgroundBlurEnabled ?? c.blurBackground ?? true, + ); + c.backgroundBlurEnabled = blurOn; + c.blurBackground = blurOn; + + if (c.extractPerson === undefined || c.extractPerson === null) { + c.extractPerson = true; + } + + if (!c.titleMaxCharsPerLine && c.titleMaxLength) { + c.titleMaxCharsPerLine = Number(c.titleMaxLength); + } + if (!c.subtitleMaxCharsPerLine && c.subtitleMaxLength) { + c.subtitleMaxCharsPerLine = Number(c.subtitleMaxLength); + } + + if (c.personBorderEnabled && !c.personOutlineColor) { + c.personOutlineColor = c.personBorderColor; + c.personOutlineWidth = c.personBorderWidth; + } + + if (Array.isArray(c.titleShadowLayers)) { + c.titleShadowLayers = c.titleShadowLayers.map((layer) => ({ + enabled: layer?.enabled !== false, + offsetX: Number(layer?.offsetX) || 0, + offsetY: Number(layer?.offsetY) || 0, + blur: Number(layer?.blur) || 0, + color: layer?.color || "#000000", + opacity: Number(layer?.opacity ?? 100), + })); + } + if (Array.isArray(c.subtitleShadowLayers)) { + c.subtitleShadowLayers = c.subtitleShadowLayers.map((layer) => ({ + enabled: layer?.enabled !== false, + offsetX: Number(layer?.offsetX) || 0, + offsetY: Number(layer?.offsetY) || 0, + blur: Number(layer?.blur) || 0, + color: layer?.color || "#000000", + opacity: Number(layer?.opacity ?? 100), + })); + } + + if (!opts.keepSampleText) { + c.titleText = ""; + c.subtitleText = ""; + } + + if (c.maskImagePath === null) c.maskImagePath = undefined; + if (c.backgroundImagePath === null) c.backgroundImagePath = undefined; + if (c.personImagePath === null) c.personImagePath = undefined; + if (c.maskColor === null) c.maskColor = undefined; + + return c; +} + +/** + * @param {{ id?: string, name?: string, config?: Record }} item + * @param {{ keepSampleText?: boolean }} [opts] + */ +export function electronCoverItemToTemplate(item, opts = {}) { + const name = String(item?.name || "未命名模板").trim(); + const id = + ELECTRON_TEMPLATE_IDS[name] || + `cover_electron_${name.replace(/\s+/g, "_")}`; + + return { + id, + name, + description: "Electron 系统预设", + config: normalizeElectronCoverConfig(item?.config || {}, opts), + isSystem: true, + is_system: 1, + createdAt: 0, + updatedAt: 0, + }; +} + +/** + * 解析 Electron 导出的 JSON(单条 coverTemplate 或 coverTemplates 数组) + * @param {unknown} data + */ +export function parseElectronCoverExport(data) { + if (!data || typeof data !== "object") { + throw new Error("无效的模板文件格式"); + } + + if (data.coverTemplate && typeof data.coverTemplate === "object") { + return [electronCoverItemToTemplate(data.coverTemplate)]; + } + + const list = + data.coverTemplates || data.templates || (Array.isArray(data) ? data : null); + if (!Array.isArray(list)) { + throw new Error("无效的模板文件格式"); + } + + return list.map((t) => electronCoverItemToTemplate(t)); +}