From cd7d572e4391cc62b63d631faa77038cfc0d076f Mon Sep 17 00:00:00 2001 From: X1627315083 <1627315083@qq.com> Date: Thu, 22 Jan 2026 14:30:40 +0800 Subject: [PATCH 01/19] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E9=A6=96=E6=AC=A1?= =?UTF-8?q?=E6=89=93=E5=BC=80detail=20=E5=BA=94=E8=AF=A5=E4=BD=BF=E7=94=A8?= =?UTF-8?q?=E6=8E=A5=E5=8F=A3=E6=95=B0=E6=8D=AE=E8=80=8C=E4=B8=8D=E6=98=AF?= =?UTF-8?q?new=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 | 30 +++++++++++-------- src/component/Detail/canvas/index.vue | 2 +- .../Detail/detailLeft/colorBox/index.vue | 1 - src/lang/en.ts | 2 +- 4 files changed, 19 insertions(+), 16 deletions(-) diff --git a/src/component/Detail/DesignDetail.vue b/src/component/Detail/DesignDetail.vue index ff753391..6f72c68c 100644 --- a/src/component/Detail/DesignDetail.vue +++ b/src/component/Detail/DesignDetail.vue @@ -331,15 +331,15 @@ export default defineComponent({ } const setClothes = async (list:any,str:string)=>{ let clothesList:any = [] - await uploadElement() if(detailData.isEditPattern.value == 'editSketch')await detailDom.canvasBox.submitBase64Data().then((rv)=>{ detailData.selectDetail.sketchString = rv }) if(detailDom.detailRight?.privewDetail)await (detailDom.detailRight as any).privewDetail() if(detailDom.canvasBox && (detailData.currentDetailType != 'sketch' || detailData.isEditPattern.value == 'canvasEditor')){ - let otherData = await updateOtherLayers('single') + let otherData = await updateOtherLayers(detailData.isEditPattern.value == 'canvasEditor'?'all':'single') await detailDom.canvasBox.updateOtherLayers(otherData) await detailDom.canvasBox.privewDetail() + await uploadElement() } for(let i = 0;i{ + detailData.loadingShow = true let workspace = store.state.Workspace.probjects let clothes:any = await setClothes(detailData.designDetail.clothes,'sub') let data = { @@ -494,7 +498,6 @@ export default defineComponent({ processId:userDetail.value.userId, probjectId:store.state.Workspace.probjects.id, } - detailData.loadingShow = true Https.axiosPost(Https.httpUrls.designSingle, data).then(async (rv)=>{ saveCanvasJSONToSession() // store.commit('DesignDetail/setPraeview',rv) @@ -526,8 +529,9 @@ export default defineComponent({ } const previwe = async ()=>{ detailData.loadingShow = true - if((detailData.currentDetailType == 'sketch' && !detailData.isEditPattern.value) || detailData.isEditPattern.value == 'editSketch'){ + if((detailData.currentDetailType == 'models' && !detailData.isEditPattern.value) || (detailData.currentDetailType == 'sketch' && !detailData.isEditPattern.value) || detailData.isEditPattern.value == 'editSketch'){ await getSubmitData('preview') + if(detailData.currentDetailType == 'models' && !detailData.isEditPattern.value)return await getSketchSize() detailDom.canvasBox.changeSketchUpdateFrontBack = async ()=>{ await detailDom.canvasBox.privewDetail() @@ -633,14 +637,14 @@ export default defineComponent({ }); }) } - const updateOtherLayers = async (str:any='all')=>{//更新到画布图层 + const updateOtherLayers = async (str:any='all',type:any='noFirst')=>{//更新到画布图层 let otherData:any = {} if(detailDom.detailRight?.privewDetail)await (detailDom.detailRight as any).privewDetail() if(str == 'all'){ otherData = { - color: detailData.selectDetail.newDetail?.color?.r?detailData.selectDetail.newDetail?.color:detailData.selectDetail.color, - printObject: detailData.selectDetail.newDetail?.print?.length>0?{prints:detailData.selectDetail.newDetail?.print}:detailData.selectDetail.printObject || null, - trims: detailData.selectDetail.newDetail?.element?.length>0?detailData.selectDetail.newDetail?.element:detailData.selectDetail.trims || null, + color: type == 'first'? detailData.selectDetail.color:detailData.selectDetail.newDetail?.color, + printObject: type == 'first'? detailData.selectDetail.printObject || null:{prints:detailData.selectDetail.newDetail?.print}, + trims: type == 'first'? detailData.selectDetail.trims || null:{prints:detailData.selectDetail.newDetail?.element}, } }else if(str == 'single'){ otherData = { @@ -661,10 +665,10 @@ export default defineComponent({ } } if(detailData.currentDetailType == 'print'){ - otherData.printObject = detailData.selectDetail.newDetail?.print?.length>0?{prints:detailData.selectDetail.newDetail?.print}:detailData.selectDetail.printObject || null + otherData.printObject = {prints:detailData.selectDetail.newDetail?.print || []} } if(detailData.currentDetailType == 'element'){ - otherData.trims = detailData.selectDetail.newDetail?.element?.length>0?{prints:detailData.selectDetail.newDetail?.element}:detailData.selectDetail.trims || null + otherData.trims = {prints:detailData.selectDetail.newDetail?.element || []} } } return otherData diff --git a/src/component/Detail/canvas/index.vue b/src/component/Detail/canvas/index.vue index bcca72b7..3cdf8d69 100644 --- a/src/component/Detail/canvas/index.vue +++ b/src/component/Detail/canvas/index.vue @@ -338,7 +338,7 @@ export default defineComponent({ // },3000) // } const canvasLoadJsonSuccess = async ()=>{ - let otherData = await props.updateOtherLayers() + let otherData = await props.updateOtherLayers('all','first') await updateOtherLayers(otherData) if(detailData.changeSketchUpdateFrontBack){ await detailData.changeSketchUpdateFrontBack() diff --git a/src/component/Detail/detailLeft/colorBox/index.vue b/src/component/Detail/detailLeft/colorBox/index.vue index d278d1ce..382330b5 100644 --- a/src/component/Detail/detailLeft/colorBox/index.vue +++ b/src/component/Detail/detailLeft/colorBox/index.vue @@ -145,7 +145,6 @@ export default defineComponent({ colorData.selectDetail.color.rgba?.g == color?.rgba?.g && colorData.selectDetail.color.rgba?.b == color?.rgba?.b || (JSON.stringify(colorData.selectDetail.color.gradient) == JSON.stringify(color?.gradient) && colorData.selectDetail.color.gradient) - && colorData.selectDetail.color.rgba?.r ){ console.log(123) isNoSelect = true diff --git a/src/lang/en.ts b/src/lang/en.ts index 1794a793..ae823e1e 100644 --- a/src/lang/en.ts +++ b/src/lang/en.ts @@ -1184,7 +1184,7 @@ export default { CanvasTitle: { ModifySketch: 'Modify Sketch', ModifyItem: 'Modify Item', - RedGreen: 'Front and back section', + RedGreen: 'Edit Front and Back Section', }, Canvas: { Canvas: 'Canvas', From 2ab23d0f30b88efe769182b495e9bfd3f5786d97 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 15:23:15 +0800 Subject: [PATCH 02/19] =?UTF-8?q?=E5=8D=B0=E8=8A=B1=E5=85=83=E7=B4=A0?= =?UTF-8?q?=E5=88=86=E7=B1=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../CanvasEditor/managers/CanvasManager.js | 8 ++- .../CanvasEditor/managers/PartManager.js | 71 +++++++++++++------ 2 files changed, 56 insertions(+), 23 deletions(-) diff --git a/src/component/Canvas/CanvasEditor/managers/CanvasManager.js b/src/component/Canvas/CanvasEditor/managers/CanvasManager.js index 30be134d..6aa63a6d 100644 --- a/src/component/Canvas/CanvasEditor/managers/CanvasManager.js +++ b/src/component/Canvas/CanvasEditor/managers/CanvasManager.js @@ -1217,9 +1217,9 @@ backgroundObject.scaleY,'CanvasManager resetCanvasSizeByFixedLayer') obj.object.gapX = fill_.gapX; obj.object.gapY = fill_.gapY; } - if(obj.level2Type === "Pattern"){ + if(sourceData.type === "print"){ prints.push(obj); - }else if(obj.level2Type === "Embroidery"){ + }else if(sourceData.type === "trims"){ trims.push(obj); } }) @@ -1510,6 +1510,7 @@ backgroundObject.scaleY,'CanvasManager resetCanvasSizeByFixedLayer') const singleLayers = [];// 平铺图层 otherData_.printObject?.prints?.forEach((print, index) => {// 印花 print.name = t("Canvas.Print") + (index + 1); + print.type = "print"; if(print.ifSingle){ printTrimsLayers.unshift({...print}); }else{ @@ -1518,6 +1519,7 @@ backgroundObject.scaleY,'CanvasManager resetCanvasSizeByFixedLayer') }) otherData_.trims?.prints?.forEach((trims, index) => {// 元素 trims.name = t("Canvas.Elements") + (index + 1); + trims.type = "trims"; printTrimsLayers.unshift({...trims}); }) if(isUpdate ? updateSpecialGroup : true){ @@ -1648,7 +1650,7 @@ backgroundObject.scaleY,'CanvasManager resetCanvasSizeByFixedLayer') let flipX = false; let flipY = false; let blendMode = BlendMode.MULTIPLY; - if(item.level2Type === "Embroidery") blendMode = BlendMode.NORMAL;// 元素正常 + if(item.type === "trims") blendMode = BlendMode.NORMAL;// 元素正常 if(item.object){ opacity = item.object.opacity flipX = item.object.flipX diff --git a/src/component/Canvas/CanvasEditor/managers/PartManager.js b/src/component/Canvas/CanvasEditor/managers/PartManager.js index 35d1af71..b9a1c304 100644 --- a/src/component/Canvas/CanvasEditor/managers/PartManager.js +++ b/src/component/Canvas/CanvasEditor/managers/PartManager.js @@ -79,8 +79,9 @@ export class PartManager { this.cleanupEvents(); this.clearPartObject(); this.clearPointData(); - }else{ - // this.clearPointData(); + } else { + this.clearPointData(); + this.resetPartObject(); } console.log("切换工具", toolId); } @@ -222,11 +223,7 @@ export class PartManager { const isLeft = button === 1;// 左键1(添加) 右键3(删除) const fixedObject = this.canvasManager.getFixedLayerObject(); if (!fixedObject) return console.warn("未找到固定图层"); - const { x, y } = options.absolutePointer; - const width = fixedObject.width * fixedObject.scaleX; - const height = fixedObject.height * fixedObject.scaleY; - const X = (x - (fixedObject.left - width / 2)) / fixedObject.scaleX; - const Y = (y - (fixedObject.top - height / 2)) / fixedObject.scaleY; + const { x, y } = this.handleMousePosition(options, fixedObject); const label = isLeft ? 1 : 0; const points = []; const labels = []; @@ -234,19 +231,16 @@ export class PartManager { points.push([item.x, item.y]); labels.push(item.label); }); - points.push([X, Y]); + points.push([x, y]); labels.push(label); const url = await this.getSegAnythingImage({ - image_path: this.props.clothingMinIOPath, type: "point", points, labels, - // type: "box", - // box: [0,0,0,0], }); this.pointList.push({ - x: X, - y: Y, + x: x, + y: y, label: label, }) const image1 = await this.loadImageToObject(url); @@ -283,15 +277,39 @@ export class PartManager { /** 框选工具模式下点击事件处理 */ _rectangleDownHandler(options) { - console.log(options.absolutePointer); + this.clearPointData(); + const fixedObject = this.canvasManager.getFixedLayerObject(); + if (!fixedObject) return console.warn("未找到固定图层"); + const { x, y } = this.handleMousePosition(options, fixedObject); + this.pointList.push(x, y); } /** 框选工具模式下移动事件处理 */ - _rectangleMoveHandler(options) { - - } + _rectangleMoveHandler(options) { } /** 框选工具模式下抬起事件处理 */ - _rectangleUpHandler(options) { - console.log(options.absolutePointer); + async _rectangleUpHandler(options) { + const fixedObject = this.canvasManager.getFixedLayerObject(); + if (!fixedObject) return console.warn("未找到固定图层"); + const { x, y } = this.handleMousePosition(options, fixedObject); + this.pointList.push(x, y); + + if (this.pointList.length !== 4) return console.warn("框选工具选择区域必须是矩形"); + const url = await this.getSegAnythingImage({ + type: "box", + box: [...this.pointList], + }); + const image1 = await this.loadImageToObject(url); + this.resetPartObject(); + const group = this.partGroup; + const rgba = { r: 0, g: 255, b: 0, a: 200 } + const canvas = getObjectAlphaToCanvas(image1, null, 0, rgba); + this.partCanvas = canvas; + const image2 = new fabric.Image(canvas); + image2.set({ + originX: fixedObject.originX, + originY: fixedObject.originY, + }); + group.add(image2); + this.canvas.renderAll(); } @@ -318,7 +336,19 @@ export class PartManager { } - + /** 处理鼠标点位 */ + handleMousePosition(options, fixedObject) { + const pos = options.absolutePointer; + const { x, y } = options.absolutePointer; + const width = fixedObject.width * fixedObject.scaleX; + const height = fixedObject.height * fixedObject.scaleY; + const X = (x - (fixedObject.left - width / 2)) / fixedObject.scaleX; + const Y = (y - (fixedObject.top - height / 2)) / fixedObject.scaleY; + return { + x: Math.round(X), + y: Math.round(Y), + } + } /** 获取分隔后图片 */ async getSegAnythingImage(obj) { @@ -329,6 +359,7 @@ export class PartManager { // const user_id = store.state.UserHabit.userDetail.userId; const user_id = 24299; const data = { + image_path: this.props.clothingMinIOPath, user_id, ...obj, } From 3c77c9753227ba7b9d8436ca31e818c41cb34c0b Mon Sep 17 00:00:00 2001 From: X1627315083 <1627315083@qq.com> Date: Thu, 22 Jan 2026 15:40:28 +0800 Subject: [PATCH 03/19] fix --- src/component/Detail/DesignDetail.vue | 86 ++++++++++--------- .../Detail/detailLeft/colorBox/index.vue | 4 +- 2 files changed, 49 insertions(+), 41 deletions(-) diff --git a/src/component/Detail/DesignDetail.vue b/src/component/Detail/DesignDetail.vue index 6f72c68c..8bfe3017 100644 --- a/src/component/Detail/DesignDetail.vue +++ b/src/component/Detail/DesignDetail.vue @@ -336,16 +336,17 @@ export default defineComponent({ }) if(detailDom.detailRight?.privewDetail)await (detailDom.detailRight as any).privewDetail() if(detailDom.canvasBox && (detailData.currentDetailType != 'sketch' || detailData.isEditPattern.value == 'canvasEditor')){ - let otherData = await updateOtherLayers(detailData.isEditPattern.value == 'canvasEditor'?'all':'single') - await detailDom.canvasBox.updateOtherLayers(otherData) + if(detailData.isEditPattern.value !== 'editSketch'){ + let otherData = await updateOtherLayers(detailData.isEditPattern.value == 'canvasEditor'?'all':'single') + await detailDom.canvasBox.updateOtherLayers(otherData) + } await detailDom.canvasBox.privewDetail() await uploadElement() } for(let i = 0;i Date: Thu, 22 Jan 2026 16:00:45 +0800 Subject: [PATCH 04/19] fix --- src/component/Detail/DesignDetail.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/component/Detail/DesignDetail.vue b/src/component/Detail/DesignDetail.vue index 8bfe3017..6a5fcbcd 100644 --- a/src/component/Detail/DesignDetail.vue +++ b/src/component/Detail/DesignDetail.vue @@ -733,7 +733,7 @@ export default defineComponent({ let color:any = {} if(allInfo.color?.color?.rgba || allInfo.color?.color?.gradient){ let canvasColor = allInfo.color.color; - if(allInfo.color?.color?.rgba){ + if(canvasColor?.rgba?.r){ let colorData:any = await getColorName(allInfo.color.color?.rgba) color = { hsv:{ From c5b736597746b43aea7b368a2c60fffaee3beb15 Mon Sep 17 00:00:00 2001 From: X1627315083 <1627315083@qq.com> Date: Fri, 23 Jan 2026 13:34:28 +0800 Subject: [PATCH 05/19] =?UTF-8?q?=E8=B0=83=E6=95=B4=E9=83=A8=E7=BD=B2?= =?UTF-8?q?=E6=97=A5=E6=9C=9F=E4=BF=AE=E5=A4=8Ddetail=E5=8D=B0=E8=8A=B1?= =?UTF-8?q?=E7=B4=AF=E5=8A=A0=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/component/Detail/DesignDetail.vue | 8 +- .../Detail/detailRight/editPrintElement.vue | 5 +- .../overallSetting/RepeatSetting.vue | 34 +- src/component/Detail/model/modelNav.vue | 3 +- .../Detail/model/modelPosition copy.vue | 705 ++++++++++++++++++ src/component/Detail/model/modelPosition.vue | 5 +- src/router/index.ts | 2 +- src/views/Upgrade.vue | 10 +- 8 files changed, 752 insertions(+), 20 deletions(-) create mode 100644 src/component/Detail/model/modelPosition copy.vue diff --git a/src/component/Detail/DesignDetail.vue b/src/component/Detail/DesignDetail.vue index 6a5fcbcd..03591432 100644 --- a/src/component/Detail/DesignDetail.vue +++ b/src/component/Detail/DesignDetail.vue @@ -357,7 +357,7 @@ export default defineComponent({ // ] let isCurrent = list[i].id == detailData?.selectDetail?.id let color = '' - let gradient = {} + let gradient = null if((detailData.currentDetailType == 'color' || detailData.isEditPattern.value == 'canvasEditor') && isCurrent){ color = `${newData?.color.rgba.r} ${newData?.color.rgba.g} ${newData?.color.rgba.b}` if(newData?.color.gradient){ @@ -379,8 +379,6 @@ export default defineComponent({ }) } } - console.log(newData,'========') - if(newData)console.log(JSON.parse(JSON.stringify(newData))) let data:any = { changed:false, color, @@ -552,8 +550,8 @@ export default defineComponent({ } await detailDom.canvasBox.privewDetail() await upDateFrontBackSketch() - saveCanvasJSONToSession() await uploadSelectDetail() + saveCanvasJSONToSession() detailData.loadingShow = false } } @@ -754,7 +752,7 @@ export default defineComponent({ detailData.detailLeftColorKey++ } } - if(detailData.isEditPattern.value !== 'canvasEditor'){ + if(detailData.isEditPattern.value == 'canvasEditor'){ delete detailData.selectDetail.newDetail detailData.selectDetail.trims.prints = allInfo.trims || [] detailData.selectDetail.printObject.prints = allInfo.prints || [] diff --git a/src/component/Detail/detailRight/editPrintElement.vue b/src/component/Detail/detailRight/editPrintElement.vue index 1fbefccb..ae4ababb 100644 --- a/src/component/Detail/detailRight/editPrintElement.vue +++ b/src/component/Detail/detailRight/editPrintElement.vue @@ -482,9 +482,8 @@ export default defineComponent({ } if(arr.length > 0){ editPrintElementData.imgDomIndex = 0 - editPrintElementData.printStyleList[props.type][newVal] = [] - // editPrintElementData.printStyleList[props.type].single = [] - // editPrintElementData.printStyleList[props.type].overall = [] + editPrintElementData.printStyleList[props.type].single = [] + editPrintElementData.printStyleList[props.type].overall = [] arr.forEach((item:any,index:number) => { getItemPosition(item) }); diff --git a/src/component/Detail/detailRight/overallSetting/RepeatSetting.vue b/src/component/Detail/detailRight/overallSetting/RepeatSetting.vue index 2f5418db..16160cb0 100644 --- a/src/component/Detail/detailRight/overallSetting/RepeatSetting.vue +++ b/src/component/Detail/detailRight/overallSetting/RepeatSetting.vue @@ -1,6 +1,5 @@ From 9cc012b851a5096d0a55dfef2f2a93f591dbc131 Mon Sep 17 00:00:00 2001 From: X1627315083 <1627315083@qq.com> Date: Fri, 23 Jan 2026 14:43:19 +0800 Subject: [PATCH 06/19] =?UTF-8?q?=E4=BF=AE=E5=A4=8Ddetail=E7=9B=B8?= =?UTF-8?q?=E5=85=B3bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/component/Detail/DesignDetail.vue | 21 +++++++++++-------- .../Detail/detailRight/editPrintElement.vue | 2 ++ src/component/Detail/model/modelPosition.vue | 2 +- 3 files changed, 15 insertions(+), 10 deletions(-) diff --git a/src/component/Detail/DesignDetail.vue b/src/component/Detail/DesignDetail.vue index 03591432..a9d5bf58 100644 --- a/src/component/Detail/DesignDetail.vue +++ b/src/component/Detail/DesignDetail.vue @@ -398,7 +398,7 @@ export default defineComponent({ partialDesign:list[i].partialDesign, // partialDesign:detailData.isEditPattern.value?list[i].partialDesign:{}, path:(newData?.sketch && detailData.currentDetailType == 'sketch' && isCurrent && !detailData.isEditPattern.value)?newData?.sketch.minIOPath:list[i].minIOPath, - printObject:((newData?.prints && detailData.currentDetailType == 'print' || detailData.isEditPattern.value == 'canvasEditor') && isCurrent)?{prints:newData.prints}:list[i].printObject?list[i].printObject:{prints:[]}, + printObject:((newData?.print?.length>0 && (detailData.currentDetailType == 'print' || detailData.isEditPattern.value == 'canvasEditor')) && isCurrent)?{prints:newData.print}:list[i].printObject?list[i].printObject:{prints:[]}, priority, // scale:[ // 0.5, @@ -407,9 +407,8 @@ export default defineComponent({ scale:[scale[0]?scale[0]:1,scale[1]?scale[1]:1], type:(newData?.sketch && detailData.currentDetailType == 'sketch' && isCurrent && !detailData.isEditPattern.value)?newData?.sketch.level2Type || newData?.sketch.categoryValue:list[i].type, sketchString:list[i].sketchString?list[i].sketchString:'', - trims:((newData?.trims && detailData.currentDetailType == 'element' || detailData.isEditPattern.value == 'canvasEditor') && isCurrent)?{prints:newData.trims}:list[i].trims?.prints?list[i].trims:{prints:[]}, + trims:((newData?.element?.length>0 && (detailData.currentDetailType == 'element' || detailData.isEditPattern.value == 'canvasEditor')) && isCurrent)?{prints:newData.element}:list[i].trims?.prints?list[i].trims:{prints:[]}, } - console.log(JSON.parse(JSON.stringify(data))) printObjectToJSON(data.printObject.prints) printObjectToJSON(data.trims.prints) if((detailData.isEditPattern.value && list[i].color?.gradient) || (!detailData.isEditPattern.value && (list[i].newDetail?.color?.gradient || list[i].color?.gradient))){ @@ -458,6 +457,7 @@ export default defineComponent({ let el:any = document.querySelector('.molepositon .perview_img') let scale = 0 await new Promise(async (resolve, reject) => { + if(!detailData.frontBack.body.path)resolve(true) const img = new Image(); img.src = detailData.frontBack.body.path; img.onload = () => { @@ -533,7 +533,7 @@ export default defineComponent({ detailData.loadingShow = true if((detailData.currentDetailType == 'models' && !detailData.isEditPattern.value) || (detailData.currentDetailType == 'sketch' && !detailData.isEditPattern.value) || detailData.isEditPattern.value == 'editSketch'){ await getSubmitData('preview') - if(detailData.currentDetailType == 'models' && !detailData.isEditPattern.value)return + if(detailData.currentDetailType == 'models')return detailData.loadingShow = false await getSketchSize() detailDom.canvasBox.changeSketchUpdateFrontBack = async ()=>{ await detailDom.canvasBox.privewDetail() @@ -641,12 +641,13 @@ export default defineComponent({ } const updateOtherLayers = async (str:any='all',type:any='noFirst')=>{//更新到画布图层 let otherData:any = {} - if(detailDom.detailRight?.privewDetail)await (detailDom.detailRight as any).privewDetail() + console.log('detailData.selectDetail.newDetail',detailData.selectDetail) if(str == 'all'){ + await uploadSelectDetail() otherData = { - color: type == 'first'? detailData.selectDetail.color:detailData.selectDetail.newDetail?.color, - printObject: type == 'first'? detailData.selectDetail.printObject || null:{prints:detailData.selectDetail.newDetail?.print}, - trims: type == 'first'? detailData.selectDetail.trims || null:{prints:detailData.selectDetail.newDetail?.element}, + color: detailData.selectDetail.color, + printObject: detailData.selectDetail.printObject || null, + trims: detailData.selectDetail.trims || null, } }else if(str == 'single'){ otherData = { @@ -667,6 +668,7 @@ export default defineComponent({ } } if(detailData.currentDetailType == 'print'){ + if(detailDom.detailRight?.privewDetail)await (detailDom.detailRight as any).privewDetail() otherData.printObject = {prints:detailData.selectDetail.newDetail?.print || []} } if(detailData.currentDetailType == 'element'){ @@ -691,7 +693,8 @@ export default defineComponent({ store.commit('DesignDetail/setNewDetail',printValue) if(allInfo.color?.color?.rgba || allInfo.color?.color?.gradient){ let value:any = { - str:'color' + str:'color', + data:{}, } let canvasColor = allInfo.color.color; if(allInfo.color?.color?.rgba){ diff --git a/src/component/Detail/detailRight/editPrintElement.vue b/src/component/Detail/detailRight/editPrintElement.vue index ae4ababb..fe2c678b 100644 --- a/src/component/Detail/detailRight/editPrintElement.vue +++ b/src/component/Detail/detailRight/editPrintElement.vue @@ -314,6 +314,7 @@ export default defineComponent({ str:props.type, id:id, } + console.log('data',value) store.commit('DesignDetail/setNewDetail',value) } const sort = (list:any)=>{ @@ -473,6 +474,7 @@ export default defineComponent({ setPosition() },{immediate: true,}) watch(()=>editPrintElementData.stateOverallSingle,(newVal)=>{ + previewDetailPrintData() let arr:any = editPrintElementData.selectDetail.newDetail?.print || editPrintElementData.selectDetail.printObject.prints if(props.type == 'element'){ arr = editPrintElementData.selectDetail.newDetail?.element || editPrintElementData.selectDetail.trims.prints diff --git a/src/component/Detail/model/modelPosition.vue b/src/component/Detail/model/modelPosition.vue index f7524167..733050e4 100644 --- a/src/component/Detail/model/modelPosition.vue +++ b/src/component/Detail/model/modelPosition.vue @@ -28,7 +28,7 @@
From 86db2f22a16e1c284056d211148e65d974e8dcad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E5=BF=97=E9=B9=8F?= <2916022834@qq.com> Date: Fri, 23 Jan 2026 15:24:39 +0800 Subject: [PATCH 07/19] =?UTF-8?q?=E5=90=8C=E6=AD=A5=E5=8D=B0=E8=8A=B1?= =?UTF-8?q?=E7=9A=84=E7=BC=A9=E6=94=BE=E5=81=8F=E7=A7=BB=E6=98=BE=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/BrushControlPanel.vue | 2 + .../SelectMenuPanel/RepeatSetting.vue | 102 ++++++++----- .../components/SelectMenuPanel/index.vue | 8 +- .../CanvasEditor/managers/CanvasManager.js | 38 +++-- .../CanvasEditor/managers/PartManager.js | 144 ++++++++++++------ .../CanvasEditor/managers/ToolManager.js | 33 +++- .../Canvas/CanvasEditor/utils/objectHelper.js | 4 + src/component/Canvas/canvasExample.vue | 1 - .../overallSetting/RepeatSetting.vue | 1 + 9 files changed, 224 insertions(+), 109 deletions(-) diff --git a/src/component/Canvas/CanvasEditor/components/BrushControlPanel.vue b/src/component/Canvas/CanvasEditor/components/BrushControlPanel.vue index 310b6a60..0a8efeb4 100644 --- a/src/component/Canvas/CanvasEditor/components/BrushControlPanel.vue +++ b/src/component/Canvas/CanvasEditor/components/BrushControlPanel.vue @@ -154,6 +154,8 @@ const isVisible = computed(() => { OperationType.ERASER, OperationType.RED_BRUSH, OperationType.GREEN_BRUSH, + OperationType.PART_BRUSH, + OperationType.PART_ERASER, ].includes(props.activeTool); }); diff --git a/src/component/Canvas/CanvasEditor/components/SelectMenuPanel/RepeatSetting.vue b/src/component/Canvas/CanvasEditor/components/SelectMenuPanel/RepeatSetting.vue index fd59a643..3e699e09 100644 --- a/src/component/Canvas/CanvasEditor/components/SelectMenuPanel/RepeatSetting.vue +++ b/src/component/Canvas/CanvasEditor/components/SelectMenuPanel/RepeatSetting.vue @@ -14,7 +14,7 @@ {{ t("Canvas.scale") }} {{ t("Canvas.offset") }}
@@ -79,29 +79,6 @@ import Slider from "../tools/Slider.vue"; import { useI18n } from "vue-i18n"; const { t } = useI18n(); - - const props = defineProps({ - object: { - required: true, - type: Object, - }, - }); - const angle = computed( - () => getTransformScaleAngle(props.object.fill?.patternTransform).angle - ); - const scale = computed(() => { - const patternTransform = props.object.fill?.patternTransform; - const scaleValue = getTransformScaleAngle(patternTransform).scale * 100; - return Number(Number(scaleValue).toFixed(2)); - }); - const gapX = computed(() => props.object.fill_?.gapX || 0); - const gapY = computed(() => props.object.fill_?.gapY || 0); - const offsetX = computed( - () => (props.object.fill?.offsetX / props.object.width) * 100 - ); - const offsetY = computed( - () => (props.object.fill?.offsetY / props.object.height) * 100 - ); const emit = defineEmits([ "inputFillAngle", "changeFillAngle", @@ -112,13 +89,63 @@ "inputFillGap", "changeFillGap", ]); - const inputFillScale = (e) => { + + const props = defineProps({ + object: { + required: true, + type: Object, + }, + }); + const angle = computed( + () => getTransformScaleAngle(props.object.fill?.patternTransform).angle + ); + const gapX = computed(() => props.object.fill_?.gapX || 0); + const gapY = computed(() => props.object.fill_?.gapY || 0); + + // 缩放比例 + const scale = computed(() => { + const object = props.object; + const patternTransform = object.fill?.patternTransform; + const scaleValue = getTransformScaleAngle(patternTransform).scale; + const scaleX = scaleValue / (object.width / object.fill_.width / 5); + const scaleY = scaleValue / (object.height / object.fill_.height / 5); + const scaleXY = object.width > object.height ? scaleX : scaleY; + return Number(Number(scaleXY * 100).toFixed(2)); + }); + const inputFillScale = (e) => setFillScale(e, true); + const changeFillScale = (e) => setFillScale(e, false); + const setFillScale = (e, isInput) => { + const object = props.object; const scale = e / 100; - emit("inputFillScale", scale); + const scaleX = (object.width / object.fill_.width / 5) * scale; + const scaleY = (object.height / object.fill_.height / 5) * scale; + const scaleXY = object.width > object.height ? scaleX : scaleY; + emit(isInput ? "inputFillScale" : "changeFillScale", scaleXY); }; - const changeFillScale = (e) => { - const scale = e / 100; - emit("changeFillScale", scale); + + // 偏移量 + const offset = computed(() => { + const object = props.object; + const patternTransform = object.fill?.patternTransform; + const scale = getTransformScaleAngle(patternTransform).scale; + const offsetX = object.fill?.offsetX; + const offsetY = object.fill?.offsetY; + const twidth = object.fill_?.width; + const theight = object.fill_?.height; + const x = ((offsetX - (twidth * scale) / 2) * 100) / object.width; + const y = ((offsetY - (theight * scale) / 2) * 100) / object.height; + return { x, y }; + }); + const inputFillOffset = (e) => setFillOffset(e, true); + const changeFillOffset = (e) => setFillOffset(e, false); + const setFillOffset = (e, isInput) => { + const { left, top } = e; + const object = props.object; + const patternTransform = object.fill?.patternTransform; + const scale = getTransformScaleAngle(patternTransform).scale; + const x = (left / 100) * object.width + (object.fill_?.width * scale) / 2; + const y = (top / 100) * object.height + (object.fill_?.height * scale) / 2; + emit(isInput ? "inputFillOffset" : "changeFillOffset", { x, y }); }; @@ -126,6 +153,7 @@ .repeat-setting { user-select: none; width: 228px; + overflow: hidden; > .title { line-height: 35px; font-size: 14px; diff --git a/src/component/Canvas/CanvasEditor/components/SelectMenuPanel/index.vue b/src/component/Canvas/CanvasEditor/components/SelectMenuPanel/index.vue index fea8cf41..638f5237 100644 --- a/src/component/Canvas/CanvasEditor/components/SelectMenuPanel/index.vue +++ b/src/component/Canvas/CanvasEditor/components/SelectMenuPanel/index.vue @@ -439,16 +439,16 @@ if (!obj.oldPattern) obj.oldPattern = obj.get("fill"); const pattern = new fabric.Pattern({ ...obj.get("fill"), - offsetX: (value.left / 100) * obj.width, - offsetY: (value.top / 100) * obj.height, + offsetX: value.x, + offsetY: value.y, }); obj.set("fill", pattern); props.canvas.renderAll(); }; const changeFillOffset = (value, obj) => { const pattern = new fabric.Pattern({ - offsetX: (value.left / 100) * obj.width, - offsetY: (value.top / 100) * obj.height, + offsetX: value.x, + offsetY: value.y, }); changeFill(obj, pattern); }; diff --git a/src/component/Canvas/CanvasEditor/managers/CanvasManager.js b/src/component/Canvas/CanvasEditor/managers/CanvasManager.js index 6aa63a6d..fdc87410 100644 --- a/src/component/Canvas/CanvasEditor/managers/CanvasManager.js +++ b/src/component/Canvas/CanvasEditor/managers/CanvasManager.js @@ -70,6 +70,7 @@ export class CanvasManager { this.isFixedErasable = options.isFixedErasable || false; // 是否允许擦除固定图层 this.eraserStateManager = null; // 橡皮擦状态管理器引用 this.handleCanvasInit = null; // 画布初始化回调函数 + this.partManager = options.partManager || null; this.props = options.props || {}; this.emit = options.emit || (() => {}); // 初始化画布 @@ -174,7 +175,12 @@ export class CanvasManager { _initCanvasEvents() { // 添加笔刷图像转换处理回调 this.canvas.onBrushImageConverted = async (fabricImage) => { - await this.addImageToLayer({ fabricImage, targetLayerId: null }); + const activeTool = this.toolManager?.activeTool?.value; + if(activeTool === OperationType.PART_BRUSH){ + this.partManager?.addPartImage(fabricImage); + }else{ + await this.addImageToLayer({ fabricImage, targetLayerId: null }); + } // 返回false表示使用默认行为(直接添加到画布) return false; }; @@ -1208,8 +1214,8 @@ backgroundObject.scaleY,'CanvasManager resetCanvasSizeByFixedLayer') 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; + 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; @@ -1707,15 +1713,15 @@ backgroundObject.scaleY,'CanvasManager resetCanvasSizeByFixedLayer') 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 scaleX_ = flWidth / image.width * (item.scale?.[0] || 1) / 5; + let scaleY_ = flHeight / image.height * (item.scale?.[1] || 1) / 5; + let scale = flWidth > flHeight ? scaleX_ : scaleY_; + let offsetX = (item.location?.[0] || 0) + image.width * scale / 2 + let offsetY = (item.location?.[1] || 0) + image.height * scale / 2 + let top = flTop - flHeight * flScaleY / 2 + let left = flLeft - flWidth * flScaleX / 2 + let scaleX = flScaleX + let scaleY = flScaleY let opacity = 1 let angle = 0 let gapX = 0 @@ -1725,8 +1731,8 @@ backgroundObject.scaleY,'CanvasManager resetCanvasSizeByFixedLayer') let flipY = false; let blendMode = BlendMode.MULTIPLY; if(item.object){ - top += item.object.top * fixedLayerObj.scaleY - left += item.object.left * fixedLayerObj.scaleX + top += item.object.top * flScaleY + left += item.object.left * flScaleX scaleX *= item.object.scaleX scaleY *= item.object.scaleY opacity = item.object.opacity @@ -1742,8 +1748,8 @@ backgroundObject.scaleY,'CanvasManager resetCanvasSizeByFixedLayer') id: id, layerId: id, layerName: name, - width: fixedLayerObj.width, - height: fixedLayerObj.height, + width: flWidth, + height: flHeight, top: top, left: left, scaleX: scaleX, diff --git a/src/component/Canvas/CanvasEditor/managers/PartManager.js b/src/component/Canvas/CanvasEditor/managers/PartManager.js index b9a1c304..1c6262b3 100644 --- a/src/component/Canvas/CanvasEditor/managers/PartManager.js +++ b/src/component/Canvas/CanvasEditor/managers/PartManager.js @@ -53,11 +53,15 @@ export class PartManager { // 当前工具 this.activeTool = this.toolManager.activeTool; + this.rgba = { r: 0, g: 255, b: 0, a: 200 }; this.partGroup = null; // 当前选区对象 this.partId = "part_selector"; this.partCanvas = null;// 选区画布 - // 点选工具相关 + // 点位列表 this.pointList = []; // 存储点选坐标 + + // 绘制列表 + this.drawList = []; // 存储绘制对象 } /** @@ -69,6 +73,10 @@ export class PartManager { const wasActive = this.isActive; this.isActive = this.tools.includes(toolId); + if (toolId === OperationType.PART_ERASER) { + this.setEraserTool(); + } + // 如果从非选区工具切换到选区工具,初始化事件 if (!wasActive && this.isActive) { this.initEvents(); @@ -79,11 +87,12 @@ export class PartManager { this.cleanupEvents(); this.clearPartObject(); this.clearPointData(); - } else { - this.clearPointData(); - this.resetPartObject(); } - console.log("切换工具", toolId); + // 如果从选区工具切换到选区工具,重置选区 + else if (wasActive && this.isActive) { + // this.clearPointData(); + // this.resetPartObject(); + } } /** 初始化选区相关事件 */ @@ -246,8 +255,7 @@ export class PartManager { const image1 = await this.loadImageToObject(url); this.resetPartObject(); const group = this.partGroup; - const rgba = { r: 0, g: 255, b: 0, a: 200 } - const canvas = getObjectAlphaToCanvas(image1, null, 0, rgba); + const canvas = getObjectAlphaToCanvas(image1, null, 0, this.rgba); this.partCanvas = canvas; const image2 = new fabric.Image(canvas); image2.set({ @@ -300,8 +308,7 @@ export class PartManager { const image1 = await this.loadImageToObject(url); this.resetPartObject(); const group = this.partGroup; - const rgba = { r: 0, g: 255, b: 0, a: 200 } - const canvas = getObjectAlphaToCanvas(image1, null, 0, rgba); + const canvas = getObjectAlphaToCanvas(image1, null, 0, this.rgba); this.partCanvas = canvas; const image2 = new fabric.Image(canvas); image2.set({ @@ -311,45 +318,6 @@ export class PartManager { group.add(image2); this.canvas.renderAll(); } - - - /** 绘制工具模式下点击事件处理 */ - _brushDownHandler(options) { - } - /** 绘制工具模式下移动事件处理 */ - _brushMoveHandler(options) { - - } - /** 绘制工具模式下抬起事件处理 */ - _brushUpHandler(options) { - } - - - /** 擦除工具模式下抬起事件处理 */ - _eraseUpHandler(options) { - } - /** 擦除工具模式下点击事件处理 */ - _eraseDownHandler(options) { - } - /** 擦除工具模式下移动事件处理 */ - _eraseMoveHandler(options) { - - } - - /** 处理鼠标点位 */ - handleMousePosition(options, fixedObject) { - const pos = options.absolutePointer; - const { x, y } = options.absolutePointer; - const width = fixedObject.width * fixedObject.scaleX; - const height = fixedObject.height * fixedObject.scaleY; - const X = (x - (fixedObject.left - width / 2)) / fixedObject.scaleX; - const Y = (y - (fixedObject.top - height / 2)) / fixedObject.scaleY; - return { - x: Math.round(X), - y: Math.round(Y), - } - } - /** 获取分隔后图片 */ async getSegAnythingImage(obj) { setTimeout(() => { @@ -378,6 +346,85 @@ export class PartManager { }); }); } + /** 处理鼠标点位 */ + handleMousePosition(options, fixedObject) { + const pos = options.absolutePointer; + const { x, y } = options.absolutePointer; + const width = fixedObject.width * fixedObject.scaleX; + const height = fixedObject.height * fixedObject.scaleY; + const X = (x - (fixedObject.left - width / 2)) / fixedObject.scaleX; + const Y = (y - (fixedObject.top - height / 2)) / fixedObject.scaleY; + return { + x: Math.round(X), + y: Math.round(Y), + } + } + + async addPartImage(fabricImage) { + const scaleX = fabricImage.scaleX / this.partGroup.scaleX; + const scaleY = fabricImage.scaleY / this.partGroup.scaleY; + const top = (fabricImage.top - this.partGroup.top) / this.partGroup.scaleY; + const left = (fabricImage.left - this.partGroup.left) / this.partGroup.scaleX; + fabricImage.set({ + scaleX, + scaleY, + top: top + this.partGroup.height / 2, + left: left + this.partGroup.width / 2, + }) + this.drawList.push(fabricImage); + const tcanvas = new fabric.StaticCanvas(document.createElement("canvas"), { + width: this.partGroup.width, + height: this.partGroup.height, + enableRetinaScaling: false, + }); + this.drawList.forEach(item => tcanvas.add(item)) + tcanvas.renderAll(); + const canvas = getObjectAlphaToCanvas(tcanvas, null, 0, this.rgba); + this.partCanvas = canvas; + const image = new fabric.Image(canvas); + image.set({ + originX: this.partGroup.originX, + originY: this.partGroup.originY, + erasable: true, + }); + this.resetPartObject(); + this.partGroup.add(image); + this.canvas.renderAll(); + } + + + /** 绘制工具模式下点击事件处理 */ + _brushDownHandler(options) { + } + /** 绘制工具模式下移动事件处理 */ + _brushMoveHandler(options) { + + } + /** 绘制工具模式下抬起事件处理 */ + _brushUpHandler(options) { + } + + + /** 切换到擦除工具 */ + setEraserTool() { + if (!this.canvas) return console.warn("未找到画布"); + const objects = this.canvas.getObjects(); + objects.forEach(obj => { + obj.set({ + erasable: true + }) + }) + } + /** 擦除工具模式下抬起事件处理 */ + _eraseUpHandler(options) { + } + /** 擦除工具模式下点击事件处理 */ + _eraseDownHandler(options) { + } + /** 擦除工具模式下移动事件处理 */ + _eraseMoveHandler(options) { + + } /** 删除指定ID的对象 */ removeObjectsById(id) { @@ -415,6 +462,7 @@ export class PartManager { originY: fixedObject.originY, selectable: false, evented: false, + erasable: false, }) this.canvas.add(group); this.partGroup = group; diff --git a/src/component/Canvas/CanvasEditor/managers/ToolManager.js b/src/component/Canvas/CanvasEditor/managers/ToolManager.js index 69a6dd95..ee5d5759 100644 --- a/src/component/Canvas/CanvasEditor/managers/ToolManager.js +++ b/src/component/Canvas/CanvasEditor/managers/ToolManager.js @@ -736,15 +736,40 @@ export class ToolManager { if (!isExecute && this.canvasManager && this.canvasManager.partManager) { this.canvasManager.partManager.setCurrentTool(OperationType.PART_BRUSH); } + const greenColor = "#0f0"; + // 确保有笔刷管理器 + if (this.brushManager) { + // 设置绿色笔刷 + this.brushManager.setBrushColor(greenColor); // 纯绿色 + this.brushManager.setBrushOpacity(200/255); // 完全不透明 + this.brushManager.setBrushType("pencil"); // 铅笔类型 + + // 更新笔刷大小(使用当前大小) + if (BrushStore && BrushStore.state.size) { + this.brushManager.setBrushSize(BrushStore.state.size); + } + + // 更新应用到画布 + this.brushManager.updateBrush(); + } + + // 启用笔刷指示器并设置绿色 + this._enableBrushIndicator(greenColor); } /** * 设置部件选取工具--橡皮擦 */ setupPartEraserTool(isExecute = false) { if (!this.canvas) return; - this.canvas.isDrawingMode = false; + this.canvas.isDrawingMode = true; this.canvas.selection = false; - if (!isExecute && this.canvasManager && this.canvasManager.partManager) { + if (this.brushManager) { + this.brushManager.createEraser(); + } + // 启用笔刷指示器 + this._enableBrushIndicator(); + + if (!isExecute && this.canvasManager && this.canvasManager.partManager) { this.canvasManager.partManager.setCurrentTool(OperationType.PART_ERASER); } } @@ -1602,7 +1627,9 @@ export class ToolManager { OperationType.ERASER, OperationType.RED_BRUSH, OperationType.GREEN_BRUSH, - OperationType.LIQUIFY, + OperationType.LIQUIFY, + OperationType.PART_BRUSH, + OperationType.PART_ERASER, ]; return brushTools.includes(currentTool); diff --git a/src/component/Canvas/CanvasEditor/utils/objectHelper.js b/src/component/Canvas/CanvasEditor/utils/objectHelper.js index 8cf3b7ed..d52d02fc 100644 --- a/src/component/Canvas/CanvasEditor/utils/objectHelper.js +++ b/src/component/Canvas/CanvasEditor/utils/objectHelper.js @@ -69,6 +69,10 @@ export async function restoreFabricObject(serializedObject, canvas) { */ export function getObjectAlphaToCanvas(object, revData, diff = 30, rgba = { r: 255, g: 255, b: 255, a: 255 }) { const image = object.getElement(); + if (image.nodeName !== "IMG" && image.nodeName !== "CANVAS") { + console.warn("对象不是图片"); + return null; + } const { width, height } = image; if (!width || !height) { console.warn("对象没有元素"); diff --git a/src/component/Canvas/canvasExample.vue b/src/component/Canvas/canvasExample.vue index ce160580..ce7f0a2f 100644 --- a/src/component/Canvas/canvasExample.vue +++ b/src/component/Canvas/canvasExample.vue @@ -417,7 +417,6 @@ }" @change-canvas="changeCanvas" @canvas-init="canvasInit" - isFixedErasable showFixedLayer >