@@ -144,12 +144,13 @@
@click="changePasswordType()"
>
-
{{ userI18n[selectUserI18n].inputPasswordTip }}
-
{{ userI18n[selectUserI18n].Email }}
+
{{ userI18n[selectUserI18n].Email }}
* {
@@ -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 @@
-
-
-
-
-
{{ $t('admin.CreateTime') }}:
-
-
-
-
-
-
-
-
-
-
{{ $t('admin.UserName') }}:
-
-
-
-
-
-
- {{ $t('admin.search') }}
-
-
- {{ $t('admin.add') }}
-
-
- {{ $t('admin.DownloadTemplate') }}
-
-
- {{ $t('admin.UploadTemplate') }}
-
-
- {{ $t('admin.ExportAccountData') }}
-
-
- {{ $t('admin.Delete') }}
-
-
-
-
- {{ $t('admin.NearlyAYear') }}
-
-
- {{ $t('admin.LastMonth') }}
-
-
- {{ $t('admin.LastWeek') }}
-
-
+
+
+
+ {{ $t('admin.search') }}
-
-
+ {{ $t('admin.add') }}
+
+
+ {{ $t('admin.DownloadTemplate') }}
+
+
+ {{ $t('admin.UploadTemplate') }}
+
+
+ {{ $t('admin.ExportAccountData') }}
+
+
+ {{ $t('admin.Delete') }}
+
+
+
+
+ {{ $t('admin.NearlyAYear') }}
+
+
+ {{ $t('admin.LastMonth') }}
+
+
+ {{ $t('admin.LastWeek') }}
+
+
+
+
+
+
+
+
-
-
-
- {{ $t('admin.Edit') }}
-
-
- {{ $t('admin.Delete') }}
-
-
-
-
-
-
-
+
+
+
+
+
\ 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 @@