浏览代码

feat(marketingEdit): 更新画布预览图片并优化滚动定位逻辑

- 更新了两个画布模板的 preview 图片链接
- 修改了 canvas_json 中文本框的字体和对齐方式
- 新增 scrollToCanvas 方法实现画布间平滑滚动定位
- 调整画布容器样式,将 overflow 设置为 visible
- 优化 canvas-switch 按钮位置和样式表现
- 在新增画布后触发滚动到当前画布的逻辑
- 为画布元素添加 ref 引用以支持精确定位
panqiuyao 6 天之前
父节点
当前提交
e23e3033ee

文件差异内容过多而无法显示
+ 1 - 1
frontend/src/views/components/marketingEdit/canvas.json


+ 64 - 6
frontend/src/views/components/marketingEdit/index.vue

@@ -94,6 +94,7 @@ export default {
       this.destroyCanvasInstance()
       this.$nextTick(() => {
         this.init()
+        this.scrollToCanvas(newValue)
       })
     }
   },
@@ -268,6 +269,8 @@ export default {
         if(nextIndex === this.index){
           this.$nextTick(() => {
             this.init()
+            // 新增画布后也需要滚动
+            this.scrollToCanvas(nextIndex)
           })
         }
 /*        this.index = this.data.length - 1*/
@@ -382,6 +385,54 @@ export default {
       }
       this.$message.success('画布已删除')
     },
+    scrollToCanvas(idx){
+      // 使用重试机制,确保 DOM 已渲染
+      const tryScroll = (attempt = 0) => {
+        if (attempt > 10) return // 最多重试10次
+
+        // 增加延迟,确保 DOM 完全渲染
+        setTimeout(() => {
+          this.$nextTick(() => {
+            // 获取滚动容器
+            const scrollContainer = this.$refs.wrap
+            if (!scrollContainer) {
+              if (attempt < 10) {
+                setTimeout(() => tryScroll(attempt + 1), 100 * (attempt + 1))
+              }
+              return
+            }
+
+            const ref = this.$refs[`canvasItem-${idx}`]
+            const el = Array.isArray(ref) ? ref[0] : ref
+            const target = el || document.getElementById(`marketing-canvas-${idx}`)?.closest('.canvas-stack_item')
+
+            if (target && scrollContainer) {
+              // 计算目标元素相对于滚动容器的位置
+              const containerRect = scrollContainer.getBoundingClientRect()
+              const targetRect = target.getBoundingClientRect()
+              
+              // 计算需要滚动的距离(目标元素顶部 - 容器顶部 - 导航栏高度100px)
+              const scrollTop = scrollContainer.scrollTop
+              const targetPosition = scrollTop + (targetRect.top - containerRect.top) - 100
+
+              // 在滚动容器上平滑滚动
+              scrollContainer.scrollTo({
+                top: Math.max(0, targetPosition), // 确保不为负数
+                behavior: 'smooth'
+              })
+            } else if (attempt < 10) {
+              // 如果元素还没准备好,延迟重试
+              setTimeout(() => tryScroll(attempt + 1), 100 * (attempt + 1))
+            }
+          })
+        }, attempt * 50) // 每次尝试增加延迟
+      }
+
+      // 使用 requestAnimationFrame 确保在下一帧执行
+      requestAnimationFrame(() => {
+        tryScroll(0)
+      })
+    },
     canvasBodyStyle(item){
       const height = Number(item?.height)
       const width = Number(item?.width) || FIXED_CANVAS_WIDTH
@@ -619,7 +670,7 @@ export default {
   padding: 0;
   box-sizing: border-box;
   position: relative;
-  overflow: hidden;
+  overflow: visible;
   transition: background 0.2s, box-shadow 0.2s, border 0.2s;
   &.inactive {
     ::v-deep {
@@ -654,12 +705,19 @@ export default {
 
 .canvas-stack_switch {
   position: absolute;
-  top: 12px;
-  right: 12px;
-  background: rgba($primary1, 0.1);
-  border-color: rgba($primary1, 0.3);
-  color: $primary1;
+  top: 0px;
+  right: -25px;
+  width: 25px;
+  height: 60px;
+  background: rgba(104, 188, 165, 0.1);
+  border-color: rgba(104, 188, 165, 0.3);
+  color: #68BCA5;
   z-index: 10;
+  display: block;
+  padding: 0px;
+  white-space: break-spaces;
+  border-top-left-radius: 0px;
+  border-bottom-left-radius: 0px;
 }
 
 .canvas-stack_body.active .canvas-stack_switch {

+ 1 - 0
frontend/src/views/components/marketingEdit/tpl/view.js

@@ -10,6 +10,7 @@ export default function() {
           class="canvas-stack_item"
           v-for="(item, idx) in data"
           :key="(item.id || item.tpl_url || idx) + '-' + idx"
+          :ref="'canvasItem-' + idx"
           :style="{backgroundColor: item.bg_color || '#fff'}"
         >
           <div

部分文件因为文件数量过多而无法显示