From 87d3b7fc17d7dcfe04fa09f1f6579aa088343ad2 Mon Sep 17 00:00:00 2001 From: lq1405 <2769838458@qq.com> Date: Mon, 23 Jun 2025 22:08:22 +0800 Subject: [PATCH] =?UTF-8?q?V=203.4.0=201.=20=E6=96=B0=E5=A2=9E=E6=9D=A5?= =?UTF-8?q?=E6=8E=A8=E5=86=85=E7=BD=AE=E8=87=AA=E8=90=A5=E7=94=9F=E5=9B=BE?= =?UTF-8?q?=E5=8C=85=202.=20=E6=96=B0=E5=A2=9E=20=E5=B7=A5=E5=85=B7?= =?UTF-8?q?=E7=AE=B1=20=E8=8F=9C=E5=8D=95=EF=BC=8C=E6=B7=BB=E5=8A=A0=20?= =?UTF-8?q?=E5=9B=BE=E7=89=87=E5=8E=8B=E7=BC=A9=20=E5=92=8C=20LaiTool?= =?UTF-8?q?=E5=9B=BE=E5=BA=8A=EF=BC=88=E7=94=A8=E4=BD=9CMJ=E5=9E=AB?= =?UTF-8?q?=E5=9B=BE=EF=BC=89=203.=20=E6=96=B0=E5=A2=9E=E4=B8=80=E4=B8=AA?= =?UTF-8?q?=E6=96=B0=E7=9A=84=E6=8E=A8=E7=90=86=E6=A8=A1=E5=BC=8F=204.=20?= =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=89=AA=E6=98=A0=E5=85=B3=E9=94=AE=E7=BC=A9?= =?UTF-8?q?=E6=94=BE=E5=A4=A7=E5=B0=8F=E8=AE=A1=E7=AE=97=E9=94=99=E8=AF=AF?= =?UTF-8?q?=205.=20MJ=E7=94=9F=E5=9B=BE=E5=8C=85=E9=80=82=E9=85=8D?= =?UTF-8?q?=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 2 +- resources/scripts/db/book.realm.lock | Bin 1416 -> 1416 bytes resources/scripts/db/software.realm.lock | Bin 1416 -> 1416 bytes resources/tmp/config/global_setting.json | 2 +- src/define/api/apiUrlDefine.ts | 15 +- src/define/data/softawareData.ts | 12 +- src/define/gptDefine.js | 152 ++--- src/main/Public/clipDraft.js | 4 +- src/main/Service/MJ/mj.ts | 3 +- src/main/Service/MJ/mjApi.ts | 29 +- src/renderer/src/common/homeMenu.ts | 320 +++++++++ src/renderer/src/common/toolData.ts | 262 ++++++++ .../components/Backstep/PushBackPrompt.vue | 3 +- src/renderer/src/components/Home/Home.vue | 394 +---------- src/renderer/src/components/Home/HomeMenu.vue | 45 ++ .../src/components/Home/ShowMessage.vue | 77 --- src/renderer/src/components/Icon/ToolBox.vue | 16 + .../ImageCompress/ImageCompressHome.vue | 632 ++++++++++++++++++ .../ToolBox/ImageUpload/ImageDisplay.vue | 403 +++++++++++ .../ToolBox/ImageUpload/ImageUploadHome.vue | 95 +++ .../ToolBox/ImageUpload/ImageUploader.vue | 470 +++++++++++++ .../src/components/ToolBox/ToolBoxHome.vue | 261 ++++++++ .../src/components/ToolBox/ToolGrid.vue | 153 +++++ src/renderer/src/main.js | 20 +- 24 files changed, 2795 insertions(+), 575 deletions(-) create mode 100644 src/renderer/src/common/homeMenu.ts create mode 100644 src/renderer/src/common/toolData.ts create mode 100644 src/renderer/src/components/Home/HomeMenu.vue delete mode 100644 src/renderer/src/components/Home/ShowMessage.vue create mode 100644 src/renderer/src/components/Icon/ToolBox.vue create mode 100644 src/renderer/src/components/ToolBox/ImageCompress/ImageCompressHome.vue create mode 100644 src/renderer/src/components/ToolBox/ImageUpload/ImageDisplay.vue create mode 100644 src/renderer/src/components/ToolBox/ImageUpload/ImageUploadHome.vue create mode 100644 src/renderer/src/components/ToolBox/ImageUpload/ImageUploader.vue create mode 100644 src/renderer/src/components/ToolBox/ToolBoxHome.vue create mode 100644 src/renderer/src/components/ToolBox/ToolGrid.vue diff --git a/package.json b/package.json index 18af8cf..d56b6b1 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "laitool", - "version": "3.3.9", + "version": "3.4.0", "description": "An AI tool for image processing, video processing, and other functions.", "main": "./out/main/index.js", "author": "laitool.cn", diff --git a/resources/scripts/db/book.realm.lock b/resources/scripts/db/book.realm.lock index c1b9debd57b3b4b516bf7aee1aaafbad4bd6d23b..bb9e84c309a54551785eefa053528d9bef3ee4d4 100644 GIT binary patch literal 1416 zcmZQ%(1|Ho}f fFpW+i+y_x-V2^M+y4q3xXb6mkz-R~zg%AJ$C3*-g literal 1416 zcmZQ%)iasvm5o6z+l e+y_yoQOOHdg3BIs{iFQR5Eu=C(GVDHApiiJas}f6 diff --git a/resources/scripts/db/software.realm.lock b/resources/scripts/db/software.realm.lock index 9e7c84629b73fddecf3fa49dfc4770dd33ff9d68..fe9b9e53be9339ee9043bbf47d9ae7d3514869f4 100644 GIT binary patch literal 1416 zcmZQ%vIA9sFgBn76a?7^!XS_cw-@4;9m%W^ g2{aPnK8U&lSrBzFbI_EJaz{g8Gz3ONV9vH(?pFgBooCWx>X;+6$B*ug45ZbAlb baQ8vf9k>Wlhpc9lJsJX|Aut*OLn#CRsSyN} diff --git a/resources/tmp/config/global_setting.json b/resources/tmp/config/global_setting.json index 192a9a2..efb7508 100644 --- a/resources/tmp/config/global_setting.json +++ b/resources/tmp/config/global_setting.json @@ -10,7 +10,7 @@ "translation_secret": "2234", "translation_auto": true, "theme": "light", - "gpt_auto_inference": "storyFirst", + "gpt_auto_inference": "laitoolStoryboardMasterGeneral", "webui_api_url": "你的SD地址(后面要加/)", "gpt_count": 8, "customize_gpt_prompt": "a93b693e-bb3f-406d-9730-cba43a6585a2", diff --git a/src/define/api/apiUrlDefine.ts b/src/define/api/apiUrlDefine.ts index 4c5d32d..e0711b6 100644 --- a/src/define/api/apiUrlDefine.ts +++ b/src/define/api/apiUrlDefine.ts @@ -61,6 +61,19 @@ let apiUrl = [ d3_url: null, buy_url: 'https://www.volcengine.com/product/doubao' }, + { + label: 'LaiTool生图包', + value: '9c9023bd-871d-4b63-8004-facb3b66c5b3', + isPackage: true, + mj_url: { + imagine: 'https://lms.laitool.cn/api/mjPackage/mj/submit/imagine', + describe: 'https://lms.laitool.cn/api/mjPackage/mj/submit/describe', + update_file: 'https://lms.laitool.cn/api/mjPackage/mj/submit/upload-discord-images', + once_get_task: 'https://lms.laitool.cn/api/mjPackage/mj/task/${id}/fetch', + query_url: "https://lms.laitool.cn/mjp/task" + }, + buy_url: 'https://rvgyir5wk1c.feishu.cn/wiki/P94OwwHuCi2qh8kADutcUuw4nUe' + }, { label: 'MJ生图包-1', value: 'babe557a-bbb8-4aed-acca-70ea068c156f', @@ -73,7 +86,7 @@ let apiUrl = [ query_url: "https://mjapi.bzu.cn/" }, buy_url: 'https://rvgyir5wk1c.feishu.cn/wiki/P94OwwHuCi2qh8kADutcUuw4nUe' - }, + } ] /** diff --git a/src/define/data/softawareData.ts b/src/define/data/softawareData.ts index e9f6724..ebc064c 100644 --- a/src/define/data/softawareData.ts +++ b/src/define/data/softawareData.ts @@ -1,10 +1,12 @@ export const SoftwareData = { - "version": "V3.3.9", - "date": "2025-05-29", + "version": "V3.4.0", + "date": "2025-06-23", "notes": [ - "修复了音频处理的错误。", - "改进了视频处理的性能。", - "更新了依赖库以提高安全性。" + "1. 新增来推内置自营生图包", + "2. 新增 工具箱 菜单,添加 图片压缩 和 LaiTool图床(用作MJ垫图)", + "3. 新增一个新的推理模式", + "4. 修复剪映关键缩放大小计算错误", + "5. MJ生图包适配修改" ] } \ No newline at end of file diff --git a/src/define/gptDefine.js b/src/define/gptDefine.js index 1bd04d0..96033b7 100644 --- a/src/define/gptDefine.js +++ b/src/define/gptDefine.js @@ -334,108 +334,64 @@ export const gptDefine = { 再次强调!提示词中严禁输出“无“字,如出现“无“字,请删除“无“及其前面的逗号!提示词中严禁出现灯光、情绪、氛围等非视觉元素的描述。 `, - superSinglePromptSystemContent: { - prompt_name: '分镜大师', - prompt_roles: `1# Role: 小说转漫画提示词大师 - ## Profile - *Version*: 0.1 - *Language*: 中文 - *Description*: 这个角色会将用户输入的小说文本转化为一个生动的画面描写,最后生成对应的SD提示词。 - - ## Features - - 1. 文本转化为画面描写:创作引人入胜、生动有趣的画面描写,善于创意想象并使用各种形容词,以第三人称视角转化文本为画面描写。 - 2. 从画面描写到SD提示词:根据画面描写生成图像提示,主要的提示放在前面,次要的放在后面。命令以英语表示,简洁明了。 - - ## Rules - - 1. 一个文本就是一副画面,不跳过任何一个句子,不能编造 - 2. 【画面描写】删除人物姓名 - 3. 【画面描写】删除人物对话 - 4. 【画面描写】每一句都要有人物的外形和动作的描写,场景的具体描写,多使用形容词 - 5. SD提示词需以""开始,以" ,"结束 - 6. SD提示词用english输出,没有说明性词汇,没有对话 - 7 删除MJ提示词中的其他风格词。 - - ## Examples - - 用户: - 在那个梦里,我整整学了七年炒饭。 - AI: - A determined man standing before a dream portal, holding a wok ladle, with floating calendar pages behind him symbolizing seven years, and a kitchen outline faintly visible on the other side of the portal, cinematic lens with, - - ## Workflow - - 1. 根据画面描写生成SD提示词,英文输出,不能出现中文。 - - ## Initialization - - 作为角色 ,每一次输出都要严格遵守,一步一步思考,按顺序执行 ,使用默认 ,下面是小说文本:`, - prompt_example: [ - { - user_content: '上研究生后。发现导师竟然是曾经网恋的前男友。', - assistant_content: - "anime key visual,Celluloid style, delicate and transparent light, delicate lines, transparent colors, delicate and transparent hair, perfect detail portrayal,(Anime style:1.3), A woman entering a spacious, well-lit graduate laboratory, gaze fixed on a man diligently working at a workstation ahead - her new mentor; he stands tall in a dark shirt and neatly pressed trousers, exuding professionalism and charm; the familiar contours of his profile from their past online romance softly illuminated by warm ambient light, furrowed brow and intense gaze betraying a scholar's unwavering dedication; bustling graduate students and sophisticated equipment blend into a contemporary academic tableau, as an undercurrent of mixed emotions - sweet nostalgia and awkward reality - surges within her heart, " - } - ], - id: 'a93b693e-bb3f-406d-9730-cba43a6585e4' - }, + laitoolTextToCartoonSystemContent: ` + # Role: 小说转漫画提示词大师(优化版) - superSinglePromptChineseSystemContent: { - prompt_name: '超级无敌单帧-中文版', - prompt_roles: `# Role: 小说转漫画提示词大师 - ## Profile +## Profile +*Version*: 0.2 +*Language*: 中文 +*Description*: 将小说文本转化为连贯的漫画提示词,具备人物特征一致性、场景关联性和风格自适应性 - *Author*: laolu - *Version*: 0.1 - *Language*: 中文 - *Description*: 这个角色会将用户输入的小说文本转化为一个生动的画面描写,最后生成对应的SD提示词。 +## 核心优化功能 +1. 人物特征数据库:自动建立并维护角色形象档案 +2. 多人物关系推理:智能识别互动场景 +3. 动态风格调整:根据文本类型匹配特效程度 +4. 跨场景连续性:保持环境元素连贯性 +5. 安全内容过滤:自动规避违规描述 - ## Features +## 生成规则 +1. 直接输出中文提示词,无需分段标签 +2. 格式固定:年龄+性别+外貌特征+着装+动作+场景+(特效) +3. 玄幻类可添加"特效注释"但需用括号标明 +4. 严格避免:血腥细节、裸露描写、现实暴力 +5. 自动继承前文出现的角色特征 - 1. 文本转化为画面描写:创作引人入胜、生动有趣的画面描写,善于创意想象并使用各种形容词,以第三人称视角转化文本为画面描写。 +## 工作流程 +1. 首次出现角色:创建特征档案 +2. 后续出现:调用档案并更新状态 +3. 场景转换:保留合理的环境过渡元素 +4. 战斗场景:用"能量光效"替代血腥描写 +5. 系统元素:用"半透明界面"表现 - ## Rules +## 示例库 - 1. 一个文本就是一副画面,不跳过任何一个句子,不能编造 - 2. 【画面描写】删除人物姓名 - 3. 【画面描写】删除人物对话 - 4. 【画面描写】每一句都要有人物的外形和动作的描写,场景的具体描写,多使用形容词 +[末世求生类] +"二十岁左右男性,黑色短发,眼神锐利,穿着破损的战术背心,手持散发蓝光的武士刀,站在废弃加油站顶部,脚下环绕着失去行动能力的丧尸(系统特效:刀身缠绕数据流状光芒)" - ## Examples +"二十五岁女性,红色马尾辫,穿着改装皮甲,肩抗火箭筒,站在燃烧的装甲车顶上,背后夜空被爆炸的火光照亮(系统界面:左侧漂浮着不断跳动的击杀统计)" - 用户: - 在那个梦里,我整整学了七年炒饭。 - AI: - 一个身材高大的帅气男人站在梦境之门前,手中紧握炒饭的铲子。身后是一排代表七年的日历页,梦境之门的另一边,隐约可见一个厨房的轮廓。 +[玄幻修真类] +"十七岁少年,凌乱白发,瞳孔泛金,穿着残破的宗门服饰,掌心凝聚着漩涡状灵气,站在万丈悬崖边缘(特效:周身环绕古老符文锁链)" - ## Workflow +"三百岁女修士,银色长发及腰,眉间朱砂印记,穿着流光仙裙,脚踏玉如意飞行法宝,下方云海翻腾(特效:法宝拖尾带有星尘轨迹)" - 根据文本生成对应的画面描写,直接使用中文数据,不要又过多的说明。 +[都市言情类] +"二十八岁男性,微卷棕发,穿着皱巴巴的白衬衫,靠在深夜办公室的落地窗前,手中威士忌酒杯映着城市灯光" - ## Initialization +"二十二岁女性,齐肩黑发,戴着圆框眼镜,穿着宽松毛衣在图书馆踮脚取书,阳光透过书架形成光柱" - 作为角色 ,每一次输出都要严格遵守,一步一步思考,按顺序执行 ,使用默认 ,下面是小说文本:`, - prompt_example: [ - { - user_content: '上研究生后。发现导师竟然是曾经网恋的前男友。', - assistant_content: - '一位女士走进一间宽敞、光线充足的研究生实验室,她的目光定格在前方工作台前一位正在辛勤工作的男士身上--他是她的新导师;他身着深色衬衫和熨烫整齐的长裤,身材高大,散发着专业精神和魅力; 温暖的环境光柔和地照亮了他们过去网恋时熟悉的轮廓,皱起的眉头和专注的目光透露出学者坚定不移的奉献精神;熙熙攘攘的研究生和精密的设备融为一体,构成了一幅现代学术画卷,她的内心涌动着甜蜜的怀旧和尴尬的现实这两种复杂的情绪' - }, - { - user_content: '我欲哭无泪', - assistant_content: - '一位女士坐在昏暗的房间角落,双手紧握,眼神空洞,脸上流露出无法言说的悲伤;她的周围是散乱的家具和昏黄的灯光,营造出一种压抑和孤寂的氛围;她的身体微微前倾,仿佛承受着巨大的心理压力,却无法找到宣泄的出口;整个场景透露出一种深深的无奈和心碎,她的表情和姿态都在无声地诉说着“我欲哭无泪”的绝望。' - }, - { - user_content: '被窝里他搂着我的腰亲我,再丢掉我,就把你锁起来。', - assistant_content: - '在昏暗的卧室中,一对情侣亲密地依偎在温暖的被窝里,男子温柔地搂着女子的腰,轻吻她的脸颊,气氛温馨而浪漫;然而,随着话语的转变,男子的动作突然变得愤怒,他用力地推开女子,眼神中闪过一丝威胁;女子的表情由幸福转为惊恐,她紧紧抓住被单,试图保护自己;整个场景充满了紧张和不安,昏暗的灯光和凌乱的床铺加剧了这种氛围,仿佛预示着即将发生的冲突和束缚' - } - ], - id: 'a93b693e-bb3f-406d-9730-cba43a6585e7' - }, +## 异常处理 +1. 检测到暴力内容 → 转换为"失去行动能力的敌人" +2. 检测到暴露着装 → 调整为"得体服装" +3. 检测到现实敏感元素 → 替换为科幻/奇幻等效元素 +## 初始化声明 +请提供需要转换的小说文本,我将输出符合安全规范且保持故事连续性的漫画提示词,只输出提示词,不用输出故事类别提示。首次出现的角色将自动建档,后续提示会保持特征一致。 + `, + + laitoolTextToCartoonUserContent: ` + {textContent} + `, // 小说提示词-仅出词 onlyPromptMJSystemContent: { prompt_name: '小说提示词-仅出词', @@ -1053,9 +1009,7 @@ export const gptDefine = { * @param {*} replacements */ GetExamplePromptMessage(type) { - if (type == 'superSinglePrompt') { - return this.CustomizeGptPrompt(this.superSinglePromptSystemContent) - } else if (type == 'onlyPromptMJ') { + if (type == 'onlyPromptMJ') { return this.CustomizeGptPrompt(this.onlyPromptMJSystemContent) } else if (type == 'superSinglePromptChinese') { return this.CustomizeGptPrompt(this.superSinglePromptChineseSystemContent) @@ -1090,14 +1044,14 @@ export const gptDefine = { return this.replace(this.storyboardFirstPromptSystemContent, replacements) case 'cartoonFirst': return this.replace(this.cartoonFirstPromptSystemContent, replacements) - case 'superSinglePrompt': - return this.replace(this.superSinglePromptSystemContent, replacements) case 'superSinglePromptChinese': return this.replace(this.superSinglePromptChineseSystemContent, replacements) case 'laitoolStoryboardMasterSpecialEffects': return this.replace(this.laitoolStoryboardMasterSpecialEffectsSystemContent, replacements) case 'laitoolStoryboardMasterGeneral': return this.replace(this.laitoolStoryboardMasterGeneralSystemContent, replacements) + case 'laitoolTextToCartoon': + return this.replace(this.laitoolTextToCartoonSystemContent, replacements) default: throw new Error(`不存在的类型 : ${type}`) } @@ -1125,6 +1079,8 @@ export const gptDefine = { return this.replace(this.laitoolStoryboardMasterSpecialEffectsUserContent, replacements) case 'laitoolStoryboardMasterGeneral': return this.replace(this.laitoolStoryboardMasterGeneralUserContent, replacements) + case 'laitoolTextToCartoon': + return this.replace(this.laitoolTextToCartoonUserContent, replacements) default: throw new Error(`不存在的类型 : ${type}`) } @@ -1172,10 +1128,6 @@ export const gptDefine = { value: 'cartoonFirst', label: '漫画优先(全自动)' }, - { - value: 'superSinglePrompt', - label: '超级无敌单帧' - }, { value: 'laitoolStoryboardMasterSpecialEffects', label: 'Laitool分镜大师-特效加强' @@ -1184,6 +1136,10 @@ export const gptDefine = { value: 'laitoolStoryboardMasterGeneral', label: 'Laitool分镜大师-全面版' }, + { + value: 'laitoolTextToCartoon', + label: 'Laitool文本转漫画提示词大师' + }, { value: 'superSinglePromptChinese', label: '超级无敌单帧-中文版' diff --git a/src/main/Public/clipDraft.js b/src/main/Public/clipDraft.js index d7b09f0..d1cbf16 100644 --- a/src/main/Public/clipDraft.js +++ b/src/main/Public/clipDraft.js @@ -773,8 +773,8 @@ export class ClipDraft { // 计算方式和上面的不同 let sub_total = Math.abs(up_pos - down_pos); let currwnt_rate = sub_total * (1 - time_rate); - up_pos = up_pos + currwnt_rate / 2; - down_pos = down_pos - currwnt_rate / 2; + up_pos = up_pos - (up_pos * (currwnt_rate / up_pos)) / 2; + down_pos = down_pos + (down_pos * (currwnt_rate / down_pos)) / 2; } // 修改上面的数据,添加Y轴缩放 diff --git a/src/main/Service/MJ/mj.ts b/src/main/Service/MJ/mj.ts index 41e2d35..6c3121f 100644 --- a/src/main/Service/MJ/mj.ts +++ b/src/main/Service/MJ/mj.ts @@ -491,8 +491,7 @@ export class MJOpt { } } //#endregion - - + //#region MJ生成图片相关 /** * 单个生成图片,将任务添加到队列中 diff --git a/src/main/Service/MJ/mjApi.ts b/src/main/Service/MJ/mjApi.ts index 45d6c1b..574704a 100644 --- a/src/main/Service/MJ/mjApi.ts +++ b/src/main/Service/MJ/mjApi.ts @@ -280,15 +280,36 @@ class MJApi { } as MJ.MJResponseToFront // 生图包的处理 - - if (resData.isYouChuan && resData.youChuanTaskId && resData.youChuanTaskInfo && resData.youChuanTaskInfo.imgUrls && resData.youChuanTaskInfo.imgUrls.length == 4) { - + if (resData.isYouChuan + && resData.youChuanTaskId + && resData.youChuanTaskInfo + && resData.youChuanTaskInfo.imgUrls + && resData.youChuanTaskInfo.imgUrls.length == 4) { // 满足指定条件的数据才能返回 - let tempRes = resData.youChuanTaskInfo.imgUrls .filter(item => item.status == 'ok') .map(item => item.url); resObj.subImagePath = tempRes + } else if (resData.isPartner + && resData.partnerTaskId + && resData.partnerTaskInfo + && resData.partnerTaskInfo.imgUrls + && resData.partnerTaskInfo.imgUrls.length == 4) { + // 满足指定条件的数据才能返回 + let tempRes = resData.partnerTaskInfo.imgUrls + .filter(item => item.status == 'ok') + .map(item => item.url); + resObj.subImagePath = tempRes + } else if (resData.isOfficial + && resData.officialTaskId + && resData.officialTaskInfo + && resData.officialTaskInfo.imgUrls + && resData.officialTaskInfo.imgUrls.length == 4) { + // 满足指定条件的数据才能返回 + let tempRes = resData.officialTaskInfo.imgUrls + .filter(item => item.status == 'ok') + .map(item => item.url); + resObj.subImagePath = tempRes } return resObj diff --git a/src/renderer/src/common/homeMenu.ts b/src/renderer/src/common/homeMenu.ts new file mode 100644 index 0000000..0174c6d --- /dev/null +++ b/src/renderer/src/common/homeMenu.ts @@ -0,0 +1,320 @@ +import { h } from 'vue' +import { RouterLink } from 'vue-router' +import { NIcon } from 'naive-ui' +import { + CaretDownOutline, + HomeOutline, + PaperPlaneOutline, + SettingsOutline, + DuplicateOutline, + GridOutline, + RadioOutline, + BookOutline +} from '@vicons/ionicons5' +import APIIcon from '../components/Icon/APIIcon.vue' +import BackTaskIcon from '../components/Icon/BackTaskIcon.vue' +import ToolBox from '../components/Icon/ToolBox.vue' + +// 菜单数据源 - 纯数据配置 +export const menuDataSource = [ + { + label: '首页', + key: 'mainHome', + routeName: 'mainHome', + type: 'route', + icon: 'home', + className: 'router-link-a' + }, + { + label: '文案处理', + key: 'gptCopywriting', + routeName: 'gptCopywriting', + type: 'route', + icon: 'book', + className: 'router-link-a' + }, + { + label: '原创生图(弃用)', + key: 'sdoriginal', + routeName: 'sdoriginal', + type: 'route', + icon: 'plane', + showCondition: 'showOriginal' + }, + { + label: '超级矩阵', + key: 'backward_matrix', + type: 'group', + icon: 'duplicate', + children: [ + { + label: '抽帧', + key: 'backward_frame', + routeName: 'getframe', + type: 'route' + }, + { + label: '文案洗稿', + key: 'copywriting', + routeName: 'copywriting', + type: 'route' + }, + { + label: '反推提示词', + key: 'push_back', + routeName: 'pushBackPrompt', + type: 'route' + }, + { + label: '批次生成', + key: 'regenerate', + routeName: 'regenerate', + type: 'route' + }, + { + label: '重绘/视频合成', + key: 'VideoGenerate', + routeName: 'VideoGenerate', + type: 'route' + } + ] + }, + { + label: '聚合推文', + key: 'book_management', + routeName: 'book_management', + type: 'route', + icon: 'grid' + }, + { + label: 'API服务', + key: 'lai_api', + routeName: 'lai_api', + type: 'route', + icon: 'api' + }, + { + label: '语音服务', + key: 'TTS_Services', + routeName: 'TTS_Services', + type: 'route', + icon: 'radio' + }, + { + label: '设置', + key: 'setting', + type: 'group', + icon: 'settings', + children: [ + { + label: '通用设置', + key: 'global_setting', + routeName: 'global_setting', + type: 'route' + }, + { + label: '剪映设置', + key: 'clip_setting', + routeName: 'clip_setting', + type: 'route' + }, + { + label: '生成视频设置', + key: 'videogeneratesetting', + routeName: 'videogeneratesetting', + type: 'route' + }, + { + label: 'SD设置', + key: 'sd_setting', + routeName: 'sd_setting', + type: 'route', + className: 'sd_setting' + }, + { + label: 'MJ设置', + key: 'mj_setting', + routeName: 'mj_setting', + type: 'route' + } + ] + }, + { + label: '后台任务', + key: 'back_task', + type: 'action', + icon: 'backTask', + style: 'font-weight: bold;', + showCondition: 'always' + }, + { + label: '工具箱', + key: 'toolbox', + routeName: 'toolbox', + type: 'route', + icon: 'toolBox' + } +] + +// 图标映射 +const iconMap = { + home: HomeOutline, + book: BookOutline, + plane: PaperPlaneOutline, + duplicate: DuplicateOutline, + grid: GridOutline, + api: APIIcon, + radio: RadioOutline, + settings: SettingsOutline, + backTask: BackTaskIcon, + toolBox: ToolBox, +} + +// 渲染函数 - 根据数据源渲染菜单项 +export function renderMenuLabel(item, options) { + // 修复:提供默认值 + const opts = options || {} + const onBackTaskClick = opts.onBackTaskClick + + switch (item.type) { + case 'route': + return () => + h( + RouterLink, + { + to: { name: item.routeName }, + class: item.className || '' + }, + { default: () => item.label } + ) + + case 'action': + if (item.key === 'back_task') { + return () => + h( + 'div', + { + onClick: () => { + if (onBackTaskClick) { + onBackTaskClick() + } + }, + style: item.style || '' + }, + { default: () => item.label } + ) + } + break + + case 'group': + default: + return item.label + } +} + +// 渲染图标函数 +export function renderMenuIcon(option, options) { + // 修复:提供默认值 + const opts = options || {} + const onBackTaskClick = opts.onBackTaskClick + + // 特殊处理 + if (option.key === 'sheep-man') return true + if (option.key === 'food') return null + + // 后台任务特殊处理 + if (option.key === 'back_task') { + return h( + NIcon, + { + onClick: () => { + if (onBackTaskClick) { + onBackTaskClick() + } + } + }, + { default: () => h(BackTaskIcon) } + ) + } + + // 根据数据源查找图标 + const menuItem = findMenuItemByKey(option.key) + if (menuItem && menuItem.icon) { + const IconComponent = iconMap[menuItem.icon] + if (IconComponent) { + return h(NIcon, null, { default: () => h(IconComponent) }) + } + } + + return null +} + +// 展开图标 +export function expandIcon() { + return h(NIcon, null, { default: () => h(CaretDownOutline) }) +} + +// 辅助函数:根据key查找菜单项 +function findMenuItemByKey(key) { + function findInItems(items) { + for (const item of items) { + if (item.key === key) return item + if (item.children) { + const found = findInItems(item.children) + if (found) return found + } + } + return null + } + return findInItems(menuDataSource) +} + +// 菜单过滤函数 +function shouldShowMenuItem(item, conditions) { + // 修复:提供默认值 + const conds = conditions || {} + + if (!item.showCondition) return true + + switch (item.showCondition) { + case 'showOriginal': + return conds.showOriginal + case 'always': + return true + default: + return true + } +} + +// 转换数据源为菜单选项 +function transformMenuItem(item, options) { + // 修复:提供默认值 + const opts = options || {} + const onBackTaskClick = opts.onBackTaskClick + const conditions = opts.conditions || {} + + const menuItem = { + key: item.key, + label: renderMenuLabel(item, { onBackTaskClick }), + children: undefined, + } + + // 处理子菜单 + if (item.children) { + menuItem.children = item.children + .filter(child => shouldShowMenuItem(child, conditions)) + .map(child => transformMenuItem(child, opts)) + } + + return menuItem +} + +// 主要的菜单选项生成函数 +export function generateMenuOptions(showOriginal = true, onBackTaskClick) { + const conditions = { showOriginal } + const options = { onBackTaskClick, conditions } + + return menuDataSource + .filter(item => shouldShowMenuItem(item, conditions)) + .map(item => transformMenuItem(item, options)) +} \ No newline at end of file diff --git a/src/renderer/src/common/toolData.ts b/src/renderer/src/common/toolData.ts new file mode 100644 index 0000000..3aa34f0 --- /dev/null +++ b/src/renderer/src/common/toolData.ts @@ -0,0 +1,262 @@ +import { + ImageOutline, + VideocamOutline, + MusicalNotesOutline, + DocumentTextOutline, + CodeSlashOutline, + ColorPaletteOutline, + CalculatorOutline, + GlobeOutline, + LockClosedOutline, + TimeOutline, + ArchiveOutline, + SettingsOutline, + CloudUploadOutline +} from '@vicons/ionicons5' + +// 工具分类 +export const categories = [ + { key: 'media', label: '媒体工具', color: '#2080f0' }, + // { key: 'document', label: '文档处理', color: '#18a058' }, + // { key: 'development', label: '开发工具', color: '#f0a020' }, + // { key: 'design', label: '设计工具', color: '#d03050' }, + // { key: 'utility', label: '实用工具', color: '#7c3aed' }, + // { key: 'network', label: '网络工具', color: '#0ea5e9' }, + // { key: 'security', label: '安全工具', color: '#dc2626' }, + // { key: 'system', label: '系统工具', color: '#059669' } +] + +// 工具数据 +export const toolsData = [ + // 媒体工具 + { + id: 'image-converter', + name: 'LaiTool 图床', + description: "将图片上传到 LaiTool 图床,支持多种图片格式,获得可分享的链接", + category: 'media', + icon: CloudUploadOutline, + color: '#2080f0', + tags: ['图片', '转换', '格式'], + quickAccess: true, + action: { + type: 'route', + route: '/toolbox/image-upload' + } + }, + { + id: 'image-compress', + name: '图片压缩助手', + description: "将图片进行压缩,支持多种图片格式,减小文件大小", + category: 'media', + icon: CloudUploadOutline, + color: '#2080f0', + tags: ['图片', '压缩', '格式'], + quickAccess: true, + action: { + type: 'route', + route: '/toolbox/image-compress' + } + }, + // { + // id: 'image-converter', + // name: '图片格式转换', + // description: '支持多种图片格式之间的转换,包括JPG、PNG、WebP、SVG等', + // category: 'media', + // icon: ImageOutline, + // color: '#2080f0', + // tags: ['图片', '转换', '格式'], + // quickAccess: true, + // action: { + // type: 'route', + // route: '/toolbox/image-converter' + // } + // }, + // { + // id: 'image-compressor', + // name: '图片压缩', + // description: '无损或有损压缩图片文件,减小文件大小', + // category: 'media', + // icon: ImageOutline, + // color: '#18a058', + // tags: ['图片', '压缩', '优化'], + // action: { + // type: 'route', + // route: '/toolbox/image-compressor' + // } + // }, + // { + // id: 'video-converter', + // name: '视频格式转换', + // description: '转换视频文件格式,支持MP4、AVI、MOV等主流格式', + // category: 'media', + // icon: VideocamOutline, + // color: '#f0a020', + // tags: ['视频', '转换', '格式'], + // action: { + // type: 'route', + // route: '/toolbox/video-converter' + // } + // }, + // { + // id: 'audio-converter', + // name: '音频格式转换', + // description: '转换音频文件格式,支持MP3、WAV、FLAC等格式', + // category: 'media', + // icon: MusicalNotesOutline, + // color: '#d03050', + // tags: ['音频', '转换', '格式'], + // action: { + // type: 'route', + // route: '/toolbox/audio-converter' + // } + // }, + + // // 文档工具 + // { + // id: 'pdf-merger', + // name: 'PDF合并', + // description: '将多个PDF文件合并为一个文件', + // category: 'document', + // icon: DocumentTextOutline, + // color: '#18a058', + // tags: ['PDF', '合并', '文档'], + // quickAccess: true, + // action: { + // type: 'route', + // route: '/toolbox/pdf-merger' + // } + // }, + // { + // id: 'pdf-splitter', + // name: 'PDF分割', + // description: '将PDF文件按页数或书签分割成多个文件', + // category: 'document', + // icon: DocumentTextOutline, + // color: '#7c3aed', + // tags: ['PDF', '分割', '文档'], + // action: { + // type: 'route', + // route: '/toolbox/pdf-splitter' + // } + // }, + + // // 开发工具 + // { + // id: 'json-formatter', + // name: 'JSON格式化', + // description: '格式化、验证和美化JSON数据', + // category: 'development', + // icon: CodeSlashOutline, + // color: '#f0a020', + // tags: ['JSON', '格式化', '开发'], + // quickAccess: true, + // action: { + // type: 'route', + // route: '/toolbox/json-formatter' + // } + // }, + // { + // id: 'base64-encoder', + // name: 'Base64编解码', + // description: '对文本或文件进行Base64编码和解码', + // category: 'development', + // icon: CodeSlashOutline, + // color: '#2080f0', + // tags: ['Base64', '编码', '解码'], + // action: { + // type: 'route', + // route: '/toolbox/base64-encoder' + // } + // }, + + // // 设计工具 + // { + // id: 'color-picker', + // name: '颜色选择器', + // description: '选择颜色并获取各种格式的颜色值', + // category: 'design', + // icon: ColorPaletteOutline, + // color: '#d03050', + // tags: ['颜色', '设计', '取色'], + // action: { + // type: 'route', + // route: '/toolbox/color-picker' + // } + // }, + + // // 实用工具 + // { + // id: 'calculator', + // name: '计算器', + // description: '多功能计算器,支持基础运算和科学计算', + // category: 'utility', + // icon: CalculatorOutline, + // color: '#7c3aed', + // tags: ['计算', '数学', '实用'], + // action: { + // type: 'function', + // handler: () => { + // alert('打开计算器') + // } + // } + // }, + // { + // id: 'timestamp-converter', + // name: '时间戳转换', + // description: '时间戳与日期时间之间的相互转换', + // category: 'utility', + // icon: TimeOutline, + // color: '#0ea5e9', + // tags: ['时间', '转换', '时间戳'], + // action: { + // type: 'route', + // route: '/toolbox/timestamp-converter' + // } + // }, + + // // 网络工具 + // { + // id: 'qr-generator', + // name: '二维码生成器', + // description: '生成各种类型的二维码', + // category: 'network', + // icon: GlobeOutline, + // color: '#0ea5e9', + // tags: ['二维码', '生成', '网络'], + // action: { + // type: 'route', + // route: '/toolbox/qr-generator' + // } + // }, + + // // 安全工具 + // { + // id: 'password-generator', + // name: '密码生成器', + // description: '生成安全性高的随机密码', + // category: 'security', + // icon: LockClosedOutline, + // color: '#dc2626', + // tags: ['密码', '生成', '安全'], + // quickAccess: true, + // action: { + // type: 'route', + // route: '/toolbox/password-generator' + // } + // }, + + // // 系统工具 + // { + // id: 'file-hasher', + // name: '文件哈希计算', + // description: '计算文件的MD5、SHA1、SHA256等哈希值', + // category: 'system', + // icon: ArchiveOutline, + // color: '#059669', + // tags: ['哈希', '文件', '校验'], + // action: { + // type: 'route', + // route: '/toolbox/file-hasher' + // } + // } +] \ No newline at end of file diff --git a/src/renderer/src/components/Backstep/PushBackPrompt.vue b/src/renderer/src/components/Backstep/PushBackPrompt.vue index 952d015..f11be82 100644 --- a/src/renderer/src/components/Backstep/PushBackPrompt.vue +++ b/src/renderer/src/components/Backstep/PushBackPrompt.vue @@ -15,9 +15,8 @@ + \ No newline at end of file diff --git a/src/renderer/src/components/Home/HomeMenu.vue b/src/renderer/src/components/Home/HomeMenu.vue new file mode 100644 index 0000000..523569b --- /dev/null +++ b/src/renderer/src/components/Home/HomeMenu.vue @@ -0,0 +1,45 @@ + + + diff --git a/src/renderer/src/components/Home/ShowMessage.vue b/src/renderer/src/components/Home/ShowMessage.vue deleted file mode 100644 index d258b1c..0000000 --- a/src/renderer/src/components/Home/ShowMessage.vue +++ /dev/null @@ -1,77 +0,0 @@ - - - diff --git a/src/renderer/src/components/Icon/ToolBox.vue b/src/renderer/src/components/Icon/ToolBox.vue new file mode 100644 index 0000000..5035157 --- /dev/null +++ b/src/renderer/src/components/Icon/ToolBox.vue @@ -0,0 +1,16 @@ + diff --git a/src/renderer/src/components/ToolBox/ImageCompress/ImageCompressHome.vue b/src/renderer/src/components/ToolBox/ImageCompress/ImageCompressHome.vue new file mode 100644 index 0000000..db1e86c --- /dev/null +++ b/src/renderer/src/components/ToolBox/ImageCompress/ImageCompressHome.vue @@ -0,0 +1,632 @@ + + + + + \ No newline at end of file diff --git a/src/renderer/src/components/ToolBox/ImageUpload/ImageDisplay.vue b/src/renderer/src/components/ToolBox/ImageUpload/ImageDisplay.vue new file mode 100644 index 0000000..74af957 --- /dev/null +++ b/src/renderer/src/components/ToolBox/ImageUpload/ImageDisplay.vue @@ -0,0 +1,403 @@ + + + + + diff --git a/src/renderer/src/components/ToolBox/ImageUpload/ImageUploadHome.vue b/src/renderer/src/components/ToolBox/ImageUpload/ImageUploadHome.vue new file mode 100644 index 0000000..afdffdb --- /dev/null +++ b/src/renderer/src/components/ToolBox/ImageUpload/ImageUploadHome.vue @@ -0,0 +1,95 @@ + + + + + diff --git a/src/renderer/src/components/ToolBox/ImageUpload/ImageUploader.vue b/src/renderer/src/components/ToolBox/ImageUpload/ImageUploader.vue new file mode 100644 index 0000000..2c6b317 --- /dev/null +++ b/src/renderer/src/components/ToolBox/ImageUpload/ImageUploader.vue @@ -0,0 +1,470 @@ + + + + + diff --git a/src/renderer/src/components/ToolBox/ToolBoxHome.vue b/src/renderer/src/components/ToolBox/ToolBoxHome.vue new file mode 100644 index 0000000..082012d --- /dev/null +++ b/src/renderer/src/components/ToolBox/ToolBoxHome.vue @@ -0,0 +1,261 @@ + + + + + diff --git a/src/renderer/src/components/ToolBox/ToolGrid.vue b/src/renderer/src/components/ToolBox/ToolGrid.vue new file mode 100644 index 0000000..583696f --- /dev/null +++ b/src/renderer/src/components/ToolBox/ToolGrid.vue @@ -0,0 +1,153 @@ + + + + + diff --git a/src/renderer/src/main.js b/src/renderer/src/main.js index e389674..4bb9f41 100644 --- a/src/renderer/src/main.js +++ b/src/renderer/src/main.js @@ -78,11 +78,6 @@ const routes = [ name: 'videogeneratesetting', component: () => import('./components/Setting/VideoGenerateSetting.vue') }, - { - path: '/ShowMessage', - name: 'ShowMessage', - component: () => import('./components/Home/ShowMessage.vue') - }, { path: '/sdoriginal', name: 'sdoriginal', @@ -122,6 +117,21 @@ const routes = [ path: '/TTS_Services', name: 'TTS_Services', component: () => import('./components/TTS/TTSHome.vue') + }, + { + path: '/toolbox', + name: 'toolbox', + component: () => import('./components/ToolBox/ToolBoxHome.vue') + }, + { + path: '/toolbox/image-upload', + name: 'image-upload', + component: () => import('./components/ToolBox/ImageUpload/ImageUploadHome.vue') + }, + { + path: '/toolbox/image-compress', + name: 'image-compress', + component: () => import('./components/ToolBox/ImageCompress/ImageCompressHome.vue') } ] },