From fa4e0b0f1a4a6d26fccf92f13a48a298639ce2cc Mon Sep 17 00:00:00 2001 From: X1627315083 <1627315083@qq.com> Date: Wed, 24 Sep 2025 17:58:40 +0800 Subject: [PATCH 1/5] fix --- src/component/Detail/model/modelNav.vue | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/component/Detail/model/modelNav.vue b/src/component/Detail/model/modelNav.vue index 15a611bd..a1076188 100644 --- a/src/component/Detail/model/modelNav.vue +++ b/src/component/Detail/model/modelNav.vue @@ -95,7 +95,9 @@ export default defineComponent({ }); }else{ resolve(true) - emit('canvasReload') + if(detailData.selectDetail.id !== item.id){ + emit('canvasReload') + } } }).then((rv)=>{ if(rv)store.commit('DesignDetail/setDesignColthes',item.id) From 9ac3152b6c65d75b533375dc24d94d1145c556e2 Mon Sep 17 00:00:00 2001 From: X1627315083 <1627315083@qq.com> Date: Wed, 24 Sep 2025 18:00:26 +0800 Subject: [PATCH 2/5] fix --- src/views/HomeMain.vue | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/views/HomeMain.vue b/src/views/HomeMain.vue index 7395fc87..3588b64a 100644 --- a/src/views/HomeMain.vue +++ b/src/views/HomeMain.vue @@ -398,10 +398,10 @@ export default defineComponent({ homeMainData.openType = Object.keys(query)[0] homeMainData.openTypeChild = query[Object.keys(query)[0]] } - // if((query?.id || query?.history) && !await getIdExistToHistory()){ - // router.push('/home') - // return - // } + if((query?.id || query?.history) && !await getIdExistToHistory()){ + router.push('/home') + return + } }else{ homeMainData.openType = '' homeMainData.openTypeChild = '' From 564b75de61c6e5e4e662b48deeac4395bf1dd3dc 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, 25 Sep 2025 13:52:05 +0800 Subject: [PATCH 3/5] =?UTF-8?q?=E8=A7=A3=E5=86=B3=E7=94=BB=E5=B8=83?= =?UTF-8?q?=E6=89=93=E5=BC=80=E5=9B=BE=E7=89=87=E5=AF=BC=E5=87=BA=E5=9B=BE?= =?UTF-8?q?=E7=89=87=E5=88=86=E8=BE=A8=E7=8E=87=E4=B8=8D=E4=B8=80=E5=80=BC?= =?UTF-8?q?=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components.d.ts | 12 ----- src/component/Canvas/CanvasEditor/index.vue | 22 +++++++++ .../CanvasEditor/managers/CanvasManager.js | 1 + .../CanvasEditor/managers/ExportManager.js | 49 +++++++++++++++---- .../CanvasEditor/utils/selectionToImage.js | 16 +++++- .../tools/deReconstruction/canvas/index.vue | 16 +++--- src/component/modules/generalMiniCanvas.vue | 18 ++++--- 7 files changed, 98 insertions(+), 36 deletions(-) diff --git a/components.d.ts b/components.d.ts index 1c57248a..b2d38451 100644 --- a/components.d.ts +++ b/components.d.ts @@ -9,31 +9,19 @@ export {} declare module 'vue' { export interface GlobalComponents { ABadge: typeof import('ant-design-vue/es')['Badge'] - ABreadcrumb: typeof import('ant-design-vue/es')['Breadcrumb'] ACheckbox: typeof import('ant-design-vue/es')['Checkbox'] - ADatePicker: typeof import('ant-design-vue/es')['DatePicker'] ADrawer: typeof import('ant-design-vue/es')['Drawer'] - AImage: typeof import('ant-design-vue/es')['Image'] AInputNumber: typeof import('ant-design-vue/es')['InputNumber'] - AMenu: typeof import('ant-design-vue/es')['Menu'] - AMenuItem: typeof import('ant-design-vue/es')['MenuItem'] AModal: typeof import('ant-design-vue/es')['Modal'] - APagination: typeof import('ant-design-vue/es')['Pagination'] APopover: typeof import('ant-design-vue/es')['Popover'] ARangePicker: typeof import('ant-design-vue/es')['RangePicker'] ASelect: typeof import('ant-design-vue/es')['Select'] ASelectOption: typeof import('ant-design-vue/es')['SelectOption'] ASlider: typeof import('ant-design-vue/es')['Slider'] - ASpace: typeof import('ant-design-vue/es')['Space'] ASpin: typeof import('ant-design-vue/es')['Spin'] - ASubMenu: typeof import('ant-design-vue/es')['SubMenu'] ASwitch: typeof import('ant-design-vue/es')['Switch'] ATable: typeof import('ant-design-vue/es')['Table'] - ATabPane: typeof import('ant-design-vue/es')['TabPane'] - ATabs: typeof import('ant-design-vue/es')['Tabs'] - ATimeRangePicker: typeof import('ant-design-vue/es')['TimeRangePicker'] AUpload: typeof import('ant-design-vue/es')['Upload'] - ElCascader: typeof import('element-plus/es')['ElCascader'] RouterLink: typeof import('vue-router')['RouterLink'] RouterView: typeof import('vue-router')['RouterView'] } diff --git a/src/component/Canvas/CanvasEditor/index.vue b/src/component/Canvas/CanvasEditor/index.vue index 7247885a..0e4b7844 100644 --- a/src/component/Canvas/CanvasEditor/index.vue +++ b/src/component/Canvas/CanvasEditor/index.vue @@ -456,6 +456,13 @@ onMounted(async () => { // 使用window的resize事件代替ResizeObserver // 只有当窗口大小变化时才更新画布尺寸 // window.addEventListener("resize", handleWindowResize); + if(props.config.initZoom) { + const width = canvasManager.width; + const height = canvasManager.height; + const cwidth = props.config.width; + const cheight = props.config.height; + setZoom(Math.min(width/cwidth,height/cheight)); // 设置画布缩放 + } }); watchEffect(() => { @@ -521,6 +528,19 @@ function resetZoom() { canvasManager.resetZoom(); } +function setZoom(zoom) { + setTimeout(()=>{ + if (!canvasManager) return; + const newZoom = Math.max(zoom / 1.1, 0.1); // 减少10%,最小0.1倍 + // 使用画布中心作为缩放点 + const centerPoint = { + x: canvasManager.canvas.width / 2, + y: canvasManager.canvas.height / 2, + }; + canvasManager.animateZoom(centerPoint, newZoom); + }) +} + function zoomIn() { if (!canvasManager) return; @@ -882,6 +902,7 @@ defineExpose({ layerId = "", // 导出具体图层ID layerIdArray = [], // 导出多个图层ID数组 expPicType = "png", // 导出图片类型 JPG 或 PNG ,SVG + isEnhanceImg, // 是否是增强图片 } = {}) => { return canvasManager.exportImage({ isContainBg, @@ -890,6 +911,7 @@ defineExpose({ layerId, layerIdArray, expPicType, + isEnhanceImg, }); }, /** diff --git a/src/component/Canvas/CanvasEditor/managers/CanvasManager.js b/src/component/Canvas/CanvasEditor/managers/CanvasManager.js index 6c4083da..a0abed05 100644 --- a/src/component/Canvas/CanvasEditor/managers/CanvasManager.js +++ b/src/component/Canvas/CanvasEditor/managers/CanvasManager.js @@ -811,6 +811,7 @@ export class CanvasManager { * @param {Array} options.layerIdArray 导出多个图层ID数组 * @param {String} options.expPicType 导出图片类型 (png/jpg/svg) * @param {Boolean} options.restoreOpacityInRedGreen 红绿图模式下是否恢复透明度为1 + * @param {Boolean} options.isEnhanceImg 是否是增强图片 * @returns {String} 导出的图片数据URL */ async exportImage(options = {}) { diff --git a/src/component/Canvas/CanvasEditor/managers/ExportManager.js b/src/component/Canvas/CanvasEditor/managers/ExportManager.js index 41d1007d..0b474d05 100644 --- a/src/component/Canvas/CanvasEditor/managers/ExportManager.js +++ b/src/component/Canvas/CanvasEditor/managers/ExportManager.js @@ -18,10 +18,12 @@ export class ExportManager { * @param {Object} options 导出选项 * @param {Boolean} options.isContainBg 是否包含背景图层 * @param {Boolean} options.isContainFixed 是否包含固定图层 + * @param {Boolean} options.isCropByBg 是否使用背景大小裁剪 * @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 是否是增强图片 * @returns {String} 导出的图片数据URL */ exportImage(options = {}) { @@ -33,6 +35,7 @@ export class ExportManager { layerIdArray = [], expPicType = "png", restoreOpacityInRedGreen = true, + isEnhanceImg, // 是否是增强图片 } = options; try { // 检查是否为红绿图模式 @@ -44,7 +47,8 @@ export class ExportManager { expPicType, isRedGreenMode, restoreOpacityInRedGreen, - isCropByBg + isCropByBg, + isEnhanceImg, // 是否是增强图片 ); } @@ -57,7 +61,8 @@ export class ExportManager { isContainFixed, isRedGreenMode, restoreOpacityInRedGreen, - isCropByBg + isCropByBg, + isEnhanceImg, // 是否是增强图片 ); } @@ -68,7 +73,8 @@ export class ExportManager { isContainFixed, isRedGreenMode, restoreOpacityInRedGreen, - isCropByBg + isCropByBg, + isEnhanceImg, // 是否是增强图片 ); } catch (error) { console.error("导出图片失败:", error); @@ -82,6 +88,8 @@ export class ExportManager { * @param {String} expPicType 导出类型 * @param {Boolean} isRedGreenMode 是否为红绿图模式 * @param {Boolean} restoreOpacityInRedGreen 红绿图模式下是否恢复透明度为1 + * @param {Boolean} isCropByBg 是否使用背景大小裁剪 + * @param {Boolean} isEnhanceImg 是否是增强图片 * @returns {String} 图片数据URL * @private */ @@ -89,7 +97,9 @@ export class ExportManager { layerId, expPicType, isRedGreenMode, - restoreOpacityInRedGreen + restoreOpacityInRedGreen, + isCropByBg, // 是否使用背景大小裁剪 + isEnhanceImg, // 是否是增强图片 ) { if (!this.layerManager) { throw new Error("图层管理器未初始化"); @@ -117,7 +127,9 @@ export class ExportManager { return this._exportWithRedGreenMode( objectsToExport, expPicType, - restoreOpacityInRedGreen + restoreOpacityInRedGreen, + isCropByBg, // 是否使用背景大小裁剪 + isEnhanceImg, // 是否是增强图片 ); } @@ -137,6 +149,8 @@ export class ExportManager { * @param {Boolean} isContainFixed 是否包含固定图层 * @param {Boolean} isRedGreenMode 是否为红绿图模式 * @param {Boolean} restoreOpacityInRedGreen 红绿图模式下是否恢复透明度为1 + * @param {Boolean} isCropByBg 是否使用背景大小裁剪 + * @param {Boolean} isEnhanceImg 是否是增强图片 * @returns {String} 图片数据URL * @private */ @@ -147,7 +161,8 @@ export class ExportManager { isContainFixed, isRedGreenMode, restoreOpacityInRedGreen, - isCropByBg + isCropByBg, // 是否使用背景大小裁剪 + isEnhanceImg, // 是否是增强图片 ) { if (!this.layerManager) { throw new Error("图层管理器未初始化"); @@ -178,7 +193,9 @@ export class ExportManager { return await this._exportWithCanvasSize( objectsToExport, expPicType, - restoreOpacityInRedGreen + restoreOpacityInRedGreen, + isCropByBg, // 是否使用背景大小裁剪 + isEnhanceImg, // 是否是增强图片 ); } @@ -189,6 +206,8 @@ export class ExportManager { * @param {Boolean} isContainFixed 是否包含固定图层 * @param {Boolean} isRedGreenMode 是否为红绿图模式 * @param {Boolean} restoreOpacityInRedGreen 红绿图模式下是否恢复透明度为1 + * @param {Boolean} isCropByBg 是否使用背景大小裁剪 + * @param {Boolean} isEnhanceImg 是否是增强图片 * @returns {String} 图片数据URL * @private */ @@ -198,7 +217,8 @@ export class ExportManager { isContainFixed, isRedGreenMode, restoreOpacityInRedGreen, - isCropByBg + isCropByBg, // 是否使用背景大小裁剪 + isEnhanceImg, // 是否是增强图片 ) { // 按图层顺序收集对象(从底到顶) const objectsToExport = this._collectObjectsByLayerOrder( @@ -251,7 +271,9 @@ export class ExportManager { objectsToExport, expPicType, restoreOpacityInRedGreen, - canvasClipPath + canvasClipPath, + isCropByBg, // 是否使用背景大小裁剪 + isEnhanceImg, // 是否是增强图片 ); } @@ -603,6 +625,9 @@ export class ExportManager { * @param {Array} objectsToExport 要导出的对象数组 * @param {String} expPicType 导出类型 * @param {Boolean} restoreOpacityInRedGreen 是否恢复透明度为1 + * @param {Object} maskObject 裁剪对象 + * @param {Boolean} isCropByBg 是否使用背景大小裁剪 + * @param {Boolean} isEnhanceImg 是否是增强图片 * @returns {String} 图片数据URL * @private */ @@ -610,7 +635,9 @@ export class ExportManager { objectsToExport, expPicType, restoreOpacityInRedGreen, - maskObject + maskObject, // 裁剪对象 + isCropByBg, // 是否使用背景大小裁剪 + isEnhanceImg, // 是否是增强图片 ) { // 使用当前画布尺寸 // const canvasWidth = @@ -629,6 +656,8 @@ export class ExportManager { trimWhitespace: true, // 裁剪空白 trimPadding: 0, // 裁剪边距 restoreOpacityInRedGreen, + isCropByBg, // 是否使用背景大小裁剪 + isEnhanceImg, // 是否是增强图片 }); console.log("导出图片数据URL:", dataURL); diff --git a/src/component/Canvas/CanvasEditor/utils/selectionToImage.js b/src/component/Canvas/CanvasEditor/utils/selectionToImage.js index 848f6916..2f518624 100644 --- a/src/component/Canvas/CanvasEditor/utils/selectionToImage.js +++ b/src/component/Canvas/CanvasEditor/utils/selectionToImage.js @@ -21,6 +21,7 @@ export const createRasterizedImage = async ({ preserveOriginalQuality = true, // 是否保持原始质量(新增) selectionManager = null, // 选区管理器,用于获取羽化值等设置 restoreOpacityInRedGreen, // 是否在红绿图模式下恢复透明度 + isEnhanceImg, // 是否是增强图片 } = {}) => { try { console.log(`📊 开始栅格化 ${fabricObjects.length} 个对象`); @@ -41,6 +42,7 @@ export const createRasterizedImage = async ({ clippingObject, isReturenDataURL, selectionManager, // 传递选区管理器 + isEnhanceImg, // 是否是增强图片 }); } @@ -81,6 +83,7 @@ const createClippedObjects = async ({ clippingObject, isReturenDataURL, selectionManager = null, // 新增选区管理器参数 + isEnhanceImg, // 是否是增强图片 }) => { try { console.log("🎯 使用新的图像遮罩裁剪方法创建对象"); @@ -110,6 +113,7 @@ const createClippedObjects = async ({ clippingObject, selectionBounds: optimizedBounds, // 使用优化后的边界框 featherAmount, + isEnhanceImg, // 是否是增强图片 }); } @@ -120,6 +124,7 @@ const createClippedObjects = async ({ clippingObject, selectionBounds: optimizedBounds, // 使用优化后的边界框 featherAmount, + isEnhanceImg, // 是否是增强图片 }); // 将DataURL转换为fabric.Image对象 @@ -173,6 +178,7 @@ const createClippedDataURLByCanvas = async ({ clippingObject, selectionBounds, featherAmount = 0, + isEnhanceImg = false, // 是否是增强图片 }) => { try { console.log("🖼️ 使用图像遮罩裁剪方法生成DataURL"); @@ -185,7 +191,9 @@ const createClippedDataURLByCanvas = async ({ // 使用高分辨率以保证质量 const pixelRatio = window.devicePixelRatio || 1; - const qualityMultiplier = Math.max(2, pixelRatio); + const qualityMultiplier = !!isEnhanceImg ? Math.max(2, pixelRatio) : 1; + + console.log("使用高分辨率以保证质量:" + isEnhanceImg, optimizedBounds); const canvasWidth = Math.ceil(optimizedBounds.width * qualityMultiplier); const canvasHeight = Math.ceil(optimizedBounds.height * qualityMultiplier); @@ -455,6 +463,8 @@ const createLegacyRasterization = async ({ quality, format, isReturenDataURL, + isCropByBg, // 是否根据背景裁剪 + isEnhanceImg, // 是否是增强图片 }) => { console.log("⚠️ 使用兼容的离屏渲染方法"); @@ -481,6 +491,8 @@ const createLegacyRasterization = async ({ format, currentZoom, isReturenDataURL, + isCropByBg, // 是否根据背景裁剪 + isEnhanceImg, // 是否是增强图片 }); }; @@ -571,6 +583,8 @@ const createOffscreenRasterization = async ({ format, currentZoom, isReturenDataURL, + isCropByBg, // 是否根据背景裁剪 + isEnhanceImg, // 是否是增强图片 }) => { try { // 创建离屏画布,使用绝对尺寸以保证高质量 diff --git a/src/component/home/tools/deReconstruction/canvas/index.vue b/src/component/home/tools/deReconstruction/canvas/index.vue index 0c6b8277..3e6ef56c 100644 --- a/src/component/home/tools/deReconstruction/canvas/index.vue +++ b/src/component/home/tools/deReconstruction/canvas/index.vue @@ -113,12 +113,16 @@ export default defineComponent({ return new Promise((res,rev)=>{ let img = new Image() img.onload = ()=>{ - let wH = [1,1] - let domHeight = dataDom.canvasBox.offsetHeight - 200 - let imgHeight = img.height - wH = [1,domHeight/imgHeight] - data.canvasConfig.width = img.width * wH[1] - data.canvasConfig.height = domHeight + // let wH = [1,1] + // let domHeight = dataDom.canvasBox.offsetHeight - 200 + // let imgHeight = img.height + // wH = [1,domHeight/imgHeight] + // data.canvasConfig.width = img.width * wH[1] + // data.canvasConfig.height = domHeight + data.canvasConfig.height = img.height + data.canvasConfig.width = img.width + data.canvasConfig.initZoom = true + data.canvasLoad = true res('') } diff --git a/src/component/modules/generalMiniCanvas.vue b/src/component/modules/generalMiniCanvas.vue index e9463578..eaf2be3d 100644 --- a/src/component/modules/generalMiniCanvas.vue +++ b/src/component/modules/generalMiniCanvas.vue @@ -87,7 +87,7 @@ export default defineComponent({ // dataDom.editCanvas.exportImage({isContainBg:props.source == 'detail',isContainFixed:true}).then((rv)=>{ // emit('submitBase64Data',rv) // }) - dataDom.editCanvas.exportImage({isContainBg:true,isContainFixed:true}).then((rv)=>{ + dataDom.editCanvas.exportImage({isContainBg:true,isContainFixed:true,isCropByBg:true}).then((rv)=>{ emit('submitBase64Data',rv) }) } @@ -135,12 +135,16 @@ export default defineComponent({ if(props.imgUrl){ let img = new Image() img.onload = ()=>{ - let wH = [1,1] - let domHeight = dataDom.canvasBox.offsetHeight - 200 - let imgHeight = img.height - wH = [1,domHeight/imgHeight] - data.canvasConfig.height = domHeight - data.canvasConfig.width = wH[1] * img.width + // let wH = [1,1] + // let domHeight = dataDom.canvasBox.offsetHeight - 200 + // let imgHeight = img.height + // wH = [1,domHeight/imgHeight] + // data.canvasConfig.height = domHeight + // data.canvasConfig.width = wH[1] * img.width + data.canvasConfig.height = img.height + data.canvasConfig.width = img.width + data.canvasConfig.initZoom = true + data.canvasLoad = true // setTimeout(()=>{ // canvasLoadAddImg() From 6ba33701a570ef3dc25a0621f573d4a01a5a08a5 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, 25 Sep 2025 14:01:49 +0800 Subject: [PATCH 4/5] =?UTF-8?q?=E8=A7=A3=E5=86=B3=E7=94=BB=E5=B8=83?= =?UTF-8?q?=E6=89=93=E5=BC=80=E5=9B=BE=E7=89=87=E5=AF=BC=E5=87=BA=E5=9B=BE?= =?UTF-8?q?=E7=89=87=E5=88=86=E8=BE=A8=E7=8E=87=E4=B8=8D=E5=80=BC=E4=B8=80?= =?UTF-8?q?=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/component/Canvas/CanvasEditor/index.vue | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/component/Canvas/CanvasEditor/index.vue b/src/component/Canvas/CanvasEditor/index.vue index 0e4b7844..aa90942e 100644 --- a/src/component/Canvas/CanvasEditor/index.vue +++ b/src/component/Canvas/CanvasEditor/index.vue @@ -461,7 +461,9 @@ onMounted(async () => { const height = canvasManager.height; const cwidth = props.config.width; const cheight = props.config.height; - setZoom(Math.min(width/cwidth,height/cheight)); // 设置画布缩放 + let zoom = Math.min(1,width/cwidth,height/cheight); + if(zoom < 1) zoom -= 0.05; + setZoom(zoom); // 设置画布缩放 } }); @@ -531,7 +533,7 @@ function resetZoom() { function setZoom(zoom) { setTimeout(()=>{ if (!canvasManager) return; - const newZoom = Math.max(zoom / 1.1, 0.1); // 减少10%,最小0.1倍 + const newZoom = Math.max(zoom, 0.1); // 减少10%,最小0.1倍 // 使用画布中心作为缩放点 const centerPoint = { x: canvasManager.canvas.width / 2, From d50f494b348bed87248e2243f1f58b65635048b8 Mon Sep 17 00:00:00 2001 From: X1627315083 <1627315083@qq.com> Date: Thu, 25 Sep 2025 14:29:23 +0800 Subject: [PATCH 5/5] =?UTF-8?q?=E4=BF=AE=E5=A4=8Ddetail=E6=93=8D=E4=BD=9C?= =?UTF-8?q?=E6=8C=89=E9=92=AE=E9=9B=86=E4=B8=AD=E5=B7=A6=E4=B8=8A=E8=A7=92?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/component/Account/frontPage/bindPage.vue | 4 +- src/component/Detail/DesignDetail.vue | 104 +++++++++--------- src/component/Detail/model/modelPosition.vue | 2 +- .../design/collection/MoodboardUpload.vue | 2 +- .../design/collection/PrintboardUpload.vue | 3 +- src/component/home/design/collection/more.vue | 8 ++ src/component/home/design/index.vue | 7 +- src/store/Detail/designDetail.ts | 15 ++- 8 files changed, 86 insertions(+), 59 deletions(-) diff --git a/src/component/Account/frontPage/bindPage.vue b/src/component/Account/frontPage/bindPage.vue index 61e81949..7ec33f51 100644 --- a/src/component/Account/frontPage/bindPage.vue +++ b/src/component/Account/frontPage/bindPage.vue @@ -28,7 +28,7 @@