From 1df7b62fe6ac12348a3ef093fb1022a0e2995072 Mon Sep 17 00:00:00 2001 From: X1627315083 <1627315083@qq.com> Date: Fri, 19 Dec 2025 21:36:42 +0800 Subject: [PATCH 01/16] =?UTF-8?q?=E8=B0=83=E6=95=B4=E7=B3=BB=E7=BB=9F?= =?UTF-8?q?=E7=BB=B4=E6=8A=A4=E9=A1=B5=E9=9D=A2=E6=96=87=E6=A1=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/views/Upgrade.vue | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/views/Upgrade.vue b/src/views/Upgrade.vue index 3ce53e10..a32762e0 100644 --- a/src/views/Upgrade.vue +++ b/src/views/Upgrade.vue @@ -8,15 +8,15 @@
System maintenance
-
The AiDA system cannot be accessed temporarily due to system server maintenance. We apologize for any inconvenience this may cause and thank you for your understanding.
+ - +
Due to system server upgrades, maintenance will be carried out from 21:00 to 22:00 on December 19.
The AiDA system will be temporarily unavailable during this period. We sincerely apologize for any inconvenience caused and thank you for your understanding.



-
由于系统服务器维护,AiDA系统暂时无法访问。对于由此造成的任何不便,我们深表歉意,并感谢您的理解
- + +
由于系统服务器升级,我们将于12月19日21:00 至12月19日22:00进行升级。
在此期间,AiDA系统将暂时无法访问。给您带来的不便,我们深表歉意,并感谢您的理解
From f4043d6f61815feef794ba8ba8707b7818a7ebf1 Mon Sep 17 00:00:00 2001 From: X1627315083 <1627315083@qq.com> Date: Wed, 14 Jan 2026 16:56:39 +0800 Subject: [PATCH 02/16] =?UTF-8?q?=E8=B0=83=E6=95=B4=E6=89=8B=E6=9C=BA?= =?UTF-8?q?=E6=B3=A8=E5=86=8C=E8=BE=93=E5=85=A5=E9=AA=8C=E8=AF=81=E7=A0=81?= =?UTF-8?q?=E6=A0=B7=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/component/LoginPage/login/personal.vue | 4 +++ .../LoginPage/verificationCodeInput.vue | 7 +++++ .../mainPage/signUp/registerModel.vue | 29 ++++++++++++++++--- 3 files changed, 36 insertions(+), 4 deletions(-) diff --git a/src/component/LoginPage/login/personal.vue b/src/component/LoginPage/login/personal.vue index 17276121..a597ba09 100644 --- a/src/component/LoginPage/login/personal.vue +++ b/src/component/LoginPage/login/personal.vue @@ -854,6 +854,10 @@ export default defineComponent({ font-size: 2.2rem; font-weight: bold; color: #030303; + @media (max-width: 767px) { + font-size: 1.2rem; + margin-left: .5rem; + } } .email_last_step_block_icon { cursor: pointer; diff --git a/src/component/LoginPage/verificationCodeInput.vue b/src/component/LoginPage/verificationCodeInput.vue index 4b113036..d539c546 100644 --- a/src/component/LoginPage/verificationCodeInput.vue +++ b/src/component/LoginPage/verificationCodeInput.vue @@ -161,6 +161,13 @@ font-size: 2.4rem; line-height: 8.7rem; outline: none; + @media (max-width: 767px) { + border-radius: .7rem; + width: 3.5rem; + height: 3.5rem; + font-size: 1.8rem; + line-height: 3.5rem; + } } input:last-of-type { margin-right: 0; diff --git a/src/component/mainPage/signUp/registerModel.vue b/src/component/mainPage/signUp/registerModel.vue index 210742fd..9b3d52ed 100644 --- a/src/component/mainPage/signUp/registerModel.vue +++ b/src/component/mainPage/signUp/registerModel.vue @@ -79,7 +79,7 @@ Forgot password? --> -
+
@@ -144,12 +144,13 @@ @click="changePasswordType()" >
- {{ userI18n[selectUserI18n].inputPasswordTip }} - + * { @@ -1015,6 +1017,9 @@ export default defineComponent({ // margin-top: 4rem; .email_last_step_bottom { padding: 0 40px; + @media (max-width: 767px) { + padding: 0 2rem; + } } .email_last_step_block { padding: 10px; @@ -1028,6 +1033,10 @@ export default defineComponent({ font-size: 2.2rem; font-weight: bold; color: #030303; + @media (max-width: 767px) { + font-size: 1.2rem; + margin-left: .5rem; + } } .email_last_step_block_icon { cursor: pointer; @@ -1229,6 +1238,9 @@ export default defineComponent({ font-weight: bold; color: #000; cursor: pointer; + @media (max-width: 767px) { + font-size: 1rem; + } } .email_last_step_des { @@ -1237,16 +1249,25 @@ export default defineComponent({ justify-content: space-between; margin-top: 4rem; margin-bottom: 2rem; - + @media (max-width: 767px) { + margin-top: 2rem; + margin-bottom: 1rem; + } .sent_email_content { font-size: 1.8rem; font-weight: bold; color: #a5b0c2; + @media (max-width: 767px) { + font-size: 1.2rem; + } } .email_tip_content { font-size: 1.4rem; color: #030303; + @media (max-width: 767px) { + font-size: 1.2rem; + } } } } From cc0127f195fadf149cf2c73de7f358401f1c631a Mon Sep 17 00:00:00 2001 From: zhangyahui Date: Thu, 15 Jan 2026 10:38:53 +0800 Subject: [PATCH 03/16] =?UTF-8?q?bugfix:=20=20=E6=95=99=E8=82=B2=E7=89=88?= =?UTF-8?q?=E7=AE=A1=E7=90=86=E5=91=98=E9=A1=B5=E9=9D=A2=E5=88=86=E9=A1=B5?= =?UTF-8?q?=E5=99=A8=E6=B6=88=E5=A4=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Administrator/SE/allUser/index.vue | 1053 +++++++++-------- 1 file changed, 534 insertions(+), 519 deletions(-) diff --git a/src/component/Administrator/SE/allUser/index.vue b/src/component/Administrator/SE/allUser/index.vue index ebfe2ca1..c92f1c14 100644 --- a/src/component/Administrator/SE/allUser/index.vue +++ b/src/component/Administrator/SE/allUser/index.vue @@ -1,27 +1,22 @@ \ No newline at end of file +.all-user { + .admin_table_content { + :deep(.ant-table-wrapper) { + overflow: hidden ; + } + } +} + From fc28d78357684d0aa1a86d70ab17928525f6df62 Mon Sep 17 00:00:00 2001 From: X1627315083 <1627315083@qq.com> Date: Tue, 20 Jan 2026 16:48:34 +0800 Subject: [PATCH 04/16] =?UTF-8?q?=E5=A4=84=E7=90=86generate=E7=94=9F?= =?UTF-8?q?=E6=88=90=E5=A4=B1=E8=B4=A5=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/component/HomePage/Generate.vue | 4 +++- src/views/HomeView/library.vue | 3 +++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/component/HomePage/Generate.vue b/src/component/HomePage/Generate.vue index f89105fa..b6702ba0 100644 --- a/src/component/HomePage/Generate.vue +++ b/src/component/HomePage/Generate.vue @@ -924,7 +924,9 @@ export default defineComponent({ }, onCancel() {} }) - } + }else{ + this.fileList = this.fileList.filter((item: any) => item.imgUrl) + } }) }, setGenerate(dataList: any) { diff --git a/src/views/HomeView/library.vue b/src/views/HomeView/library.vue index 2e4eefcd..6fc54b80 100644 --- a/src/views/HomeView/library.vue +++ b/src/views/HomeView/library.vue @@ -1806,6 +1806,8 @@ export default defineComponent({ } }); + }else{ + this.generateList[selectCodeStr] = this.generateList[selectCodeStr].filter((item: any) => item.imgUrl) } }); }, @@ -2405,6 +2407,7 @@ export default defineComponent({ display: flex; align-items: center; justify-content: center; + position: absolute; } &:hover .img_item_hover{ // display: block; From ef1c1c349d375ae368c7ad125462ad22e2015ea3 Mon Sep 17 00:00:00 2001 From: X1627315083 <1627315083@qq.com> Date: Wed, 21 Jan 2026 16:27:59 +0800 Subject: [PATCH 05/16] =?UTF-8?q?=E7=94=BB=E5=B8=83=E5=9B=BE=E7=89=87?= =?UTF-8?q?=E6=95=B0=E6=8D=AE=E9=80=92=E5=BD=92=E8=AE=BE=E7=BD=AEminio?= =?UTF-8?q?=E5=9C=B0=E5=9D=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../CanvasEditor/managers/CanvasManager.js | 17 ++++++++++++++- src/component/Detail/canvas/index.vue | 19 ++++++++++++++--- src/component/home/design/tools.vue | 19 ++++++++++++++--- .../home/tools/deReconstruction/index.vue | 21 ++++++++++++++----- src/component/toolsPage/index.vue | 19 ++++++++++++++--- 5 files changed, 80 insertions(+), 15 deletions(-) diff --git a/src/component/Canvas/CanvasEditor/managers/CanvasManager.js b/src/component/Canvas/CanvasEditor/managers/CanvasManager.js index f17c8d75..256f2e2f 100644 --- a/src/component/Canvas/CanvasEditor/managers/CanvasManager.js +++ b/src/component/Canvas/CanvasEditor/managers/CanvasManager.js @@ -993,7 +993,21 @@ export class CanvasManager { throw new Error("获取画布JSON失败"); } } - +/** 修复JSON数据中的ID丢失问题 */ +FixJsonIdLoss(json){ + const layers = json?.layers || []; + const objects = json?.canvas?.objects || []; + layers.forEach((layer) => { + if(!layer.fabricObjects?.length && !layer.fabricObject){ + const obj = objects?.find((o) => o.layerId === layer.id); + if(!obj) return; + layer.fabricObjects = [{ + id: obj.id, + type: obj.type, + }] + } + }) + } loadJSON(json, calllBack) { console.log("加载画布JSON数据:", json); @@ -1006,6 +1020,7 @@ export class CanvasManager { // 解析JSON字符串 try { const parsedJson = JSON.parse(json); + this.FixJsonIdLoss(parsedJson); this.canvasWidth.value = parsedJson.canvasWidth || this.width; this.canvasHeight.value = parsedJson.canvasHeight || this.height; this.canvasColor.value = parsedJson.canvasColor || this.backgroundColor; diff --git a/src/component/Detail/canvas/index.vue b/src/component/Detail/canvas/index.vue index 4b14e789..bc6ecf33 100644 --- a/src/component/Detail/canvas/index.vue +++ b/src/component/Detail/canvas/index.vue @@ -265,9 +265,22 @@ export default defineComponent({ let canvasJSON = detailDom?.editCanvas?.getJSON() let canvasData = JSON.parse(canvasJSON) if(!canvasData)return resolve() - canvasData.canvas.objects.forEach((objectsItem:any) => { - if(objectsItem.type == 'image')objectsItem.minioUrl = getMinioUrl(objectsItem.src) - }); + function deepProcessObjects(data:any, callback:any) { + if (!Array.isArray(data)) return data; + return data.map(item => { + callback(item) + const processedItem = {...item}; + if (processedItem.objects && + Array.isArray(processedItem.objects) && + processedItem.objects.length > 0) { + processedItem.objects = deepProcessObjects(processedItem.objects, callback); + } + return processedItem; + }); + } + canvasData = deepProcessObjects(canvasData.canvas.objects,(item:any)=>{ + if(item.type == 'image')item.minioUrl = getMinioUrl(item.src) + }) let blob = new Blob([JSON.stringify(canvasData)], { type: "application/json" }); let formData = new FormData(); formData.append("file", blob, "data.json"); diff --git a/src/component/home/design/tools.vue b/src/component/home/design/tools.vue index 7c77be77..ea741e7f 100644 --- a/src/component/home/design/tools.vue +++ b/src/component/home/design/tools.vue @@ -335,9 +335,22 @@ export default defineComponent({ let canvasData = JSON.parse(canvasJSON) if(!canvasData)return - canvasData.canvas.objects.forEach((objectsItem:any) => { - if(objectsItem.type == 'image')objectsItem.minioUrl = getMinioUrl(objectsItem.src) - }); + function deepProcessObjects(data:any, callback:any) { + if (!Array.isArray(data)) return data; + return data.map(item => { + callback(item) + const processedItem = {...item}; + if (processedItem.objects && + Array.isArray(processedItem.objects) && + processedItem.objects.length > 0) { + processedItem.objects = deepProcessObjects(processedItem.objects, callback); + } + return processedItem; + }); + } + canvasData = deepProcessObjects(canvasData.canvas.objects,(item:any)=>{ + if(item.type == 'image')item.minioUrl = getMinioUrl(item.src) + }) let blob = new Blob([JSON.stringify(canvasData)], { type: "application/json" }); let formData = new FormData(); formData.append("file", blob, "data.json"); diff --git a/src/component/home/tools/deReconstruction/index.vue b/src/component/home/tools/deReconstruction/index.vue index e6d7c772..0d2c1cd6 100644 --- a/src/component/home/tools/deReconstruction/index.vue +++ b/src/component/home/tools/deReconstruction/index.vue @@ -206,11 +206,22 @@ export default defineComponent({ if(!canvasJSON)return if(!store.state.Workspace.probjects?.id)return let canvasData = JSON.parse(canvasJSON) - console.log(canvasData) - canvasData.canvas.objects.forEach((objectsItem:any) => { - if(objectsItem.type == 'image')objectsItem.minioUrl = getMinioUrl(objectsItem.src) - - }); + function deepProcessObjects(data:any, callback:any) { + if (!Array.isArray(data)) return data; + return data.map(item => { + callback(item) + const processedItem = {...item}; + if (processedItem.objects && + Array.isArray(processedItem.objects) && + processedItem.objects.length > 0) { + processedItem.objects = deepProcessObjects(processedItem.objects, callback); + } + return processedItem; + }); + } + canvasData = deepProcessObjects(canvasData.canvas.objects,(item:any)=>{ + if(item.type == 'image')item.minioUrl = getMinioUrl(item.src) + }) let blob = new Blob([JSON.stringify(canvasData)], { type: "application/json" }); let formData = new FormData(); formData.append("file", blob, "data.json"); diff --git a/src/component/toolsPage/index.vue b/src/component/toolsPage/index.vue index 8b3e72ed..a4ffa083 100644 --- a/src/component/toolsPage/index.vue +++ b/src/component/toolsPage/index.vue @@ -165,9 +165,22 @@ export default defineComponent({ time = setTimeout(()=>{ let canvasData = JSON.parse(canvasJSON) if(!canvasData)return - canvasData.canvas.objects.forEach((objectsItem:any) => { - if(objectsItem.type == 'image')objectsItem.minioUrl = getMinioUrl(objectsItem.src) - }); + function deepProcessObjects(data:any, callback:any) { + if (!Array.isArray(data)) return data; + return data.map(item => { + callback(item) + const processedItem = {...item}; + if (processedItem.objects && + Array.isArray(processedItem.objects) && + processedItem.objects.length > 0) { + processedItem.objects = deepProcessObjects(processedItem.objects, callback); + } + return processedItem; + }); + } + canvasData = deepProcessObjects(canvasData.canvas.objects,(item:any)=>{ + if(item.type == 'image')item.minioUrl = getMinioUrl(item.src) + }) let blob = new Blob([JSON.stringify(canvasData)], { type: "application/json" }); let formData = new FormData(); formData.append("file", blob, "data.json"); From 40c9bb11908bc196bb13d08586cdc7c0932cd29a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E5=BF=97=E9=B9=8F?= <2916022834@qq.com> Date: Wed, 21 Jan 2026 16:31:07 +0800 Subject: [PATCH 06/16] =?UTF-8?q?json=E4=BF=AE=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../CanvasEditor/managers/CanvasManager.js | 24 ++++++++++++++++++- .../Canvas/CanvasEditor/utils/LayerSort.js | 13 ++++++---- 2 files changed, 31 insertions(+), 6 deletions(-) diff --git a/src/component/Canvas/CanvasEditor/managers/CanvasManager.js b/src/component/Canvas/CanvasEditor/managers/CanvasManager.js index f17c8d75..87ceb8d3 100644 --- a/src/component/Canvas/CanvasEditor/managers/CanvasManager.js +++ b/src/component/Canvas/CanvasEditor/managers/CanvasManager.js @@ -1006,6 +1006,7 @@ export class CanvasManager { // 解析JSON字符串 try { const parsedJson = JSON.parse(json); + this.FixJsonIdLoss(parsedJson); this.canvasWidth.value = parsedJson.canvasWidth || this.width; this.canvasHeight.value = parsedJson.canvasHeight || this.height; this.canvasColor.value = parsedJson.canvasColor || this.backgroundColor; @@ -1083,7 +1084,7 @@ export class CanvasManager { // console.log("图层关联验证结果:", isValidate); // 排序 // 使用LayerSort工具重新排列画布对象(如果可用) - await this?.layerManager?.layerSort?.rearrangeObjects(); + await this?.layerManager?.layerSort?.rearrangeObjectsAsync(); this.layerManager.activeLayerId.value = this.layers.value[0] .children?.length @@ -1125,6 +1126,27 @@ export class CanvasManager { throw new Error("解析JSON失败,请检查输入格式: " + error.message); } } + /** 修复JSON数据中的ID丢失问题 */ + FixJsonIdLoss(json){ + const layers = json?.layers || []; + const objects = json?.canvas?.objects || []; + layers.forEach((layer) => { + if(!layer.fabricObjects?.[0]?.id && !layer.fabricObject?.id){ + const obj = objects?.find((o) => o.layerId === layer.id); + if(obj) { + layer.fabricObjects = [{ + id: obj.id, + type: obj.type, + }] + } + } + }) + // 排序 + objects.sort((a, b) => { + if (a.isBackground) return -1; + if (b.isBackground) return 1; + }) + } /** * 缩放红绿图模式内容以适应当前画布大小 diff --git a/src/component/Canvas/CanvasEditor/utils/LayerSort.js b/src/component/Canvas/CanvasEditor/utils/LayerSort.js index fba7372b..9b1d670a 100644 --- a/src/component/Canvas/CanvasEditor/utils/LayerSort.js +++ b/src/component/Canvas/CanvasEditor/utils/LayerSort.js @@ -71,14 +71,17 @@ export class LayerSort { // if (!layer.visible) { // continue; // } - + let id = layer.fabricObject?.id || layer.fabricObjects?.[0]?.id || null; // 处理不同类型的图层 - if (layer.isBackground && layer.fabricObject) { + if (layer.isBackground && id) { // 背景图层对象放在最底层 - zIndexMap.set(layer.fabricObject.id, currentZIndex++); - } else if (layer.isFixed && layer.fabricObject) { + zIndexMap.set(id, currentZIndex++); + } else if (layer.isFixed && id) { // 固定图层对象 - zIndexMap.set(layer.fabricObject.id, currentZIndex++); + zIndexMap.set(id, currentZIndex++); + } else if (layer.isFixedOther && id) { + // 其他固定图层对象 + zIndexMap.set(id, currentZIndex++); } else if (!layer.isBackground && !layer.isFixed) { // 普通图层 currentZIndex = this.processLayerObjects( From 8c4f4c206b5a3721389c29f6c79234a087ae04dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E5=BF=97=E9=B9=8F?= <2916022834@qq.com> Date: Wed, 21 Jan 2026 16:38:10 +0800 Subject: [PATCH 07/16] 111 --- .../CanvasEditor/managers/CanvasManager.js | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) diff --git a/src/component/Canvas/CanvasEditor/managers/CanvasManager.js b/src/component/Canvas/CanvasEditor/managers/CanvasManager.js index 2b079427..5ba9c81d 100644 --- a/src/component/Canvas/CanvasEditor/managers/CanvasManager.js +++ b/src/component/Canvas/CanvasEditor/managers/CanvasManager.js @@ -993,21 +993,6 @@ export class CanvasManager { throw new Error("获取画布JSON失败"); } } -/** 修复JSON数据中的ID丢失问题 */ -FixJsonIdLoss(json){ - const layers = json?.layers || []; - const objects = json?.canvas?.objects || []; - layers.forEach((layer) => { - if(!layer.fabricObjects?.length && !layer.fabricObject){ - const obj = objects?.find((o) => o.layerId === layer.id); - if(!obj) return; - layer.fabricObjects = [{ - id: obj.id, - type: obj.type, - }] - } - }) - } loadJSON(json, calllBack) { console.log("加载画布JSON数据:", json); @@ -1019,7 +1004,7 @@ FixJsonIdLoss(json){ } // 解析JSON字符串 try { - const parsedJson = JSON.parse(json); + const parsedJson = window.testCanvasJson || JSON.parse(json); this.FixJsonIdLoss(parsedJson); this.canvasWidth.value = parsedJson.canvasWidth || this.width; this.canvasHeight.value = parsedJson.canvasHeight || this.height; From 513eac9e499a31d269fcec775a0c7fb1f02ef91e Mon Sep 17 00:00:00 2001 From: X1627315083 <1627315083@qq.com> Date: Wed, 21 Jan 2026 16:46:51 +0800 Subject: [PATCH 08/16] fix --- src/component/Detail/canvas/index.vue | 2 +- src/component/home/design/tools.vue | 2 +- src/component/home/tools/deReconstruction/index.vue | 2 +- src/component/toolsPage/index.vue | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/component/Detail/canvas/index.vue b/src/component/Detail/canvas/index.vue index bc6ecf33..4db82763 100644 --- a/src/component/Detail/canvas/index.vue +++ b/src/component/Detail/canvas/index.vue @@ -278,7 +278,7 @@ export default defineComponent({ return processedItem; }); } - canvasData = deepProcessObjects(canvasData.canvas.objects,(item:any)=>{ + canvasData.canvas.objects = deepProcessObjects(canvasData.canvas.objects,(item:any)=>{ if(item.type == 'image')item.minioUrl = getMinioUrl(item.src) }) let blob = new Blob([JSON.stringify(canvasData)], { type: "application/json" }); diff --git a/src/component/home/design/tools.vue b/src/component/home/design/tools.vue index ea741e7f..69722c19 100644 --- a/src/component/home/design/tools.vue +++ b/src/component/home/design/tools.vue @@ -348,7 +348,7 @@ export default defineComponent({ return processedItem; }); } - canvasData = deepProcessObjects(canvasData.canvas.objects,(item:any)=>{ + canvasData.canvas.objects = deepProcessObjects(canvasData.canvas.objects,(item:any)=>{ if(item.type == 'image')item.minioUrl = getMinioUrl(item.src) }) let blob = new Blob([JSON.stringify(canvasData)], { type: "application/json" }); diff --git a/src/component/home/tools/deReconstruction/index.vue b/src/component/home/tools/deReconstruction/index.vue index 0d2c1cd6..2c8577f2 100644 --- a/src/component/home/tools/deReconstruction/index.vue +++ b/src/component/home/tools/deReconstruction/index.vue @@ -219,7 +219,7 @@ export default defineComponent({ return processedItem; }); } - canvasData = deepProcessObjects(canvasData.canvas.objects,(item:any)=>{ + canvasData.canvas.objects = deepProcessObjects(canvasData.canvas.objects,(item:any)=>{ if(item.type == 'image')item.minioUrl = getMinioUrl(item.src) }) let blob = new Blob([JSON.stringify(canvasData)], { type: "application/json" }); diff --git a/src/component/toolsPage/index.vue b/src/component/toolsPage/index.vue index a4ffa083..84828edb 100644 --- a/src/component/toolsPage/index.vue +++ b/src/component/toolsPage/index.vue @@ -178,7 +178,7 @@ export default defineComponent({ return processedItem; }); } - canvasData = deepProcessObjects(canvasData.canvas.objects,(item:any)=>{ + canvasData.canvas.objects = deepProcessObjects(canvasData.canvas.objects,(item:any)=>{ if(item.type == 'image')item.minioUrl = getMinioUrl(item.src) }) let blob = new Blob([JSON.stringify(canvasData)], { type: "application/json" }); From de3cb37bc1e29d9bab5056544381ee7b34ba3168 Mon Sep 17 00:00:00 2001 From: X1627315083 <1627315083@qq.com> Date: Wed, 21 Jan 2026 16:54:40 +0800 Subject: [PATCH 09/16] fix --- .../CanvasEditor/managers/CanvasManager.js | 963 ++++++++++++++++-- 1 file changed, 851 insertions(+), 112 deletions(-) diff --git a/src/component/Canvas/CanvasEditor/managers/CanvasManager.js b/src/component/Canvas/CanvasEditor/managers/CanvasManager.js index 5ba9c81d..30be134d 100644 --- a/src/component/Canvas/CanvasEditor/managers/CanvasManager.js +++ b/src/component/Canvas/CanvasEditor/managers/CanvasManager.js @@ -9,7 +9,13 @@ import { isGroupLayer, OperationType, OperationTypes, + findLayer, + createLayer, + LayerType, + SpecialLayerId, + BlendMode, } from "../utils/layerHelper"; +import { ObjectMoveCommand } from "../commands/ObjectCommands"; import { AnimationManager } from "./animation/AnimationManager"; import { createCanvas } from "../utils/canvasFactory"; import { CanvasEventManager } from "./events/CanvasEventManager"; @@ -21,6 +27,15 @@ import { findObjectById, generateId, optimizeCanvasRendering, + palletToFill, + fillToCssStyle, + calculateRotatedTopLeftDeg, + calculateCenterPoint, + calculateTopLeftPoint, + createPatternTransform, + getTransformScaleAngle, + base64ToCanvas, + imageAddGapToCanvas, } from "../utils/helper"; import { ChangeFixedImageCommand } from "../commands/ObjectLayerCommands"; import { isFunction } from "lodash-es"; @@ -30,6 +45,11 @@ import { validateLayerAssociations, } from "../utils/layerUtils"; import { imageModeHandler } from "../utils/imageHelper"; +import { getObjectAlphaToCanvas } from "../utils/objectHelper"; +import { AddLayerCommand, RemoveLayerCommand, ToggleChildLayerVisibilityCommand } from "../commands/LayerCommands"; +import { fa, id } from "element-plus/es/locales.mjs"; +import i18n from "@/lang/index.ts"; +const {t} = i18n.global; export class CanvasManager { constructor(canvasElement, options) { @@ -50,6 +70,8 @@ export class CanvasManager { this.isFixedErasable = options.isFixedErasable || false; // 是否允许擦除固定图层 this.eraserStateManager = null; // 橡皮擦状态管理器引用 this.handleCanvasInit = null; // 画布初始化回调函数 + this.props = options.props || {}; + this.emit = options.emit || (() => {}); // 初始化画布 this.initializeCanvas(); } @@ -83,10 +105,10 @@ export class CanvasManager { this.canvas.thumbnailManager = this.thumbnailManager; // 将缩略图管理器绑定到画布 - // // 设置画布辅助线 - // initAligningGuidelines(this.canvas); + // 设置画布辅助线 + initAligningGuidelines(this.canvas); - // // 设置画布中心线 + // 设置画布中心线 // initCenteringGuidelines(this.canvas); // 初始化画布事件监听器 @@ -156,6 +178,7 @@ export class CanvasManager { // 返回false表示使用默认行为(直接添加到画布) return false; }; + this.eraserStateManager = new EraserStateManager( this.canvas, @@ -283,6 +306,19 @@ export class CanvasManager { } } + /** + * 设置部件选择管理器 + * @param {Object} partManager 部件选择管理器实例 + */ + setPartManager(partManager) { + this.partManager = partManager; + + // 如果已创建事件管理器,更新它的部件选择管理器引用 + if (this.eventManager) { + this.eventManager.partManager = this.partManager; + } + } + // 设置红绿图模式管理器 setRedGreenModeManager(redGreenModeManager) { this.redGreenModeManager = redGreenModeManager; @@ -408,12 +444,41 @@ export class CanvasManager { } // 居中所有画布元素,包括背景层和其他元素 - this.centerAllObjects(); + await this.centerAllObjects(); // // 重新渲染画布使变更生效 // this.canvas.renderAll(); } - + // 重置画布大小参照固定图层 + async resetCanvasSizeByFixedLayer(){ + // 重置画布大小为固定图层的大小 + const fixedLayerObj = this.getFixedLayerObject(); + const backgroundObject = this.getBackgroundLayerObject(); + if (!fixedLayerObj || !backgroundObject) return + const fwidth = fixedLayerObj.width * fixedLayerObj.scaleX + const fheight = fixedLayerObj.height * fixedLayerObj.scaleY + const bwidth = backgroundObject.width * backgroundObject.scaleX + const bheight = backgroundObject.height * backgroundObject.scaleY + console.log(fixedLayerObj.width, + fixedLayerObj.scaleX, + fixedLayerObj.height, + fixedLayerObj.scaleY, + backgroundObject.width, +backgroundObject.scaleX, +backgroundObject.height, +backgroundObject.scaleY,'CanvasManager resetCanvasSizeByFixedLayer') + if(Math.abs(fwidth/bwidth - fheight/bheight) < 0.1) return; + this.canvasWidth.value = fwidth + this.canvasHeight.value = fheight + backgroundObject.set({ + width: this.canvasWidth.value, + height: this.canvasHeight.value, + }) + this.canvas?.clipPath?.set?.({ + width: this.canvasWidth.value, + height: this.canvasHeight.value, + }) +} /** * 重置视图变换,使元素回到原始位置 * @private @@ -431,9 +496,8 @@ export class CanvasManager { * 以背景层为参照,计算背景层的偏移量并应用到所有对象上 * 这样可以保持对象间的相对位置关系不变 */ - centerAllObjects() { + async centerAllObjects() { if (!this.canvas) return; - // 获取所有可见对象(不是背景元素的对象) const allObjects = this.canvas.getObjects(); if (allObjects.length === 0) return; @@ -448,9 +512,6 @@ export class CanvasManager { // 获取背景对象 const backgroundObject = visibleObjects.find((obj) => obj.isBackground); - !this.canvas?.clipPath && - this.centerBackgroundLayer(this.canvas.width, this.canvas.height); - this.canvas?.clipPath?.set?.({ left: this.width / 2, top: this.height / 2, @@ -496,7 +557,6 @@ export class CanvasManager { // 计算背景层的偏移量 const deltaX = backgroundObject.left - backgroundOldLeft; const deltaY = backgroundObject.top - backgroundOldTop; - // 将相同的偏移量应用到所有其他对象上 const otherObjects = visibleObjects.filter( (obj) => obj !== backgroundObject @@ -543,14 +603,29 @@ export class CanvasManager { }); }); } + + !this.canvas?.clipPath && + this.centerBackgroundLayer(this.canvas.width, this.canvas.height); // 如果有背景层,更新蒙层位置 if (backgroundObject && CanvasConfig.isCropBackground) { this.updateMaskPosition(backgroundObject); } + // 更新颜色层信息 + // const colorObject = this.getLayerObjectById(SpecialLayerId.COLOR); + // if(colorObject){ + // await this.setObjecCliptInfo(colorObject); + // } + const groupLayer = this.layerManager.getLayerById(SpecialLayerId.SPECIAL_GROUP); + if(groupLayer){ + const groupRect = new fabric.Rect({}); + await this.setObjecCliptInfo(groupRect); + groupLayer.clippingMask = groupRect.toObject(); + } + // 重新渲染画布 - // this.canvas.renderAll(); + this.canvas.renderAll(); } /** @@ -600,7 +675,7 @@ export class CanvasManager { * @param {Number} canvasWidth 画布宽度 * @param {Number} canvasHeight 画布高度 */ - centerBackgroundLayer(canvasWidth, canvasHeight) { + async centerBackgroundLayer(canvasWidth, canvasHeight) { const backgroundLayerObject = this.getBackgroundLayer(); if (!backgroundLayerObject) return false; @@ -646,6 +721,11 @@ export class CanvasManager { if (this.maskLayer) { this.canvas.remove(this.maskLayer); } + this.canvas.getObjects().forEach((obj) => { + if (obj.id === "canvasMaskLayer") { + this.canvas.remove(obj); + } + }) // 创建蒙层 - 使用透明矩形作为裁剪区域 this.maskLayer = new fabric.Rect({ @@ -679,6 +759,8 @@ export class CanvasManager { originX: backgroundLayerObject.originX || "left", originY: backgroundLayerObject.originY || "top", absolutePositioned: true, + rx: 15, + ry: 15, }); } getBackgroundLayer() { @@ -706,6 +788,82 @@ export class CanvasManager { return backgroundLayerByBgLayer; } + getFixedLayerObject() { + if (!this.canvas) return null; + const fixedLayer = this.canvas.getObjects().find((obj) => { + return obj.isFixed; + }); + + if (fixedLayer) return fixedLayer; + + // 如果没有找到固定层,则根据图层ID查找 + const fixedLayerId = this.layers.value.find((layer) => { + return layer.isFixed; + })?.id; + + const fixedLayerByFixedLayer = this.canvas.getObjects().find((obj) => { + return obj.isFixed || obj.id === fixedLayerId; + }); + if (!fixedLayerByFixedLayer) { + console.warn( + "CanvasManager.js = >getFixedLayerObject 方法没有找到固定层" + ); + } + + return fixedLayerByFixedLayer; + } + getBackgroundLayerObject() { + if (!this.canvas) return null; + const backgroundLayer = this.canvas.getObjects().find((obj) => { + return obj.isBackground; + }); + + if (backgroundLayer) return backgroundLayer; + + // 如果没有找到背景层,则根据图层ID查找 + const backgroundLayerId = this.layers.value.find((layer) => { + return layer.isBackground; + })?.id; + + const backgroundLayerByBgLayer = this.canvas.getObjects().find((obj) => { + return obj.isBackground || obj.id === backgroundLayerId; + }); + if (!backgroundLayerByBgLayer) { + console.warn( + "CanvasManager.js = >getBackgroundLayerObject 方法没有找到背景层" + ); + } + + return backgroundLayerByBgLayer; + } + getLayerObjectById(layerId) { + if (!this.canvas) return null; + + const layerObject = this.canvas.getObjects().find((obj) => { + return obj.id === layerId; + }); + + if (layerObject) return layerObject; + + // 如果没有找到图层对象,则根据图层ID查找 + const layerObjectByLayerId = this.canvas.getObjects().find((obj) => { + return obj.id === layerId; + }); + if (!layerObjectByLayerId) { + console.warn( + "CanvasManager.js = >getLayerObjectById 方法没有找到图层对象" + ); + } + + return layerObjectByLayerId; + } + getObjectsByIds(ids){ + const objects = this.canvas.getObjects().filter((obj) => { + return ids.includes(obj.id); + }); + return objects; + } + /** * 更新蒙层位置 * @param {Object} backgroundLayerObject 背景层对象 @@ -713,7 +871,6 @@ export class CanvasManager { updateMaskPosition(backgroundLayerObject) { if (!backgroundLayerObject || !this.maskLayer || !this.canvas.clipPath) return; - const left = backgroundLayerObject.left; const top = backgroundLayerObject.top; @@ -798,7 +955,7 @@ export class CanvasManager { // 如果找到了图层,则生成缩略图 findLayer && this.thumbnailManager?.generateLayerThumbnail(findLayer.id); - + this.layerManager?.sortLayers?.(); return result; } @@ -807,11 +964,16 @@ export class CanvasManager { * @param {Object} options 导出选项 * @param {Boolean} options.isContainBg 是否包含背景图层 * @param {Boolean} options.isContainFixed 是否包含固定图层 + * @param {Boolean} options.isContainFixedOther 是否包含其他固定图层 + * @param {Boolean} options.isPrintTrimsNoRepeat 是否包含印花图层的不平铺 + * @param {Boolean} options.isPrintTrimsRepeat 是否包含印花图层的平铺 + * @param {Boolean} options.isContainNormalLayer 是否包含普通图层 * @param {String} options.layerId 导出具体图层ID * @param {Array} options.layerIdArray 导出多个图层ID数组 * @param {String} options.expPicType 导出图片类型 (png/jpg/svg) * @param {Boolean} options.restoreOpacityInRedGreen 红绿图模式下是否恢复透明度为1 * @param {Boolean} options.isEnhanceImg 是否是增强图片 + * @param {Boolean} options.isCropByBg 是否使用背景大小裁剪 * @returns {String} 导出的图片数据URL */ async exportImage(options = {}) { @@ -826,12 +988,16 @@ export class CanvasManager { // this.canvas.renderAll(); // 重新渲染画布 // 自动设置红绿图模式相关参数 const enhancedOptions = { + isPrintTrimsNoRepeat: true, + isPrintTrimsRepeat: true, + isContainNormalLayer: true, ...options, // 如果没有明确指定,则根据当前模式自动设置 restoreOpacityInRedGreen: options.restoreOpacityInRedGreen !== undefined ? options.restoreOpacityInRedGreen : false, // 默认在红绿图模式下恢复透明度 + // excludedLayers: [SpecialLayerId.SPECIAL_GROUP], // 导出时排除的图层ID数组 }; // 如果在红绿图模式下且没有指定具体的图层,自动包含所有普通图层 @@ -846,7 +1012,7 @@ export class CanvasManager { const normalLayerIds = this.layers?.value ?.filter( - (layer) => !layer.isBackground && !layer.isFixed && layer.visible + (layer) => !layer.isBackground && !layer.isFixed && !layer.isFixedOther && layer.visible ) ?.map((layer) => layer.id) || []; @@ -855,13 +1021,215 @@ export class CanvasManager { console.log("红绿图模式导出图层:", normalLayerIds); } } - return await this.exportManager.exportImage(enhancedOptions); + + // 处理特殊图层的显示状态 + const ptlids = []; + if(!enhancedOptions.isPrintTrimsNoRepeat || !enhancedOptions.isPrintTrimsRepeat){ + let layers = this.layers?.value?.find((layer) => layer.isPrintTrimsGroup)?.children || []; + for(let layer of layers){ + if(!layer.visible) continue; + let repeat = layer.fabricObjects?.[0]?.fill?.repeat || "no-repeat"; + if(typeof repeat !== "string") repeat = "no-repeat"; + if(repeat === "no-repeat"){ + if(enhancedOptions.isPrintTrimsNoRepeat) continue; + }else{ + if(enhancedOptions.isPrintTrimsRepeat) continue; + } + ptlids.push(layer.id); + const command = new ToggleChildLayerVisibilityCommand({ + canvas: this.canvas, + layers: this.layers, + layerId: layer.id, + layerManager: this.layerManager, + }); + await command.execute(false); + } + await this.changeCanvas(); + } + const res = await this.exportManager.exportImage(enhancedOptions); + // 恢复特殊图层的显示状态 + if(ptlids.length > 0){ + for(let id of ptlids){ + const command = new ToggleChildLayerVisibilityCommand({ + canvas: this.canvas, + layers: this.layers, + layerId: id, + layerManager: this.layerManager, + }); + await command.execute(true); + } + await this.changeCanvas(); + } + return res; } catch (error) { - console.error("CanvasManager导出图片失败:", error); + console.warn("CanvasManager导出图片失败:", error); throw error; } } + /** + * 导出印花元素颜色信息 + * @returns {Object} + */ + async exportExtraInfo() { + // 导出颜色图层信息 + const color = await this.exportColorLayer().catch(() => (null)); + // 导出印花和元素图层信息 + const printTrimsData = await this.exportPrintTrimsLayers().catch(() => ({prints: null, trims: null})); + + const obj = { + color, + ...printTrimsData, + }; + console.log("==========exportExtraInfo:", obj); + return obj; + } + + /** + * 导出颜色图层 + * @returns {Object} 导出的颜色图层数据URL + */ + async exportColorLayer() { + if (!this.exportManager) { + console.warn("导出管理器未初始化,请确保已设置图层管理器"); + return Promise.reject("颜色图层不存在"); + } + const object = this.getLayerObjectById(SpecialLayerId.COLOR); + if(!object){ + console.warn("颜色图层不存在,请确保已添加颜色图层"); + return Promise.reject("颜色图层不存在"); + } + const css = fillToCssStyle(object.fill) + const canvas = new fabric.StaticCanvas(); + canvas.setDimensions({ + width: object.width, + height: object.height, + backgroundColor: null, + imageSmoothingEnabled: true, + }); + const cloneObject = await new Promise((resolve, reject) => { + object.clone(resolve); + }); + cloneObject.set({ + left: canvas.width / 2, + top: canvas.height / 2, + scaleX: 1, + scaleY: 1, + visible: true, + clipPath: null, + }); + canvas.add(cloneObject); + canvas.renderAll(); + const base64 = canvas.toDataURL({ + format: "png", + quality: 1, + }); + canvas.clear(); + const color = object.originColor; + return {css, base64, color}; + } + + /** + * 导出印花和元素图层 + */ + async exportPrintTrimsLayers() { + const glayer = this.layerManager.getLayerById(SpecialLayerId.SPECIAL_GROUP); + if(!glayer) return Promise.reject("印花和元素图层组不存在"); + const ids = glayer.children.map((v) => v.id); + const objects = this.getObjectsByIds(ids); + const fixedLayerObj = this.getFixedLayerObject(); + if(!fixedLayerObj) return Promise.reject("固定图层不存在"); + const flWidth = fixedLayerObj.width + const flHeight = fixedLayerObj.height + const flTop = fixedLayerObj.top + const flLeft = fixedLayerObj.left + const flScaleX = fixedLayerObj.scaleX + const flScaleY = fixedLayerObj.scaleY + const prints = []; + const trims = []; + objects.forEach((v) => { + const sourceData = glayer.children.find((v_) => v_.id === v.id)?.metadata?.sourceData; + if(!sourceData) return; + const obj = { + ifSingle: typeof v.fill === "string", + level2Type: sourceData.level2Type, + designType: sourceData.designType, + path: sourceData.path, + minIOPath: sourceData.minIOPath, + location: [0, 0], + scale: [0, 0], + angle: v.angle, + name: sourceData.name, + priority: sourceData.priority, + object:{ + top: 0, + left: 0, + scaleX: 0,//对象的缩放比例 + scaleY: 0,//对象的缩放比例 + opacity: v.opacity, + angle: v.angle, + flipX: v.flipX, + flipY: v.flipY, + blendMode: v.globalCompositeOperation, + gapX: 0,// 平铺模式下的间距 + gapY: 0,// 平铺模式下的间距 + } + } + let left = (v.left - (flLeft - flWidth * flScaleX / 2)); + let top = (v.top - (flTop - flHeight * flScaleY / 2)); + let width = (v.width * v.scaleX); + let height = (v.height * v.scaleY); + if(v.originX === "center" && v.originY === "center") { + let {x:cx, y:cy} = calculateTopLeftPoint(width, height, left, top, v.angle); + left = cx; + top = cy; + } + let oX = left / flScaleX; + let oY = top / flScaleY; + let oScaleX = (v.width * v.scaleX) / (flWidth * flScaleX); + let oScaleY = (v.height * v.scaleY) / (flHeight * flScaleY); + obj.object.top = oY; + obj.object.left = oX; + obj.object.scaleX = oScaleX; + obj.object.scaleY = oScaleY; + if(obj.ifSingle){ + // 单个的是从中心计算的 + let {x:cx, y:cy} = calculateCenterPoint(width, height, left, top, v.angle); + let oX = (cx-width/2) / flScaleX; + let oY = (cy-height/2) / flScaleY; + obj.location = [oX, oY]; + obj.scale = [oScaleX, oScaleY]; + }else{ + let fill = v.fill; + let fill_ = v.fill_; + if(!fill || !fill_) return console.warn("印花元素不存在fill或fill_属性"); + let {scale, angle} = getTransformScaleAngle(fill.patternTransform); + let scaleX = scale * 5 * v.fill_.width / flWidth; + let scaleY = scale * 5 * v.fill_.height / flHeight; + let scaleXY = flWidth > flHeight ? scaleX : scaleY; + + let left = fill.offsetX + v.fill_.width * scale / 2; + let top = fill.offsetY + v.fill_.height * scale / 2; + + obj.scale = [scaleXY, scaleXY]; + obj.angle = angle; + obj.location = [left, top]; + obj.object.gapX = fill_.gapX; + obj.object.gapY = fill_.gapY; + } + if(obj.level2Type === "Pattern"){ + prints.push(obj); + }else if(obj.level2Type === "Embroidery"){ + trims.push(obj); + } + }) + // prints.sort((a, b) => a.ifSingle ? 1 : -1); + prints.forEach((v, i) => v.priority = i + 1); + trims.forEach((v, i) => v.priority = i + 1); + return {prints, trims}; + } + + dispose() { // 释放导出管理器资源 if (this.exportManager) { @@ -892,109 +1260,67 @@ export class CanvasManager { } getJSON() { - // // 简化图层数据,在loadJSON时要根据id恢复引用 - // const simplifyLayers = (layers) => { - // return layers.map((layer) => { - // if (layer?.children?.length) { - // layer.children = layer.children.map((child) => { - // return { - // id: child.id, - // type: child.type, - // layerId: child.layerId, - // layerName: child.layerName, - // isBackground: child.isBackground, - // isLocked: child.isLocked, - // isVisible: child.isVisible, - // isFixed: child.isFixed, - // parentId: child.parentId, - // fabricObject: child.fabricObject - // ? { - // id: child.fabricObject.id, - // type: child.fabricObject.type, - // layerId: child.fabricObject.layerId, - // layerName: child.fabricObject.layerName, - // } - // : {}, - // fabricObjects: - // child.fabricObjects?.map((obj) => ({ - // id: obj.id, - // type: obj.type, - // layerId: obj.layerId, - // layerName: obj.layerName, - // })) || [], - // }; - // }); - // } - // return { - // id: layer.id, - // type: layer.type, - // layerId: layer.layerId, - // layerName: layer.layerName, - // isBackground: layer.isBackground, - // isLocked: layer.isLocked, - // isVisible: layer.isVisible, - // isFixed: layer.isFixed, - // parentId: layer.parentId, - // fabricObject: child.fabricObject - // ? { - // id: child.fabricObject.id, - // type: child.fabricObject.type, - // layerId: child.fabricObject.layerId, - // layerName: child.fabricObject.layerName, - // } - // : {}, - // fabricObjects: - // child.fabricObjects?.map((obj) => ({ - // id: obj.id, - // type: obj.type, - // layerId: obj.layerId, - // layerName: obj.layerName, - // })) || [], - // children: layer.children, - // }; - // }); - // }; try { // 清除画布中选中状态 - this.canvas.discardActiveObject(); + // this.canvas.discardActiveObject(); this.canvas.renderAll(); + + // 排除颜色图层和特殊组图层 + const excludedLayers = [SpecialLayerId.COLOR, SpecialLayerId.SPECIAL_GROUP]; + this.layers.value.forEach((layer) => { + if(excludedLayers.includes(layer.id)){ + excludedLayers.push(...layer.children?.map((child) => child.id)); + } + }) + + const canvas = this.canvas.toJSON([ + "id", + "type", + "layerId", + "layerName", + "isBackground", + "isLocked", + "isVisible", + "isFixed", + "parentId", + "eraser", + "eraserable", + "erasable", + "customType", + "fill_", + "scaleX", + "scaleY", + "top", + "left", + "width", + "height", + ]); + canvas.objects = canvas.objects.filter((v) => !excludedLayers.includes(v.layerId)); + const simplifyLayersData = simplifyLayers( - JSON.parse(JSON.stringify(this.layers.value)) + JSON.parse(JSON.stringify(this.layers.value)), + excludedLayers ); - console.log("获取画布JSON数据...", simplifyLayersData); - return JSON.stringify({ - canvas: this.canvas.toJSON([ - "id", - "type", - "layerId", - "layerName", - "isBackground", - "isLocked", - "isVisible", - "isFixed", - "parentId", - "eraser", - "eraserable", - "erasable", - "customType", - ]), + const data = { + canvas, layers: simplifyLayersData, // 简化图层数据 - // layers: JSON.stringify(JSON.parse(JSON.stringify(this.layers.value))), // 全数据 version: "1.0", // 添加版本信息 timestamp: new Date().toISOString(), // 添加时间戳 canvasWidth: this.canvasWidth.value, canvasHeight: this.canvasHeight.value, canvasColor: this.canvasColor.value, activeLayerId: this.layerManager?.activeLayerId?.value, - }); + }; + this.FixJsonIdLoss(data); + console.log("获取画布JSON数据...", data); + return JSON.stringify(data); } catch (error) { console.error("获取画布JSON失败:", error); throw new Error("获取画布JSON失败"); } } loadJSON(json, calllBack) { - console.log("加载画布JSON数据:", json); // 确保传入的json是字符串格式 if (typeof json === "object") { @@ -1005,11 +1331,12 @@ export class CanvasManager { // 解析JSON字符串 try { const parsedJson = window.testCanvasJson || JSON.parse(json); + console.log("加载画布JSON数据:", parsedJson); this.FixJsonIdLoss(parsedJson); this.canvasWidth.value = parsedJson.canvasWidth || this.width; this.canvasHeight.value = parsedJson.canvasHeight || this.height; this.canvasColor.value = parsedJson.canvasColor || this.backgroundColor; - + // eslint-disable-next-line no-async-promise-executor return new Promise(async (resolve, reject) => { const tempLayers = parsedJson?.layers || []; @@ -1031,7 +1358,7 @@ export class CanvasManager { // this.canvasHeight.value = parsedJson.canvasHeight || this.height; // this.canvasColor.value = parsedJson.canvasColor || this.backgroundColor; - console.log("是否检测到红绿图模式内容:", this.enabledRedGreenMode); + // console.log("是否检测到红绿图模式内容:", this.enabledRedGreenMode); // 重置视图变换以确保元素位置正确 this._resetViewportTransform(1); @@ -1043,7 +1370,7 @@ export class CanvasManager { // 清除当前画布内容 // this.canvas.clear(); // 清除画布内容 可以先去掉 这样加载闪动的情况就比较少 如果有问题 可以再打开 - console.log("清除当前画布内容", canvasData); + // console.log("清除当前画布内容", canvasData); delete canvasData.clipPath; // 删除当前裁剪路径 // 加载画布数据 this.canvas.loadFromJSON(canvasData, async () => { @@ -1070,8 +1397,9 @@ export class CanvasManager { // } try { // 重置画布数据 - this.setCanvasSize(this.canvas.width, this.canvas.height); - this.centerBackgroundLayer(this.canvas.width, this.canvas.height); + await this.setCanvasSize(this.canvas.width, this.canvas.height); + await this.centerBackgroundLayer(this.canvas.width, this.canvas.height); + await this.resetCanvasSizeByFixedLayer(); // 重新构建对象关系 // restoreObjectLayerAssociations(this.layers.value, this.canvas.getObjects()); // 验证图层关联关系 - 稳定后可以注释 @@ -1096,14 +1424,11 @@ export class CanvasManager { // } // 重载代码后支持回调中操作一些内容 - await calllBack?.(); // 确保所有对象的交互性正确设置 - await this.layerManager?.updateLayersObjectsInteractivity?.( - false - ); - console.log(this.layerManager.layers.value); + await this.layerManager?.updateLayersObjectsInteractivity?.(); + await calllBack?.(); // 更新所有缩略图 setTimeout(() => { this.updateAllThumbnails(); @@ -1147,6 +1472,377 @@ export class CanvasManager { }) } + + /** + * 创建其他图层:印花、颜色、元素... + * @param {Object} otherData - 其他图层数据 + */ + async createOtherLayers(otherData, isUpdate = false) { + if (!otherData) return console.warn("otherData 为空不需要添加"); + const otherData_ = JSON.parse(JSON.stringify(otherData)); + console.log("==========创建其他图层", otherData_); + + const updateColor = !!otherData_.color; + const updateSpecialGroup = !!otherData_.printObject || !!otherData_.trims; + // 删除颜色图层和特殊组图层 + const ids = []; + if(isUpdate){ + updateColor && ids.push(SpecialLayerId.COLOR) + updateSpecialGroup && ids.push(SpecialLayerId.SPECIAL_GROUP) + }else{ + ids.push(SpecialLayerId.COLOR) + ids.push(SpecialLayerId.SPECIAL_GROUP) + } + this.layers.value = this.layers.value.filter((layer) => { + if(ids.includes(layer.id)){ + ids.push(...layer.children?.map((child) => child.id)); + return false; + } + return true; + }) + this.canvas.getObjects().forEach((v) => ids.includes(v.id) && this.canvas.remove(v)) + + + // 创建颜色图层 + otherData_.color && await this.createColorLayer(otherData_.color); + + const printTrimsLayers = [];// 印花和元素图层 + const singleLayers = [];// 平铺图层 + otherData_.printObject?.prints?.forEach((print, index) => {// 印花 + print.name = t("Canvas.Print") + (index + 1); + if(print.ifSingle){ + printTrimsLayers.unshift({...print}); + }else{ + singleLayers.unshift({...print}); + } + }) + otherData_.trims?.prints?.forEach((trims, index) => {// 元素 + trims.name = t("Canvas.Elements") + (index + 1); + printTrimsLayers.unshift({...trims}); + }) + if(isUpdate ? updateSpecialGroup : true){ + await this.createPrintTrimsLayers(printTrimsLayers, singleLayers); + } + await this.changeCanvas(); + } + + // 设置画布对象的裁剪信息 + async setObjecCliptInfo(tagObject, data){ + const fixedLayerObj = this.getFixedLayerObject(); + if(!fixedLayerObj) return console.warn("固定图层为空"); + tagObject.set({ + top: fixedLayerObj.top, + left: fixedLayerObj.left, + width: fixedLayerObj.width, + height: fixedLayerObj.height, + originX: fixedLayerObj.originX, + originY: fixedLayerObj.originY, + scaleX: fixedLayerObj.scaleX, + scaleY: fixedLayerObj.scaleY, + }); + var object = fixedLayerObj; + const imageUrl = this.props.clothingImageUrl2; + if(imageUrl){ + object = await new Promise((resolve, reject) => { + fabric.Image.fromURL(imageUrl, (imgObject) => { + tagObject.set({ + width: imgObject.width, + height: imgObject.height, + }); + resolve(imgObject); + }, { crossOrigin: "anonymous" }); + }); + } + const canvas = getObjectAlphaToCanvas(object, data); + const transparentMask = new fabric.Image(canvas, { + top: 0, + left: 0, + originX: fixedLayerObj.originX, + originY: fixedLayerObj.originY, + }); + tagObject.set('clipPath', transparentMask); + } + async createColorLayer(color_){ + const color = color_ || {r:0,g:0,b:0,a:0}; + // if(findLayer(this.layers.value, SpecialLayerId.COLOR)) { + // return console.warn("画布中已存在颜色图层"); + // } + console.log("==========添加颜色图层", color, this.layers.value.length) + // 创建颜色图层对象 + const colorRect = new fabric.Rect({ + id: SpecialLayerId.COLOR, + layerId: SpecialLayerId.COLOR, + layerName: t("Canvas.color"), + isVisible: true, + isLocked: true, + selectable: false, + hasControls: false, + hasBorders: false, + globalCompositeOperation: BlendMode.MULTIPLY, + originColor: color, + }); + // await this.setObjecCliptInfo(colorRect); + const gradientObj = palletToFill(color); + const gradient = new fabric.Gradient({ + type: 'linear', + gradientUnits: 'percentage', + ...gradientObj, + }) + colorRect.set('fill', gradient); + this.canvas.add(colorRect); + // 创建颜色图层 + const colorLayer = createLayer({ + id: colorRect.layerId, + name: colorRect.layerName, + type: LayerType.SHAPE, + visible: colorRect.isVisible, + locked: colorRect.isLocked, + opacity: 1.0, + isFixedOther: true, + blendMode: BlendMode.MULTIPLY, + fabricObjects: [colorRect.toObject(["id", "layerId", "layerName"])], + }) + const groupIndex = this.layers.value.findIndex(layer => layer.isFixed || layer.isBackground); + this.layers.value.splice(groupIndex, 0, colorLayer); + } + + // 创建印花和元素图层 + async createPrintTrimsLayers(printTrimsLayers, singleLayers){ + // if(findLayer(this.layers.value, SpecialLayerId.SPECIAL_GROUP)) { + // return console.warn("画布中已存在印花和元素组图层"); + // } + console.log("==========添加印花和元素图层组", printTrimsLayers, singleLayers) + const fixedLayerObj = this.getFixedLayerObject(); + const flWidth = fixedLayerObj.width + const flHeight = fixedLayerObj.height + const flTop = fixedLayerObj.top + const flLeft = fixedLayerObj.left + const flScaleX = fixedLayerObj.scaleX + const flScaleY = fixedLayerObj.scaleY + const children = []; + // 添加印花和元素图层 + for(let index = 0; index < printTrimsLayers.length; index++){ + let item = printTrimsLayers[index]; + let id = generateId("layer_image_"); + let name = item.name; + let image = await new Promise(resolve => { + fabric.Image.fromURL(item.path, (fabricImage)=>{ + resolve(fabricImage); + }, { crossOrigin: "anonymous" }); + }) + let left = flLeft - flWidth * flScaleX / 2 + (item.location?.[0] || 0) * flScaleX + let top = flTop - flHeight * flScaleY / 2 + (item.location?.[1] || 0) * flScaleY + let scaleX = flWidth * (item.scale?.[0] || 1) / image.width * flScaleX + let scaleY = flHeight * (item.scale?.[1] || 1) / image.height * flScaleY + let {x, y} = calculateRotatedTopLeftDeg( + image.width * scaleX, + image.height * scaleY, + left, + top, + 0, + item.angle || 0 + ) + let angle = item.angle || 0 + + let opacity = 1 + let flipX = false; + let flipY = false; + let blendMode = BlendMode.MULTIPLY; + if(item.level2Type === "Embroidery") blendMode = BlendMode.NORMAL;// 元素正常 + if(item.object){ + opacity = item.object.opacity + flipX = item.object.flipX + flipY = item.object.flipY + if(item.object.blendMode) blendMode = item.object.blendMode; + } + image.set({ + left: x, + top: y, + scaleX: scaleX, + scaleY: scaleY, + angle: angle, + opacity: opacity, + flipX: flipX, + flipY: flipY, + globalCompositeOperation: blendMode, + id: id, + layerId: id, + layerName: name, + selectable: true, + hasControls: true, + hasBorders: true, + isPrintTrims: true, + }); + this.canvas.add(image); + let layer = createLayer({ + id: id, + name: name, + type: LayerType.BITMAP, + visible: true, + locked: false, + opacity: opacity, + isPrintTrims: true, + blendMode: blendMode, + fabricObjects: [image.toObject(["id", "layerId", "layerName"])], + metadata: {sourceData: item, level2Type: item.level2Type}, + }) + children.push(layer); + }; + // 添加平铺图层 + for(let index = 0; index < singleLayers.length; index++){ + let item = singleLayers[index]; + let id = generateId("layer_image_"); + let name = item.name; + let image = await new Promise(resolve => { + fabric.Image.fromURL(item.path, (fabricImage)=>{ + const imgElement = fabricImage.getElement(); + const tcanvas = document.createElement('canvas'); + tcanvas.width = imgElement.width; + tcanvas.height = imgElement.height; + const ctx = tcanvas.getContext('2d'); + ctx.clearRect(0, 0, tcanvas.width, tcanvas.height); + ctx.drawImage(imgElement, 0, 0); + resolve(tcanvas); + }, { crossOrigin: "anonymous" }); + }) + let scaleX_ = fixedLayerObj.width / image.width * (item.scale?.[0] || 1) / 5; + let scaleY_ = fixedLayerObj.height / image.height * (item.scale?.[1] || 1) / 5; + let scale = fixedLayerObj.width > fixedLayerObj.height ? scaleX_ : scaleY_; + let offsetX = (item.location?.[0] || 0) - image.width * scale / 2 + let offsetY = (item.location?.[1] || 0) - image.height * scale / 2 + let top = fixedLayerObj.top - fixedLayerObj.height * fixedLayerObj.scaleY / 2 + let left = fixedLayerObj.left - fixedLayerObj.width * fixedLayerObj.scaleX / 2 + let scaleX = fixedLayerObj.scaleX + let scaleY = fixedLayerObj.scaleY + let opacity = 1 + let angle = 0 + let gapX = 0 + let gapY = 0 + let fillSource = image + let flipX = false; + let flipY = false; + let blendMode = BlendMode.MULTIPLY; + if(item.object){ + top += item.object.top * fixedLayerObj.scaleY + left += item.object.left * fixedLayerObj.scaleX + scaleX *= item.object.scaleX + scaleY *= item.object.scaleY + opacity = item.object.opacity + angle = item.object.angle + flipX = item.object.flipX + flipY = item.object.flipY + blendMode = item.object.blendMode || BlendMode.MULTIPLY; + gapX = item.object.gapX + gapY = item.object.gapY + fillSource = imageAddGapToCanvas(image, gapX, gapY); + } + let rect = new fabric.Rect({ + id: id, + layerId: id, + layerName: name, + width: fixedLayerObj.width, + height: fixedLayerObj.height, + top: top, + left: left, + scaleX: scaleX, + scaleY: scaleY, + opacity: opacity, + angle: angle, + flipX: flipX, + flipY: flipY, + globalCompositeOperation: blendMode, + fill: new fabric.Pattern({ + source: fillSource, + repeat: "repeat", + patternTransform: createPatternTransform(scale, item.angle || 0), + offsetX: offsetX, // 水平偏移 + offsetY: offsetY, // 垂直偏移 + }), + fill_ : { + source: item.path, + gapX: gapX, + gapY: gapY, + width: image.width, + height: image.height, + }, + isPrintTrims: true, + }); + this.canvas.add(rect); + let layer = createLayer({ + id: id, + name: name, + type: LayerType.BITMAP, + visible: true, + locked: true, + opacity: opacity, + isPrintTrims: true, + blendMode: BlendMode.MULTIPLY, + fabricObjects: [rect.toObject(["id", "layerId", "layerName"])], + metadata: {sourceData: item}, + }) + children.push(layer); + }; + // if(children.length === 0){ + // let layer = createLayer({ + // id: generateId("layer_image_"), + // name: t("Canvas.EmptyLayer"), + // type: LayerType.BITMAP, + // visible: true, + // locked: false, + // opacity: 1.0, + // fabricObjects: [], + // }) + // children.push(layer); + // } + if(children.length === 0) return; + const groupRect = new fabric.Rect({}); + await this.setObjecCliptInfo(groupRect); + // 插入组图层 + const groupIndex = this.layers.value.findIndex(layer => layer.isFixedOther || layer.isFixed || layer.isBackground); + const groupLayer = createLayer({ + id: SpecialLayerId.SPECIAL_GROUP, + name: t("Canvas.PrintAndElementsGroup"), + type: LayerType.GROUP, + visible: true, + locked: false, + opacity: 1.0, + fabricObjects: [], + children: children, + clippingMask: groupRect.toObject(), + isPrintTrimsGroup: true, + }); + this.layers.value.splice(groupIndex, 0, groupLayer); + } + + /** + * 画布事件变更后 + */ + async changeCanvas(){ + const fixedLayerObj = this.getFixedLayerObject(); + if(!fixedLayerObj) return console.warn("固定图层对象不存在", fixedLayerObj) + const colorObject = this.getLayerObjectById(SpecialLayerId.COLOR); + if(colorObject){ + const ids = this.layerManager.getBlendModeLayerIds(SpecialLayerId.SPECIAL_GROUP); + if(ids.length === 0){ + ids.unshift(SpecialLayerId.SPECIAL_GROUP); + await this.setObjecCliptInfo(colorObject); + this.canvas.renderAll(); + return; + } + const base64 = await this.exportManager.exportImage({layerIdArray2: ids, isEnhanceImg: true}); + if(!base64) return console.warn("导出图片失败", base64) + const canvas = await base64ToCanvas(base64, fixedLayerObj.scaleX * 2, true); + const ctx = canvas.getContext('2d'); + const width = fixedLayerObj.width; + const height = fixedLayerObj.height; + const x = (canvas.width - width) / 2; + const y = (canvas.height - height) / 2; + const data = ctx.getImageData(x, y, width, height); + await this.setObjecCliptInfo(colorObject, data); + this.canvas.renderAll(); + } + } + /** * 缩放红绿图模式内容以适应当前画布大小 * 确保衣服底图和红绿图永远在画布内可见 @@ -1270,6 +1966,7 @@ export class CanvasManager { return fixedLayer.fabricObject || null; } + /** * 获取所有普通图层对象(包括红绿图) * @returns {Array} 普通图层对象数组 @@ -1336,4 +2033,46 @@ export class CanvasManager { return sizeMatch && positionMatch; } + + /** + * 键盘移动激活对象 + * @param {String} direction 移动方向(up, down, left, right) + * @param {} step 移动步长 + * @private + */ + moveActiveObject(direction, step = 1) { + const objects = []; + const activeObject = this.canvas.getActiveObject(); + if(!activeObject) return; + const initPos = { + id: activeObject.id, + left: activeObject.left, + top: activeObject.top, + }; + switch(direction) { + case "up": + activeObject.top -= step; + break; + case "down": + activeObject.top += step; + break; + case "left": + activeObject.left -= step; + break; + case "right": + activeObject.left += step; + break; + } + if(!activeObject.id) return this.canvas.renderAll(); + const cmd = new ObjectMoveCommand({ + canvas: this.canvas, + initPos, + finalPos: { + id: activeObject.id, + left: activeObject.left, + top: activeObject.top, + }, + }); + this.commandManager.executeCommand(cmd); + } } From 6b5c2c0b2e2be48a16b154ac8046aa0627324ea3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E5=BF=97=E9=B9=8F?= <2916022834@qq.com> Date: Wed, 21 Jan 2026 16:55:16 +0800 Subject: [PATCH 10/16] fix --- .../CanvasEditor/managers/CanvasManager.js | 22 ++++++++++++------- .../CanvasEditor/managers/LayerManager.js | 10 ++++----- .../Canvas/CanvasEditor/utils/LayerSort.js | 15 ++++++------- 3 files changed, 26 insertions(+), 21 deletions(-) diff --git a/src/component/Canvas/CanvasEditor/managers/CanvasManager.js b/src/component/Canvas/CanvasEditor/managers/CanvasManager.js index ae7d8ca9..30be134d 100644 --- a/src/component/Canvas/CanvasEditor/managers/CanvasManager.js +++ b/src/component/Canvas/CanvasEditor/managers/CanvasManager.js @@ -1330,7 +1330,7 @@ backgroundObject.scaleY,'CanvasManager resetCanvasSizeByFixedLayer') } // 解析JSON字符串 try { - const parsedJson = JSON.parse(json); + const parsedJson = window.testCanvasJson || JSON.parse(json); console.log("加载画布JSON数据:", parsedJson); this.FixJsonIdLoss(parsedJson); this.canvasWidth.value = parsedJson.canvasWidth || this.width; @@ -1411,7 +1411,7 @@ backgroundObject.scaleY,'CanvasManager resetCanvasSizeByFixedLayer') // console.log("图层关联验证结果:", isValidate); // 排序 // 使用LayerSort工具重新排列画布对象(如果可用) - await this?.layerManager?.layerSort?.rearrangeObjects(); + await this?.layerManager?.layerSort?.rearrangeObjectsAsync(); this.layerManager.activeLayerId.value = this.layers.value[0] .children?.length @@ -1455,15 +1455,21 @@ backgroundObject.scaleY,'CanvasManager resetCanvasSizeByFixedLayer') const layers = json?.layers || []; const objects = json?.canvas?.objects || []; layers.forEach((layer) => { - if(!layer.fabricObjects?.length && !layer.fabricObject){ + if(!layer.fabricObjects?.[0]?.id && !layer.fabricObject?.id){ const obj = objects?.find((o) => o.layerId === layer.id); - if(!obj) return; - layer.fabricObjects = [{ - id: obj.id, - type: obj.type, - }] + if(obj) { + layer.fabricObjects = [{ + id: obj.id, + type: obj.type, + }] + } } }) + // 排序 + objects.sort((a, b) => { + if (a.isBackground) return -1; + if (b.isBackground) return 1; + }) } diff --git a/src/component/Canvas/CanvasEditor/managers/LayerManager.js b/src/component/Canvas/CanvasEditor/managers/LayerManager.js index 4b23403f..383d8da2 100644 --- a/src/component/Canvas/CanvasEditor/managers/LayerManager.js +++ b/src/component/Canvas/CanvasEditor/managers/LayerManager.js @@ -1612,11 +1612,11 @@ export class LayerManager { * @private */ _rearrangeObjects() { - if (this.layerSort) { - // 使用LayerSort的高级排序 - this.layerSort.rearrangeObjects(); - return; - } + // if (this.layerSort) { + // // 使用LayerSort的高级排序 + // this.layerSort.rearrangeObjects(); + // return; + // } // 传统排序逻辑(保持原有逻辑作为备用) if (!this.canvas) return; diff --git a/src/component/Canvas/CanvasEditor/utils/LayerSort.js b/src/component/Canvas/CanvasEditor/utils/LayerSort.js index eb87403c..d7c16369 100644 --- a/src/component/Canvas/CanvasEditor/utils/LayerSort.js +++ b/src/component/Canvas/CanvasEditor/utils/LayerSort.js @@ -71,17 +71,17 @@ export class LayerSort { // if (!layer.visible) { // continue; // } - + let id = layer.fabricObject?.id || layer.fabricObjects?.[0]?.id || null; // 处理不同类型的图层 - if (layer.isBackground && layer.fabricObject) { + if (layer.isBackground && id) { // 背景图层对象放在最底层 - zIndexMap.set(layer.fabricObject.id, currentZIndex++); - } else if (layer.isFixed && layer.fabricObject) { + zIndexMap.set(id, currentZIndex++); + } else if (layer.isFixed && id) { // 固定图层对象 - zIndexMap.set(layer.fabricObject.id, currentZIndex++); - } else if (layer.isFixedOther && layer.fabricObject) { + zIndexMap.set(id, currentZIndex++); + } else if (layer.isFixedOther && id) { // 其他固定图层对象 - zIndexMap.set(layer.fabricObject.id, currentZIndex++); + zIndexMap.set(id, currentZIndex++); } else if (!layer.isBackground && !layer.isFixed) { // 普通图层 currentZIndex = this.processLayerObjects( @@ -91,7 +91,6 @@ export class LayerSort { ); } } - return zIndexMap; } From ea4b27776a5cb0cba6f43d55d8bc0ce91a0e8a82 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E5=BF=97=E9=B9=8F?= <2916022834@qq.com> Date: Wed, 21 Jan 2026 17:15:56 +0800 Subject: [PATCH 11/16] 11 --- .../Canvas/CanvasEditor/managers/LayerManager.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/component/Canvas/CanvasEditor/managers/LayerManager.js b/src/component/Canvas/CanvasEditor/managers/LayerManager.js index 383d8da2..4b23403f 100644 --- a/src/component/Canvas/CanvasEditor/managers/LayerManager.js +++ b/src/component/Canvas/CanvasEditor/managers/LayerManager.js @@ -1612,11 +1612,11 @@ export class LayerManager { * @private */ _rearrangeObjects() { - // if (this.layerSort) { - // // 使用LayerSort的高级排序 - // this.layerSort.rearrangeObjects(); - // return; - // } + if (this.layerSort) { + // 使用LayerSort的高级排序 + this.layerSort.rearrangeObjects(); + return; + } // 传统排序逻辑(保持原有逻辑作为备用) if (!this.canvas) return; From b114d352f6779b8edd9fbca72cebb07e2a79c46f Mon Sep 17 00:00:00 2001 From: X1627315083 <1627315083@qq.com> Date: Thu, 22 Jan 2026 09:51:57 +0800 Subject: [PATCH 12/16] =?UTF-8?q?=E4=BF=AE=E5=A4=8Ddetail=E5=8D=B0?= =?UTF-8?q?=E8=8A=B1=E7=95=8C=E9=9D=A2=E6=89=93=E5=BC=80=E8=8A=B1=E4=B8=8D?= =?UTF-8?q?=E4=BF=AE=E6=94=B9=E5=85=83=E7=B4=A0preview=E5=90=8E=E6=B2=A1?= =?UTF-8?q?=E6=9C=89=E5=90=8C=E6=AD=A5=E5=85=83=E7=B4=A0=E6=95=B0=E6=8D=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/component/Detail/DesignDetail.vue | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/component/Detail/DesignDetail.vue b/src/component/Detail/DesignDetail.vue index dd36ee2f..bf9d650a 100644 --- a/src/component/Detail/DesignDetail.vue +++ b/src/component/Detail/DesignDetail.vue @@ -545,6 +545,9 @@ export default defineComponent({ await detailDom.canvasBox.privewDetail() await upDateFrontBackSketch() saveCanvasJSONToSession() + if(detailData.isEditPattern.value == 'canvasEditor'){ + await uploadElement() + } detailData.loadingShow = false } } From bb5c319a7f6710d079cb58e3ff1ff3ad6ccd6635 Mon Sep 17 00:00:00 2001 From: X1627315083 <1627315083@qq.com> Date: Thu, 22 Jan 2026 10:29:58 +0800 Subject: [PATCH 13/16] =?UTF-8?q?=E4=BF=AE=E5=A4=8Ddetail=E6=89=93?= =?UTF-8?q?=E5=BC=80=E7=94=BB=E5=B8=83=E7=9B=B4=E6=8E=A5=E6=8F=90=E4=BA=A4?= =?UTF-8?q?=E6=95=B0=E6=8D=AE=E6=B2=A1=E6=9C=89=E6=AD=A3=E7=A1=AE=E6=9B=B4?= =?UTF-8?q?=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/component/Detail/DesignDetail.vue | 62 ++++++++++++++------ src/component/Detail/model/modelPosition.vue | 7 ++- 2 files changed, 51 insertions(+), 18 deletions(-) diff --git a/src/component/Detail/DesignDetail.vue b/src/component/Detail/DesignDetail.vue index bf9d650a..e36a11a2 100644 --- a/src/component/Detail/DesignDetail.vue +++ b/src/component/Detail/DesignDetail.vue @@ -545,9 +545,7 @@ export default defineComponent({ await detailDom.canvasBox.privewDetail() await upDateFrontBackSketch() saveCanvasJSONToSession() - if(detailData.isEditPattern.value == 'canvasEditor'){ - await uploadElement() - } + await uploadSelectDetail() detailData.loadingShow = false } } @@ -675,22 +673,16 @@ export default defineComponent({ if(detailData.isEditPattern.value == 'canvasEditor'){ // await detailDom.canvasBox.saveCanvas() const allInfo = await (detailDom.canvasBox as any).getCanvasElement() - if(allInfo.trims?.length > 0){ - // detailData.selectDetail.trims.prints = allInfo.trims - let value = { - data:allInfo.trims, - str:'element' - } - store.commit('DesignDetail/setNewDetail',value) + let trimsValue = { + data:allInfo.trims || [], + str:'element' } - if(allInfo.prints?.length > 0){ - // detailData.selectDetail.printObject.prints = allInfo.prints - let value = { - data:allInfo.prints, - str:'print' - } - store.commit('DesignDetail/setNewDetail',value) + store.commit('DesignDetail/setNewDetail',trimsValue) + let printValue = { + data:allInfo.prints || [], + str:'print' } + store.commit('DesignDetail/setNewDetail',printValue) if(allInfo.color?.color?.rgba){ let canvasColor = allInfo.color.color; let colorData:any = await getColorName(allInfo.color.color?.rgba) @@ -716,9 +708,45 @@ export default defineComponent({ if(detailData.currentDetailType == 'color'){ detailData.detailLeftColorKey++ } + }else{ + let value = { + data:{}, + str:'color' + } + store.commit('DesignDetail/setNewDetail',value) } } } + const uploadSelectDetail = async ()=>{//更新选中的detail + // await detailDom.canvasBox.saveCanvas() + const allInfo = await (detailDom.canvasBox as any).getCanvasElement() + let color:any = {} + if(allInfo.color?.color?.rgba){ + let canvasColor = allInfo.color.color; + let colorData:any = await getColorName(allInfo.color.color?.rgba) + color = { + hsv:{ + h:colorData.h, + s:colorData.s, + v:colorData.v, + }, + name:colorData.name, + tcx:colorData.tcx, + rgba:canvasColor.rgba, + hex:rgbaToHex([canvasColor.rgba.r,canvasColor.rgba.g,canvasColor.rgba.b]), + } + if(canvasColor.gradient){ + color.gradient = canvasColor.gradient + } + if(detailData.currentDetailType == 'color'){ + detailData.detailLeftColorKey++ + } + } + detailData.selectDetail.trims.prints = allInfo.trims || [] + detailData.selectDetail.printObject.prints = allInfo.prints || [] + detailData.selectDetail.color = color + + } const canvasReload = async ()=>{ if(detailData.isEditPattern.value){ await detailDom.canvasBox.saveCanvas() diff --git a/src/component/Detail/model/modelPosition.vue b/src/component/Detail/model/modelPosition.vue index 51da1ef3..52869e50 100644 --- a/src/component/Detail/model/modelPosition.vue +++ b/src/component/Detail/model/modelPosition.vue @@ -14,7 +14,12 @@
- +
+ +
+
+ +
From 59399d672fb952f574849a09a69ea266721d27b2 Mon Sep 17 00:00:00 2001 From: X1627315083 <1627315083@qq.com> Date: Thu, 22 Jan 2026 10:48:42 +0800 Subject: [PATCH 14/16] fix --- src/component/Detail/DesignDetail.vue | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/src/component/Detail/DesignDetail.vue b/src/component/Detail/DesignDetail.vue index e36a11a2..ff753391 100644 --- a/src/component/Detail/DesignDetail.vue +++ b/src/component/Detail/DesignDetail.vue @@ -742,9 +742,26 @@ export default defineComponent({ detailData.detailLeftColorKey++ } } - detailData.selectDetail.trims.prints = allInfo.trims || [] - detailData.selectDetail.printObject.prints = allInfo.prints || [] - detailData.selectDetail.color = color + if(detailData.isEditPattern.value !== 'canvasEditor'){ + delete detailData.selectDetail.newDetail + detailData.selectDetail.trims.prints = allInfo.trims || [] + detailData.selectDetail.printObject.prints = allInfo.prints || [] + detailData.selectDetail.color = color + }else{ + if(detailData.currentDetailType == 'color'){ + delete detailData.selectDetail.newDetail.color + detailData.selectDetail.color = color + } + if(detailData.currentDetailType == 'print'){ + delete detailData.selectDetail.newDetail.print + detailData.selectDetail.printObject.prints = allInfo.prints || [] + } + if(detailData.currentDetailType == 'element'){ + delete detailData.selectDetail.newDetail.element + detailData.selectDetail.trims.prints = allInfo.trims || [] + } + } + } const canvasReload = async ()=>{ From 1b30a7a873b93c1f2f531a1ec758bbb2ddd2dbbc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E5=BF=97=E9=B9=8F?= <2916022834@qq.com> Date: Thu, 22 Jan 2026 11:19:12 +0800 Subject: [PATCH 15/16] =?UTF-8?q?=E6=9B=B4=E6=94=B9=E7=94=BB=E5=B8=83?= =?UTF-8?q?=E6=A0=87=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Canvas/CanvasEditor/components/HeaderMenu.vue | 3 ++- src/component/Canvas/CanvasEditor/index.vue | 5 +++++ src/component/Detail/canvas/index.vue | 5 ++++- src/component/modules/generalMiniCanvas.vue | 11 +++++++++++ src/lang/cn.ts | 5 +++++ src/lang/en.ts | 5 +++++ 6 files changed, 32 insertions(+), 2 deletions(-) diff --git a/src/component/Canvas/CanvasEditor/components/HeaderMenu.vue b/src/component/Canvas/CanvasEditor/components/HeaderMenu.vue index 9d2e2de9..d1e03863 100644 --- a/src/component/Canvas/CanvasEditor/components/HeaderMenu.vue +++ b/src/component/Canvas/CanvasEditor/components/HeaderMenu.vue @@ -11,6 +11,7 @@ const layerManager = inject("layerManager"); const isShowLayerPanel = inject("isShowLayerPanel", ref(false)); const props = defineProps({ + title: String, activeTool: String, canvasWidth: Number, canvasHeight: Number, @@ -274,7 +275,7 @@ onMounted(() => {