Преглед изворни кода

fix(editor): 修复图片编辑器克隆异步问题并优化画布类型处理

- 修复 PictureEditor 中 obj.clone 异步调用导致的错误
- 避免在无普通画布时更新索引以防止递归更新
- 为模特图和场景图类型保留原始 canvas_json 占位符
- 跳过模特图/场景图的 fabric 初始化逻辑
- 保存快照时区分处理不同画布类型的数据结构
- 确保只有正常画布才生成 JSON 和预览数据
panqiuyao пре 5 дана
родитељ
комит
667a6ef2d5

+ 10 - 7
frontend/src/views/components/PictureEditor/mixin/edit/index.js

@@ -468,13 +468,16 @@ export default  {
       }
       if(force || this.clipPreview.dataUrl === ''){
         try{
-          const cloned = obj.clone()
-          const tmp = new fabric.Canvas(document.createElement('canvas'), { width: Math.min(200, bounds.width), height: Math.min(200, bounds.height) })
-          cloned.scaleToWidth(tmp.width)
-          tmp.add(cloned)
-          tmp.renderAll()
-          this.clipPreview.dataUrl = tmp.toDataURL({ format:'png', multiplier:1 })
-          tmp.dispose()
+          // clone 可能是异步的(带 filters 时),使用回调形式避免 callback is not a function
+          obj.clone((cloned)=>{
+            if(!cloned) return
+            const tmp = new fabric.Canvas(document.createElement('canvas'), { width: Math.min(200, bounds.width), height: Math.min(200, bounds.height) })
+            cloned.scaleToWidth(tmp.width)
+            tmp.add(cloned)
+            tmp.renderAll()
+            this.clipPreview.dataUrl = tmp.toDataURL({ format:'png', multiplier:1 })
+            tmp.dispose()
+          })
         }catch(e){
           console.warn('clip preview failed', e)
         }

+ 20 - 3
frontend/src/views/components/marketingEdit/index.vue

@@ -107,7 +107,10 @@ export default {
             }
           }
         }
-        this.$emit('update:index', nextIdx === -1 ? oldValue : nextIdx)
+        // 如果没有可切换的普通画布,保持当前索引,避免递归更新
+        if(nextIdx !== -1 && nextIdx !== newValue){
+          this.$emit('update:index', nextIdx)
+        }
         return
       }
       this.saveCanvasSnapshot(oldValue)
@@ -133,6 +136,7 @@ export default {
       if(this.hasLoadedTpl) return
       const tplData = JSON.parse(JSON.stringify(canvas)).map(item => ({
         canvas_type: item.canvas_type || 'normal',
+        canvas_json: (item.canvas_type === 'model' || item.canvas_type === 'scene') ? (item.canvas_type) : (item.canvas_json || ''),
         ...item,
       }))
       this.data.splice(0, this.data.length, ...tplData)
@@ -196,6 +200,7 @@ export default {
       // 模特图/场景图不初始化 fabric,直接跳过
       const canvasType = this.this_canvas?.canvas_type || 'normal'
       if (canvasType === 'model' || canvasType === 'scene') {
+        // 模特/场景图不需要 fabric,保持占位
         return
       }
 
@@ -291,7 +296,7 @@ export default {
                height:this.canvasForm.height,
                bg_color:this.canvasForm.bg_color,
                canvas_type: this.canvasForm.canvas_type || 'normal',
-               canvas_json:'',
+               canvas_json: (this.canvasForm.canvas_type === 'model' || this.canvasForm.canvas_type === 'scene') ? this.canvasForm.canvas_type : '',
                preview:'',
                multi_goods_mode: this.canvasForm.multi_goods_mode || '',
                max_goods_count: this.canvasForm.multi_goods_mode ? (this.canvasForm.max_goods_count || null) : null,
@@ -556,9 +561,21 @@ export default {
     },
     saveCanvasSnapshot(targetIndex){
       const snapshotIndex = typeof targetIndex === 'number' ? targetIndex : this.index
-      if(!this.fcanvas || snapshotIndex === undefined || snapshotIndex === null) return
+      if(snapshotIndex === undefined || snapshotIndex === null) return
       const canvasData = this.data[snapshotIndex]
       if(!canvasData) return
+
+      // 模特图 / 场景图:不生成 JSON,只保存类型占位,预览留空
+      if(canvasData.canvas_type === 'model' || canvasData.canvas_type === 'scene'){
+        this.data[snapshotIndex] = {
+          ...canvasData,
+          canvas_json: canvasData.canvas_type,
+          preview: ''
+        }
+        return
+      }
+
+      if(!this.fcanvas) return
       const json = JSON.stringify(this.fcanvas.toJSON(['name','sort','mtr','id','selectable','erasable','data-key','data-type','data-value']))
       let preview = canvasData.preview || ''
       try{