Преглед на файлове

feat(picture-editor): 添加文字内容同步功能

- 在syncObjectDataToPanel方法中添加文字内容同步逻辑
- 添加text:changed和editing:exited事件监听
- 创建reactiveTextContent响应式状态解决markRaw后的响应式问题
- 在切换编辑图层时同步文字内容到响应式状态
- 将文本框的v-model绑定从editLayer.text改为reactiveTextContent
- 修复右侧面板文字内容显示问题
- 调整CSS样式以支持动态文字内容宽度
panqiuyao преди 6 дни
родител
ревизия
c76a371527

+ 23 - 2
frontend/src/views/components/PictureEditor/mixin/actions/index.js

@@ -373,19 +373,38 @@ export default  {
 
     // 同步对象数据到右侧面板
     syncObjectDataToPanel(obj) {
-      if (!obj || !this.editLayer || obj.id !== this.editLayer.id) {
+      if (!obj) {
         return;
       }
 
       // 同步图片尺寸
       if (obj.type === 'image') {
-        if (this.imageSize) {
+        if (this.imageSize && this.editLayer && obj.id === this.editLayer.id) {
           this.imageSize.width = Math.round(obj.getScaledWidth());
           this.imageSize.height = Math.round(obj.getScaledHeight());
           // 强制更新Vue组件以反映数据变化
           this.$forceUpdate();
         }
       }
+      // 同步文字内容
+      else if (obj.type === 'textbox' || obj.type === 'text') {
+        // 同步文字内容到右侧面板
+        if (obj.text !== undefined) {
+          console.log('文字同步:', {
+            objId: obj.id,
+            oldText: this.reactiveTextContent,
+            newText: obj.text
+          });
+
+          // 更新响应式文字内容状态
+          this.reactiveTextContent = obj.text;
+
+          // 同时更新fabric对象的文字内容
+          if (this.editLayer) {
+            this.editLayer.text = obj.text;
+          }
+        }
+      }
     },
     async setCursor(){
       if(!['draw','erase'].includes(this.action))  return
@@ -761,6 +780,8 @@ export default  {
       const coreEvents = [
         "object:modified",    // 对象修改(移动、缩放、旋转等)
         "path:created",       // 绘制路径
+        "text:changed",       // 文字内容变化
+        "editing:exited",     // 文字编辑结束
       ];
 
       coreEvents.forEach(eventName => {

+ 9 - 1
frontend/src/views/components/PictureEditor/mixin/edit/index.js

@@ -65,7 +65,9 @@ export default  {
         keepRatio: true,
         originalRatio: 1, // 原始宽高比
         lastAdjusted: 'width' // 最后调整的维度 ('width' 或 'height')
-      }
+      },
+      // 响应式的文字内容状态(用于解决markRaw后的响应式问题)
+      reactiveTextContent: ''
     }
   },
   props: {
@@ -120,6 +122,9 @@ export default  {
         fill: this.editLayer?.fill ?? '#000000',
         textAlign: this.editLayer?.textAlign ?? 'left',
       }
+
+      // 同步响应式文字内容状态
+      this.reactiveTextContent = this.editLayer?.text ?? '';
       switch (this.editLayer.type){
         case "textbox":
           if(this.editLayer.shadow){
@@ -215,6 +220,9 @@ export default  {
         textAlign: this.editLayer?.textAlign ?? 'left',
       }
 
+      // 同步响应式文字内容状态
+      this.reactiveTextContent = this.editLayer?.text ?? '';
+
       // 更新图片尺寸显示
       if (this.editLayer && this.editLayer.type === 'image') {
         const originalWidth = this.editLayer.width || 100;

+ 1 - 1
frontend/src/views/components/PictureEditor/mixin/edit/module/textbox.js

@@ -17,7 +17,7 @@ const textbox = () => {
             <div class="title_two">文字内容</div>
             <el-input
               type="textarea"
-              :model-value="editLayer.text"
+              v-model="reactiveTextContent"
               @input="(val) => setLayerAttr('text', val)"
              :autosize="{ minRows: 2, maxRows: 8}"
               placeholder="请输入文字内容"

+ 1 - 2
frontend/src/views/components/marketingEdit/index.vue

@@ -1437,8 +1437,7 @@ export default {
   color: #666;
   white-space: nowrap;
   margin-right: 4px;
-  width: 50px;
-  text-align: right;
+  min-width: 50px;
 }
 
 .unit-text {