瀏覽代碼

Merge remote-tracking branch 'origin/feature-frontend' into feature-frontend

# Conflicts:
#	frontend/src/views/components/marketingEdit/index.vue
#	frontend/src/views/components/marketingEdit/tpl/header.js
#	frontend/src/views/components/marketingEdit/tpl/view.js
panqiuyao 1 周之前
父節點
當前提交
26329644ee
共有 2 個文件被更改,包括 39 次插入10 次删除
  1. 2 2
      frontend/src/views/Home/index.vue
  2. 37 8
      frontend/src/views/components/PictureEditor/mixin/edit/index.js

+ 2 - 2
frontend/src/views/Home/index.vue

@@ -14,7 +14,7 @@
     <!-- 左侧图片区域 -->
     <div class="image-container left-image" @click="goCheck" v-log="{ describe: { action: '点击拍照检查入口' } }">
       <img src="@/assets/images/home/left.png" alt="拍摄产品并处理图像" class="zoom-on-hover" />
-      <div class="overlay-text">新加模板</div>
+      <div class="overlay-text">模板列表</div>
     </div>
 
     <!-- 右侧图片区域 -->
@@ -75,7 +75,7 @@ function socketConnect(){
 
 const goCheck = async () => {
   router.push({
-    name: 'addTpl'
+    name: 'tpl'
   });
 };
 

+ 37 - 8
frontend/src/views/components/PictureEditor/mixin/edit/index.js

@@ -143,7 +143,10 @@ export default  {
           if (this.editLayer.strokeObj) {
             this.fcanvas.add(markRaw(this.editLayer.strokeObj));
           }
-          this.updateClipPreview && this.updateClipPreview()
+          // 延迟调用 updateClipPreview,确保对象已完全加载
+          this.$nextTick(() => {
+            this.updateClipPreview && this.updateClipPreview()
+          })
           break;
       }
     },
@@ -457,7 +460,23 @@ export default  {
     updateClipPreview(force=false){
       if(!this.editLayer || this.editLayer.type !== 'image') return
       const obj = this.editLayer
+      
+      // 检查对象是否已完全加载(对于图片对象)
+      if (obj.type === 'image' && obj._element && !obj._element.complete) {
+        // 如果图片还在加载中,等待加载完成后再执行
+        const onLoad = () => {
+          obj.off('loaded', onLoad)
+          this.updateClipPreview(force)
+        }
+        obj.on('loaded', onLoad)
+        return
+      }
+      
       const bounds = obj.getBoundingRect(true)
+      if (!bounds || bounds.width <= 0 || bounds.height <= 0) {
+        return // 无效的边界,跳过预览
+      }
+      
       this.clipPreview = {
         ...this.clipPreview,
         maxOffsetX: Math.max(0, Math.floor(bounds.width)),
@@ -468,13 +487,23 @@ 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 时是异步的,需要使用回调
+          obj.clone((cloned) => {
+            if (!cloned) {
+              console.warn('clip preview: clone failed')
+              return
+            }
+            try {
+              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 render failed', e)
+            }
+          })
         }catch(e){
           console.warn('clip preview failed', e)
         }