Selaa lähdekoodia

style(PictureEditor): 优化图片编辑器界面布局和样式

- 重新组织图片编辑工具的布局结构,添加其他工具分组
- 更新标题样式,调整颜色为 #333 并添加背景和边框
- 缩小图层预览尺寸从 44px 到 28px 并调整间距
- 添加图层一行布局样式和文字编辑面板样式优化
- 重构文字编辑模块界面,添加文字内容输入和分类设置区域
- 限制字体大小选项范围,移除过大的字体尺寸
- 统一工具按钮样式,添加标签文字并调整布局结构
panqiuyao 6 päivää sitten
vanhempi
commit
7e9c16f47c

+ 5 - 3
frontend/src/views/components/PictureEditor/mixin/edit/index.scss

@@ -22,14 +22,16 @@
     padding-left: 10px;
   }
   .title_two {
-    color: #000;
+    color: #333;
     font-size: 15px;
     line-height: 30px;
     height: 30px;
-    margin-top: 10px;
-    padding-left: 10px;
     text-align: left;
     margin-bottom:5px;
+    background: #fafafa;
+    padding-left: 10px;
+    border: 1px solid #eee;
+    border-left: 3px solid #f0f0f0;
   }
 
   .edit-font-size {

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

@@ -1,5 +1,5 @@
 
 import font from './font.json'
-export const fontSize = [12,14,16,18,20,24,30,36,48,60,72,84,96,108,120,140,160,180,200,300,400,500]
+export const fontSize = [12,14,16,18,20,24,30,36,48,60,72,84,96]
 export const fontWeight = ['black','black italic','bold','bold italic','regular','regular italic']
 export const fontFamily = font;

+ 13 - 5
frontend/src/views/components/PictureEditor/mixin/edit/module/image.js

@@ -6,11 +6,19 @@ let image = ()=>{
   return `
       <div class="edit-wrap">
           <div class="title step-label"><span class="step-row_color">编辑内容</span></div>
-          ${tools.flip()}
-          ${tools.size()}
-          ${tools.straw()}
-          ${tools.opacity()}
-          ${tools.cutout()}
+          <div class="pad-10">
+          
+             ${tools.size()}
+              <div class="title_two mar-top-10">其他工具</div>
+                <div>
+                  ${tools.flip()}
+                  ${tools.straw()}
+                  ${tools.opacity()}
+               </div>
+               
+                  ${tools.cutout()}
+          </div>
+          
       </div>
      `
 }

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

@@ -10,99 +10,200 @@ import textalignRight from '@/views/components/PictureEditor/mixin/edit/images/t
 const textbox = () => {
   return `
       <div class="edit-wrap">
-          <div class="title step-label"><span class="step-row_color">编辑内容</span></div>
-          <div class="flex left mar-top-10">
-            字体
-            <el-select
-            v-model="fontFamilyStyle"
-            :clearable="false"
-            style="width: 120px"
-            class="mar-left-10"
-            placeholder="请选择"
-            @change="setFontFamily"
-             >
-              <el-option
-                v-for="item in options"
-                :key="item.name"
-                :label="item.name"
-                :value="item.name">
-                <img :src="item.thumbnail" style="max-width: 80%; height: 32px;">
-              </el-option>
-            </el-select>
+          <div class="title step-label"><span class="step-row_color">文字编辑</span></div>
+           <div class="pad-10">
+          <!-- 文字内容输入 -->
+          <div>
+            <div class="title_two">文字内容</div>
+            <el-input
+              type="textarea"
+              :model-value="editLayer.text"
+              @input="(val) => setLayerAttr('text', val)"
+              :rows="3"
+              placeholder="请输入文字内容"
+              class="mar-top-5"
+              resize="none"
+            />
           </div>
 
+          <!-- 字体设置 -->
+          <div class="mar-top-15">
+            <div class="title_two">字体样式</div>
+            <div class="">
+              <div class="flex left mar-top-10" style="align-items: center; margin-right: 15px;">
+                <span class="label-text">字体:</span>
+                <el-select
+                  v-model="fontFamilyStyle"
+                  :clearable="false"
+                  style="width: 140px"
+                  class="mar-left-5"
+                  placeholder="请选择"
+                  @change="setFontFamily"
+                  size="small"
+                >
+                  <el-option
+                    v-for="item in options"
+                    :key="item.name"
+                    :label="item.name"
+                    :value="item.name">
+                    <img :src="item.thumbnail" style="max-width: 80%; height: 24px;">
+                  </el-option>
+                </el-select>
+              </div>
 
-          <div class="flex left mar-top-10">
-            <div class="edit-font-size flex left position-r" style="margin-right: 10px">
+              <div class="flex left mar-top-10" style="align-items: center;">
+                <span class="label-text">大小:</span>
                 <el-select
-                     :model-value="layerState.fontSize"
-                     @update:model-value="val=>setLayerAttr('fontSize', val)"
-                     :clearable="false"
-                     style="width: 80px"
-                 >
-                     <el-option v-for="item,index in TextboxConfig.fontSize" :key="index" :value="item">{{item}}</el-option>
-                 </el-select>
-                 <div class="bq fs-14 c-999">px</div>
-             </div>
-             <el-color-picker
-               class="mar-left-10"
-               :model-value="layerState.fill"
-               @change="(val)=>setLayerAttr('fill', val)"
-             ></el-color-picker>
+                  :model-value="layerState.fontSize"
+                  @update:model-value="val=>setLayerAttr('fontSize', val)"
+                  :clearable="false"
+                  style="width: 60px"
+                  class="mar-left-5"
+                  size="small"
+                >
+                  <el-option v-for="item,index in TextboxConfig.fontSize" :key="index" :value="item">{{item}}</el-option>
+                </el-select>
+                <span class="mar-left-10 c-999 fs-12">px</span>
+              </div>
+            </div>
           </div>
-          <div class="flex left">
-               <div class="label title_two">行高</div>
-                 <el-input-number
-                 v-model="layerState.lineHeight"
-                  controls-position="right"
-                  :precision="2"
-                  :step="0.01"
-                  class="mar-left-10"
-                  style="width: 100px"
-                   @change="(val)=>setLayerAttr('lineHeight',val)"
-                  :min="0.01"
-                   :max="100"/>
+
+          <!-- 颜色和排版 -->
+          <div class="mar-top-15">
+            <div class="title_two">颜色与排版</div>
+            <div class=" ">
+              <div class="flex left " style="align-items: center; margin-right: 15px;">
+                <span class="label-text">颜色:</span>
+                <el-color-picker
+                  :model-value="layerState.fill"
+                  @change="(val)=>setLayerAttr('fill', val)"
+                  size="small"
+                  class="mar-left-5"
+                />
+              </div>
+
+                <div class="mar-top-10 flex left">
+                  <div class="flex left" >
+                    <span class="label-text">行高:</span>
+                    <el-input-number
+                      v-model="layerState.lineHeight"
+                      controls-position="right"
+                      :precision="2"
+                      :step="0.01"
+                      size="small"
+                      style="width: 100px"
+                      class="mar-left-5"
+                      @change="(val)=>setLayerAttr('lineHeight',val)"
+                      :min="0.01"
+                      :max="10"
+                    />
+                  </div>
+              </div>
+
+                <div class="mar-top-10 flex left">
+    
+                  <div class="flex left" style="align-items: center;">
+                    <span class="label-text">字距:</span>
+                    <el-input-number
+                      v-model="layerState.charSpacing"
+                      style="width: 100px"
+                      class="mar-left-5"
+                      size="small"
+                      controls-position="right"
+                      :precision="1"
+                      :step="1"
+                      @change="(val)=>setLayerAttr('charSpacing',val)"
+                    />
+                  </div>
+              </div>
+            </div>
           </div>
 
-          <div class="flex left">
-               <div class="label title_two">字距</div>
-
-                 <el-input-number
-                 v-model="layerState.charSpacing"
-                  style="width: 100px"
-                  class="mar-left-10"
-                  controls-position="right"
-                  :precision="1"
-                  :step="1"
-                   @change="(val)=>setLayerAttr('charSpacing',val)"/> 
+          <!-- 文字装饰 -->
+          <div class="mar-top-15">
+            <div class="title_two">文字装饰</div>
+            <div class="flex left mar-top-10">
+              <el-button
+                size="small"
+                :type="editLayer.underline ? 'primary' : 'default'"
+                @click="editObj({label:'underline',value:!editLayer.underline})"
+                class="mar-right-5"
+              >
+                <el-tooltip effect="dark" content="下划线" placement="top">
+                  <img src="${underline}" style="height: 10px">
+                </el-tooltip>
+              </el-button>
+
+              <el-button
+                size="small"
+                :type="editLayer.linethrough ? 'primary' : 'default'"
+                @click="editObj({label:'linethrough',value:!editLayer.linethrough})"
+              >
+                <el-tooltip effect="dark" content="删除线" placement="top">
+                  <img src="${linethrough}" style="height: 10px">
+                </el-tooltip>
+              </el-button>
+            </div>
           </div>
 
-          <div class="flex line-20 mar-top-10">
-            <el-button size="small" class="flex-item"  @click="editObj({label:'underline',value:!editLayer.underline})">
-             <el-tooltip   effect="dark" content="下划线" placement="top"><img src="${underline}" style="height: 12px"></el-tooltip>
-            </el-button>
-            <el-button size="small" class="flex-item"  @click="editObj({label:'linethrough',value:!editLayer.linethrough})">
-             <el-tooltip  effect="dark" content="删除线" placement="top"><img src="${linethrough}" style="height: 12px"></el-tooltip>
-            </el-button>
+          <!-- 对齐方式 -->
+          <div class="mar-top-15">
+            <div class="title_two">对齐方式</div>
+            <div class="flex left mar-top-10">
+              <el-button
+                size="small"
+                :type="editLayer.textAlign === 'left' ? 'primary' : 'default'"
+                @click="editObj({label:'textAlign',value:'left'})"
+                class="mar-right-5"
+              >
+                <el-tooltip effect="dark" content="左对齐" placement="top">
+                  <img src="${textalignLeft}" style="height: 12px">
+                </el-tooltip>
+              </el-button>
+
+              <el-button
+                size="small"
+                :type="editLayer.textAlign === 'center' ? 'primary' : 'default'"
+                @click="editObj({label:'textAlign',value:'center'})"
+                class="mar-right-5"
+              >
+                <el-tooltip effect="dark" content="居中对齐" placement="top">
+                  <img src="${textalignCenter}" style="height: 12px">
+                </el-tooltip>
+              </el-button>
+
+              <el-button
+                size="small"
+                :type="editLayer.textAlign === 'right' ? 'primary' : 'default'"
+                @click="editObj({label:'textAlign',value:'right'})"
+                class="mar-right-5"
+              >
+                <el-tooltip effect="dark" content="右对齐" placement="top">
+                  <img src="${textalignRight}" style="height: 12px">
+                </el-tooltip>
+              </el-button>
+
+              <el-button
+                size="small"
+                :type="editLayer.textAlign === 'justify' ? 'primary' : 'default'"
+                @click="editObj({label:'textAlign',value:'justify'})"
+              >
+                <el-tooltip effect="dark" content="两端对齐" placement="top">
+                  <img src="${textalignLR}" style="height: 12px">
+                </el-tooltip>
+              </el-button>
+            </div>
           </div>
-          <div class="title_two">对齐方式</div>
-          <div class="flex left line-20">
-            <el-button size="small" style="padding: 15px 10px !important;" @click="editObj({label:'textAlign',value:'left'})">
-             <el-tooltip  effect="dark" content="左对齐" placement="top"><img src="${textalignLeft}" style="height: 12px"></el-tooltip>
-            </el-button>
-            <el-button size="small" style="padding: 15px 10px !important"   @click="editObj({label:'textAlign',value:'center'})">
-             <el-tooltip  effect="dark" content="居中对齐" placement="top"><img src="${textalignCenter}" style="height: 12px"></el-tooltip>
-            </el-button>
-            <el-button size="small" style="padding: 15px 10px !important"   @click="editObj({label:'textAlign',value:'right'})">
-             <el-tooltip  effect="dark" content="右对齐" placement="top"><img src="${textalignRight}" style="height: 12px"></el-tooltip>
-            </el-button>
-            <el-button size="small" style="padding: 15px 10px !important"   @click="editObj({label:'textAlign',value:'justify'})">
-             <el-tooltip  effect="dark" content="两端对齐" placement="top"><img src="${textalignLR}" style="height: 12px"></el-tooltip>
-            </el-button>
+
+          <!-- 其他工具 -->
+          <div class="mar-top-15">
+            <div class="title_two">其他工具</div>
+            <div>
+              ${tools.flip()}
+              ${tools.straw()}
+              ${tools.opacity()}
+            </div>
           </div>
-          ${tools.flip()}
-          ${tools.straw()}
-          ${tools.opacity()}
 
 <!--
           <div class="title_two">描边</div>
@@ -163,6 +264,7 @@ const textbox = () => {
                     </div>
                  </div>
           </div>-->
+          </div>
       </div>
      `
 }

+ 20 - 20
frontend/src/views/components/PictureEditor/mixin/edit/module/tools.js

@@ -2,8 +2,8 @@
 export default  {
   flip(){
     return `
-          <div class="title_two">翻转</div>
-          <div class="flex left">
+          <div class="flex left mar-top-10">
+          <div class="label-text">翻转:</div>
             <el-button size="small" @click="Flip('X')" >左右翻转</el-button>
             <el-button size="small" @click="Flip('Y')" >上下翻转</el-button>
           </div>
@@ -11,8 +11,8 @@ export default  {
   },
   straw(){
     return `
-          <div class="title_two">层级</div>
-          <div class="flex left">
+          <div class="flex left mar-top-10">
+          <div class="label-text">层级:</div>
             <el-button   @click="move(editLayer,'bringToFront')"  size="small">置顶</el-button>
             <el-button   @click="move(editLayer,'sendToBack')"  size="small">置底</el-button>
           </div>
@@ -20,8 +20,8 @@ export default  {
   },
   opacity(){
     return `
-          <div class="title_two">透明度</div>
-          <div class="flex left">
+          <div class="flex left mar-top-10">
+          <div class="label-text">透明度:</div>
             <el-slider
               size="small"
               v-model="opacityValue"
@@ -41,7 +41,7 @@ export default  {
     return `
           <div class="title_two">尺寸</div>
           <div class="flex left mar-top-10">
-            <div class="label fs-14 c-333 te-l" style="width: 35px;">宽</div>
+            <div class="label-text">宽:</div>
             <el-input-number
               v-model="imageSize.width"
               @change="updateImageSize('width')"
@@ -55,7 +55,7 @@ export default  {
             <span class="mar-left-10 c-999 fs-12">px</span>
           </div>
           <div class="flex left mar-top-10">
-            <div class="label fs-14 c-333 te-l" style="width: 35px;">高</div>
+            <div class="label-text">高:</div>
             <el-input-number
               v-model="imageSize.height"
               @change="updateImageSize('height')"
@@ -75,8 +75,8 @@ export default  {
   },
 cutout(){
   return `
-    <div class="title_two">剪裁</div>
-    <div class="flex left">
+    <div class="title_two mar-top-10">剪裁</div>
+    <div class="flex left mar-top-10">
       <el-select v-model="clipSettings.shape" @change="onClipShapeChange" size="small" style="width:100px">
         <el-option label="无" value=""></el-option>
         <el-option label="矩形" value="rect"></el-option>
@@ -91,7 +91,7 @@ cutout(){
 
       <!-- 背景色 -->
       <div class="flex left mar-top-10">
-        <div class="label fs-14 c-333 te-l" style="width: 50px;">背景</div>
+        <div class="label-text">背景:</div>
         <el-color-picker
           v-model="clipSettings.fillColor"
           @change="applyClipPath"
@@ -103,7 +103,7 @@ cutout(){
 
       <!-- 背景透明度 -->
       <div class="flex left mar-top-10">
-        <div class="label fs-14 c-333 te-l" style="width: 50px;">透明度</div>
+        <div class="label-text">透明度:</div>
         <el-slider
           v-model="clipSettings.fillOpacity"
           @input="applyClipPath"
@@ -118,7 +118,7 @@ cutout(){
 
       <!-- 描边 -->
       <div class="flex left mar-top-10">
-        <div class="label fs-14 c-333 te-l" style="width: 50px;">描边</div>
+        <div class="label-text">描边:</div>
         <el-color-picker
           v-model="clipSettings.strokeColor"
           @change="applyClipPath"
@@ -130,7 +130,7 @@ cutout(){
 
       <!-- 描边宽度 -->
       <div class="flex left mar-top-10">
-        <div class="label fs-14 c-333 te-l" style="width: 50px;">宽度</div>
+        <div class="label-text">宽度:</div>
         <el-input-number
           v-model="clipSettings.strokeWidth"
           @change="applyClipPath"
@@ -162,7 +162,7 @@ cutout(){
       
   <!--      <div class="title_two">位置</div>-->
       <div  class="flex left mar-top-10 ">
-            <div class="label fs-14 c-333 te-l"  style="width: 35px;">X</div>
+            <div class="label-text">X:</div>
                 <el-slider
                   size="small"
                   v-model="clipSettings.offsetX"
@@ -190,7 +190,7 @@ cutout(){
       </div>
       
       <div  class="flex left mar-top-10 ">
-            <div class="label fs-14 c-333 te-l"  style="width: 35px;">Y</div>
+            <div class="label-text">Y:</div>
                 <el-slider
                   size="small"
                   v-model="clipSettings.offsetY"
@@ -225,7 +225,7 @@ cutout(){
     <template v-if="clipSettings.shape === 'rect'">
        <!-- <div class="title_two">大小</div>-->
       <div  class="flex left mar-top-10 ">
-        <div class="label fs-14 c-333 te-l" style="width: 35px;">宽</div>
+            <div class="label-text">宽:</div>
         
                 <el-slider
                   size="small"
@@ -254,7 +254,7 @@ cutout(){
         
       </div>
       <div  class="flex left mar-top-10 ">
-        <div class="label fs-14 c-333 te-l"  style="width: 35px;">高</div>
+            <div class="label-text">高:</div>
         
                 <el-slider
                   size="small"
@@ -282,7 +282,7 @@ cutout(){
         <span class="mar-left-10 fs-12 c-999">px</span>
       </div>
       <div  class="flex left mar-top-10 ">
-        <div class="label fs-14 c-333 te-l"  style="width: 35px;">圆角</div>
+            <div class="label-text">圆角:</div>
         <el-input-number v-model="clipSettings.rectRadius" @input="applyClipPath" :step="1" :min="0" size="small" placeholder="圆角"/>
       </div>
     </template>
@@ -290,7 +290,7 @@ cutout(){
     <!-- 圆形参数 -->
     
       <div v-else  class="flex left mar-top-10 ">
-        <div class="label fs-14 c-333 te-l"  style="width: 35px;">半径</div>
+            <div class="label-text">半径:</div>
                 <el-slider
                   size="small"
                   v-model="clipSettings.radius"

+ 3 - 3
frontend/src/views/components/PictureEditor/mixin/layer/index.scss

@@ -57,8 +57,8 @@
   }
 
   .layer-item__preview {
-    width: 44px;
-    height: 44px;
+    width: 28px;
+    height: 28px;
     border-radius: 4px;
     background: #f5f5f5;
     border: 1px solid #eee;
@@ -66,7 +66,7 @@
     align-items: center;
     justify-content: center;
     overflow: hidden;
-    margin-right: 8px;
+    margin-right: 5px;
   }
   .layer-item__preview img {
     width: 100%;

+ 75 - 0
frontend/src/views/components/marketingEdit/index.vue

@@ -1384,6 +1384,45 @@ export default {
   background: #f5f7fa;
 }
 
+/* 图层一行布局样式 */
+.layer-item__content {
+  display: flex;
+  align-items: center;
+  gap: 8px;
+  width: 100%;
+}
+
+.layer-item__preview {
+  flex-shrink: 0;
+  width: 32px;
+  height: 32px;
+  border-radius: 4px;
+  overflow: hidden;
+}
+
+.layer-item__preview img {
+  width: 100%;
+  height: 100%;
+  object-fit: cover;
+}
+
+.layer-item__name-wrap {
+  flex: 1;
+  display: flex;
+  align-items: center;
+  gap: 4px;
+  min-width: 0; /* 允许flex子项缩小 */
+}
+
+.layer-item__name {
+  flex: 1;
+  min-width: 60px; /* 设置最小宽度 */
+}
+
+.layer-item__ops {
+  flex-shrink: 0;
+}
+
 /* 默认隐藏确认按钮,输入框聚焦时显示 */
 .layer-item__confirm {
   display: none;
@@ -1392,6 +1431,42 @@ export default {
   display: inline-block;
 }
 
+/* 文字编辑面板样式优化 */
+.label-text {
+  font-size: 12px;
+  color: #666;
+  white-space: nowrap;
+  margin-right: 4px;
+  width: 50px;
+}
+
+.unit-text {
+  font-size: 12px;
+  color: #999;
+  margin-left: 2px;
+}
+
+.edit-wrap .el-input__inner,
+.edit-wrap .el-textarea__inner {
+  border-radius: 4px;
+}
+
+.edit-wrap .el-button {
+  border-radius: 4px;
+}
+
+.edit-wrap .el-button--small {
+  padding: 7px 12px;
+}
+
+.edit-wrap .el-select .el-input__inner {
+  border-radius: 4px;
+}
+
+.edit-wrap .el-input-number .el-input__inner {
+  border-radius: 4px;
+}
+
 .goods-mode-samples .sample-row {
   display: flex;
   gap: 12px;

+ 4 - 4
frontend/src/views/components/marketingEdit/tpl/layer.js

@@ -14,10 +14,10 @@ export default function() {
             :class="{active:selectedIds.includes(item.id)}"
             @click.stop="onLayerClick(item)"
           >
-            <div class="layer-item__preview">
-              <img :src="getLayerCover(item)" alt="" />
-            </div>
-            <div class="layer-item__meta">
+            <div class="layer-item__content">
+              <div class="layer-item__preview">
+                <img :src="getLayerCover(item)" alt="" />
+              </div>
               <div class="layer-item__name-wrap">
                 <span v-if="item['data-key'] && item['data-type'] === 'text'" style="" class="fs-12">动态</span>
                 <input