liuhairui преди 3 седмици
родител
ревизия
9872e8d3dc
променени са 2 файла, в които са добавени 280 реда и са изтрити 249 реда
  1. BIN
      public/src/assets/top-bg.png
  2. 280 249
      src/view/performance/QualityAssessment/Product.vue

BIN
public/src/assets/top-bg.png


+ 280 - 249
src/view/performance/QualityAssessment/Product.vue

@@ -6,26 +6,8 @@
         <el-form inline>
           <el-form-item>
             <el-input v-model="searchInfo" placeholder="搜索关键字" clearable style="width: 300px;" />
-            
-            <!-- 文件夹筛选下拉菜单 -->
-            <!-- <el-dropdown @command="handleFolderCommand" style="margin-right: 10px;">
-              <el-button  icon="search" title="文件夹筛选">
-                {{ selectedFolder || '文件夹筛选' }}<el-icon class="el-icon--right"><arrow-down /></el-icon>
-              </el-button>
-              <template #dropdown>
-                <el-dropdown-menu>
-                  <el-dropdown-item command="">全部文件夹</el-dropdown-item>
-                  <el-dropdown-item v-for="(folder, index) in folderList" :key="index" :command="folder">
-                    {{ folder }}
-                  </el-dropdown-item>
-                </el-dropdown-menu>
-              </template>
-            </el-dropdown> -->
-            
             <el-button type="primary" icon="search" @click="onSubmit" title="搜索">查询</el-button>
             <el-button type="primary"  @click="onADD" >新增产品</el-button>
-            <!-- <el-button type="primary" title="选择图片,文生图" @click="texttoimg" :loading="isLoading">文生图</el-button>
-            <el-button type="primary" title="选择图片,图生图" @click="imgtoimg" :loading="isLoading">图生图</el-button> -->
           </el-form-item>
         </el-form>
       </layout-header>
@@ -33,7 +15,7 @@
       <layout>
         <!-- 左侧树形结构 -->
         <template v-if="userStore.userInfo.nickName === '超级管理员'">
-        <layout-sider :resize-directions="['right']" :width="190" style="margin-right: 10px">
+        <layout-sider :resize-directions="['right']" :width="290" style="margin-right: 10px">
           <div class="JKWTree-tree" style="height: 200px;width:100vh">
             <h3>商户名称</h3>
             <el-tree :data="treeData" class="treecolor"   @node-click="handleNodeClick"></el-tree>
@@ -59,8 +41,7 @@
                 :cell-class-name="tableDataCellClass"
                 @selection-change="SelectionChange"
                 @row-dblclick="onRowDblClick"
-                :show-overflow-tooltip="true"
-              >
+                :show-overflow-tooltip="true">
                 <el-table-column type="selection" width="55" />
                 <el-table-column label="ID" prop="id" width="70" />
                 <el-table-column label="产品名称" prop="产品名称" width="300" />
@@ -79,30 +60,24 @@
                 <el-table-column label="效果图" width="120">
                   <template #default="{ row }">
                     <el-image
-  :src="formatImageUrl(row.产品效果图)"
-  :preview-src-list="[formatImageUrl(row.产品效果图)]"
-  style="width: 90px; height: 70px;"
-  fit="contain"
-  preview-teleported
->
-  <template #error>
-    <div style="width: 100%; height: 100%; display: flex; flex-direction: column; align-items: center; justify-content: center; background: #f5f7fa; color: #909399; font-size: 12px;">
-      <el-icon><Picture /></el-icon>
-      <span>暂无效果图</span>
-    </div>
-  </template>
-</el-image>
+                      :src="formatImageUrl(row.产品效果图)"
+                      :preview-src-list="[formatImageUrl(row.产品效果图)]"
+                      style="width: 90px; height: 70px;"
+                      fit="contain"
+                      preview-teleported>
+                      <template #error>
+                        <div style="width: 100%; height: 100%; display: flex; flex-direction: column; align-items: center; justify-content: center; background: #f5f7fa; color: #909399; font-size: 12px;">
+                          <el-icon><Picture /></el-icon>
+                          <span>暂无效果图</span>
+                        </div>
+                      </template>
+                    </el-image>
                   </template>
                 </el-table-column>
                 <el-table-column label="创建时间" prop="创建时间" width="300" />
                 <el-table-column label="创建人" prop="创建人" width="300" />
-                
-  
-                
-
               </el-table>
 
-              <!-- 分页 -->
               <div class="gva-pagination">
                 <el-pagination
                   @size-change="handleSizeChange"
@@ -111,8 +86,7 @@
                   :page-sizes="[10, 30, 50, 100]"
                   :page-size="pageSize"
                   layout="total, sizes, prev, pager, next, jumper"
-                  :total="total"
-                />
+                  :total="total"/>
               </div>
             </div>
           </el-main>
@@ -120,32 +94,6 @@
       </layout>
     </layout>
 
-    <!-- 文生图弹窗 -->
-    <el-dialog v-model="txtimgDialogVisible" title="文生图" width="660px" top="10%">
-      <el-form label-width="100px">
-        <el-form-item label="文生图模型">
-          <div style="display: flex; align-items: center; gap: 20px; flex-wrap: wrap;">
-            <el-radio-group v-model="txtimgselectedModel" @change="handleModelChange">
-              <el-radio 
-                v-for="item in txttoimg_modelList" 
-                :key="item.id"
-                :label="item.txttoimg">
-                {{ item.txttoimg }} 
-                <span v-if="item.id === usedIds.wenshengtu" style="color: #67C23A; margin-left: 5px;">(默认使用)</span>
-              </el-radio>
-            </el-radio-group>
-            <el-button type="success"  @click="setActive('wenshengtu')"  :disabled="!selectedIds.wenshengtu || selectedIds.wenshengtu === usedIds.wenshengtu">
-              设为默认使用模型
-            </el-button>
-          </div>
-        </el-form-item>
-      </el-form>
-      <template #footer>
-        <el-button @click="txtimgDialogVisible = false">取消</el-button>
-        <el-button type="primary" @click="generateTxtImg" :loading="isGenerating">生成文生图</el-button>
-      </template>
-    </el-dialog>
-
 <el-dialog 
   v-model="editDialogVisible" 
   title="图片对比与编辑" 
@@ -160,15 +108,12 @@
       <!-- 图片对比区域 -->
       <div class="image-comparison-section" style="flex: 1; display: flex; flex-direction: column; gap: 15px;">
         <div class="image-item">
-    <div class="image-title">原图</div>
     <div style="display: flex; justify-content: space-between; width: 100%;">
       <div style="display: flex; gap: 12px;">
-        <el-button type="primary" size="large" @click="downloadImage('original')">
-          <el-icon><Download /></el-icon>下载原图
-        </el-button>
-        <el-button type="primary" size="large" @click="downloadImage('new')">
-        <el-icon><Download /></el-icon>下载新图
+        <el-button type="danger" size="large" @click="editDialogVisible = false">
+          <el-icon><Close /></el-icon>关闭
         </el-button>
+
       </div>
 
       <div style="display: flex; gap: 12px;">
@@ -182,15 +127,37 @@
     </div>
     
     <!-- 原图区域 -->
-    <div class="image-preview">
+    <div class="image-preview" style="position: relative;">
       <el-image
         v-if="editFormData.original_image_url"
         :src="formatImageUrl(editFormData.original_image_url)"
-        :preview-src-list="[formatImageUrl(editFormData.original_image_url)]"
         style="width: 100%; height: 200px;"
         fit="contain"
-        preview-teleported
       />
+      <!-- 放大图标 -->
+      <el-button
+        v-if="editFormData.original_image_url"
+        type="primary"
+        circle
+        size="medium"
+        style="position: absolute; top: 10px; left: 10px; opacity: 0; transition: opacity 0.3s; z-index: 10;"
+        @click.stop="handleImageZoom(formatImageUrl(editFormData.original_image_url))"
+        class="image-zoom-btn"
+      >
+        <el-icon><ZoomIn /></el-icon>
+      </el-button>
+      <!-- 下载图标 -->
+      <el-button
+        v-if="editFormData.original_image_url"
+        type="primary"
+        circle
+        size="medium"
+        style="position: absolute; top: 10px; right: 10px; opacity: 0; transition: opacity 0.3s; z-index: 10;"
+        @click.stop="downloadImage('original')"
+        class="image-download-btn"
+      >
+        <el-icon><Download /></el-icon>
+      </el-button>
       <div v-else class="image-placeholder">
         <el-icon :size="40"><Picture /></el-icon>
         <span>暂无原图</span>
@@ -201,15 +168,37 @@
     </div>
 
     <!-- 新图区域 -->
-    <div class="image-preview">
+    <div class="image-preview" style="position: relative;">
       <el-image
         v-if="editFormData.new_image_url"
         :src="formatImageUrl(editFormData.new_image_url)"
-        :preview-src-list="[formatImageUrl(editFormData.new_image_url)]"
         style="width: 100%; height: 200px;"
         fit="contain"
-        preview-teleported
       />
+      <!-- 放大图标 -->
+      <el-button
+        v-if="editFormData.new_image_url"
+        type="primary"
+        circle
+        size="medium"
+        style="position: absolute; top: 10px; left: 10px; opacity: 0; transition: opacity 0.3s; z-index: 10;"
+        @click.stop="handleImageZoom(formatImageUrl(editFormData.new_image_url))"
+        class="image-zoom-btn"
+      >
+        <el-icon><ZoomIn /></el-icon>
+      </el-button>
+      <!-- 下载图标 -->
+      <el-button
+        v-if="editFormData.new_image_url"
+        type="primary"
+        circle
+        size="medium"
+        style="position: absolute; top: 10px; right: 10px; opacity: 0; transition: opacity 0.3s; z-index: 10;"
+        @click.stop="downloadImage('new')"
+        class="image-download-btn"
+      >
+        <el-icon><Download /></el-icon>
+      </el-button>
       <div v-else class="image-placeholder">
         <el-icon :size="40"><Picture /></el-icon>
         <span>暂无新图</span>
@@ -232,7 +221,7 @@
           placeholder="点击右侧模板图片可自动填充描述内容"
           show-word-limit
           maxlength="500"
-          style="width: 100%; flex: 1;"
+          style="width: 100%;"
         />
     </el-form>
     
@@ -282,9 +271,9 @@
   
   <!-- 右侧:操作按钮 -->
   <div style="display: flex; gap: 10px;">
-    <el-button size="small" @click="clearInput">清空</el-button>
-    <el-button type="primary" size="small" @click="optimizeContent">内容优化</el-button>
-    <el-button type="success" size="small" @click="generateImage">生成图片</el-button>
+    <el-button @click="clearInput">清空</el-button>
+    <el-button type="primary" @click="optimizeContent">内容优化</el-button>
+    <el-button type="success" @click="generateImage">生成图片</el-button>
   </div>
 </div>
   </div>
@@ -292,12 +281,70 @@
     
     </div>
     
+    <!-- 中间:产品信息 -->
+    <div class="middle-column" style="width: 430px; border-left: 1px solid #e4e7ed; border-right: 1px solid #e4e7ed; padding: 0 20px;">
+      <div style="height: 100%; display: flex; flex-direction: column;">
+        
+        <!-- 上:留出的空白区域 -->
+        <div style="height: 90px; background-image: url('/public/src/assets/top-bg.png'); background-size: cover; background-position: center; border-top-left-radius: 8px; border-top-right-radius: 8px;"></div>
+        
+        <!-- 上中:图片显示区域 -->
+        <div style="display: flex; flex-direction: column; align-items: center;">
+          <div style="width: 430px; height: 290px; display: flex; justify-content: center; align-items: center; background-color: white; border-radius: 4px;">
+            <el-image
+              v-if="editFormData.new_image_url && showProductImage"
+              :src="formatImageUrl(editFormData.new_image_url)"
+              :preview-src-list="[formatImageUrl(editFormData.new_image_url)]"
+              style="width: 100%; height: 100%; object-fit: fill;"
+              fit="fill"
+              preview-teleported
+            />
+            <div v-else-if="!showProductImage || !editFormData.new_image_url" class="image-placeholder">
+              <el-icon :size="60"><Picture /></el-icon>
+              <span style="margin-top: 10px; display: block;">暂无产品图片</span>
+            </div>
+          </div>
+        </div>
+        
+        <!-- 中:商品信息表单 -->
+        <div class="product-info-container" style="height: 320px;border: 12px solid #f6E0dd; border-radius: 4px; padding: 15px;">
+          <div class="product-info-item">
+            <span class="product-info-label">商品条码:</span>
+            <span class="product-info-value">{{ editFormData.barcode || '-' }}</span>
+          </div>
+          <div class="product-info-item">
+            <span class="product-info-label">宏伟编码:</span>
+            <span class="product-info-value">{{ editFormData.code || '-' }}</span>
+          </div>
+          <div class="product-info-item">
+            <span class="product-info-label">产品名称:</span>
+            <span class="product-info-value">{{ editFormData.product_name || '-' }}</span>
+          </div>
+          <div class="product-info-item">
+            <span class="product-info-label">品牌名称:</span>
+            <span class="product-info-value">{{ editFormData.brand_name || '-' }}</span>
+          </div>
+          <div class="product-info-item">
+            <span class="product-info-label">产品规格:</span>
+            <span class="product-info-value">{{ editFormData.specification || '-' }}</span>
+          </div>
+          <div class="product-info-item">
+            <span class="product-info-label">单 位:</span>
+            <span class="product-info-value">{{ editFormData.unit || '-' }}</span>
+          </div>
+        </div>
+        
+        <!-- 下:空出来的部分 -->
+        <div style="width: 430px; height: 61px;">
+          
+        </div>
+      </div>
+    </div>
+    
     <!-- 右侧:模板列表 -->
-    <div class="right-column" style="flex: 1; border-left: 1px solid #e4e7ed; padding-left: 20px;">
+    <div class="right-column" style="flex: 2; padding-left: 20px;">
   <div class="right-template" style="height: 100%; display: flex; flex-direction: column;">
     <div class="template-header" style="margin-bottom: 15px;">
-      <h4>参考模板 ({{ templateList.length }})</h4>
-      <el-tag type="warning" size="small">点击选择</el-tag>
     </div>
     
     <!-- 搜索框 -->
@@ -306,7 +353,6 @@
         v-model="searchKeyword"
         placeholder="输入关键词搜索模板..."
         clearable
-        size="small"
         @keyup.enter="handleSearch"
         @clear="handleClearSearch"
       >
@@ -314,38 +360,20 @@
           <el-icon><Search /></el-icon>
         </template>
         <template #append>
-          <el-button
-            :icon="Search"
-            size="small"
-            :loading="searchLoading"
-            @click="handleSearch"
-          />搜索
+          <el-button @click="handleSearch" >搜索</el-button>
         </template>
       </el-input>
     </div>
     
     <!-- 模板列表 -->
     <div style="flex: 1; min-height: 0;">
+      <h4>参考模板 ({{ templateList.length }})</h4>
       <el-scrollbar style="height: 100%;">
         <div class="template-list">
-          <!-- 搜索结果为空提示 -->
-          <div v-if="searchLoading" class="loading-state">
-            <el-icon class="loading-icon" :size="30"><Loading /></el-icon>
-            <p>搜索中...</p>
-          </div>
-          
           <!-- 搜索无结果提示 -->
           <div v-if="!searchLoading && searchKeyword && templateList.length === 0" class="empty-search">
-            <el-icon :size="40"><Search /></el-icon>
+            <el-icon :size="50"><Search /></el-icon>
             <p>未找到相关模板</p>
-            <el-button
-              type="text"
-              size="small"
-              @click="handleClearSearch"
-              style="margin-top: 10px;"
-            >
-              查看全部模板
-            </el-button>
           </div>
           
           <!-- 模板项 -->
@@ -356,23 +384,34 @@
             :class="{ 'active': currentTemplateId === template.id }"
             @click="selectTemplate(template)"
           >
-            <div class="template-thumbnail">
-              <el-image
-                :src="template.template_image_url"
-                :preview-src-list="[template.template_image_url]"
-                style="width: 100%; height: 100%;"
-                fit="cover"
-                preview-teleported
-                hide-on-click-modal
-                @click.stop="handleTemplatePreview($event, template)"
-              >
-                <template #error>
-                  <div class="thumbnail-error">
-                    <el-icon><Picture /></el-icon>
-                  </div>
-                </template>
-              </el-image>
+            <div class="template-thumbnail" style="position: relative;">
+              <div class="image-container" @click.stop="selectTemplate(template)">
+                <el-image
+                  :src="template.template_image_url"
+                  style="width: 100%; height: 100%;"
+                  fit="cover"
+                >
+                  <template #error>
+                    <div class="thumbnail-error">
+                      <el-icon><Picture /></el-icon>
+                    </div>
+                  </template>
+                </el-image>
+                <div class="zoom-icon" @click.stop="handleImageZoom(template.template_image_url)">
+                  <el-icon :size="20"><ZoomIn /></el-icon>
+                </div>
+              </div>
               <div class="template-id">模板 {{ template.id }}</div>
+              <el-button
+                type="primary"
+                circle
+                size="small"
+                style="position: absolute; top: 10px; right: 10px; opacity: 0; transition: opacity 0.3s; z-index: 10;"
+                @click.stop="downloadTemplateImage(template.template_image_url)"
+                class="image-download-btn"
+              >
+                <el-icon><Download /></el-icon>
+              </el-button>
             </div>
             <div class="template-desc" :title="template.chinese_description">
               {{ truncateText(template.chinese_description, 25) }}
@@ -386,6 +425,13 @@
           </div>
         </div>
       </el-scrollbar>
+    
+    <!-- 图片预览组件 -->
+    <el-image-viewer
+      v-if="previewVisible"
+      :url-list="[previewImageUrl]"
+      @close="previewVisible = false"
+    />
     </div>
   </div>
 </div>
@@ -511,7 +557,7 @@ import { ElMessage, ElLoading} from 'element-plus'
 import { getTable, imageToText, Template_ids,txttoimg_moxing,GetHttpUrl,txttoimg_update, getSide,merchantGetab,productList,productDetail,
   product_template,GetTxtToTxt,GetProductFind,productAdd,getMerchantId } from '@/api/mes/job'
 import { useUserStore } from '@/pinia/modules/user'
-import { ArrowDown } from '@element-plus/icons-vue'
+import { ArrowDown, ZoomIn } from '@element-plus/icons-vue'
 import { Layout, LayoutHeader, LayoutSider, LayoutContent } from '@arco-design/web-vue'
 const props = defineProps({
   editFormData: {
@@ -610,16 +656,25 @@ const form = reactive({
   chinese_description: ''
 })
 
+// 控制产品信息部分图片是否显示
+const showProductImage = ref(false)
+
 const formatImageUrl = (path) => {
   if (!path) return ''
   return `${full_url.value}/${path.replace(/^public\//, '')}`
 }
 
+// 点击图片时更新产品信息部分的图片
+const updateProductImage = (imageUrl) => {
+  editFormData.new_image_url = imageUrl
+  showProductImage.value = true
+  ElMessage.success('图片已更新到产品信息区域')
+}
+
 const txttoimg_modelList = ref([]); // 存储所有模型数据
 const txtimgselectedModel = ref(''); // 当前选中的模型名称
 const usedId = ref(null); // 当前使用的模型ID(兼容旧代码)
 const selectedId = ref(null); // 用户选择的模型ID(兼容旧代码)
-const txtimgDialogVisible = ref(false); // 文生图弹窗可见性
 const isGenerating = ref(false); // 文生图生成中状态
 const usedIds = ref({}); // 当前使用的模型ID集合
 const selectedIds = ref({}); // 用户选择的模型ID集合
@@ -720,106 +775,6 @@ const setActive = async (type) => {
   }
 }
 
-// // 处理文件夹选择
-// const handleFolderCommand = (command) => {
-//   selectedFolder.value = command
-//   onSubmit()
-// }
-
-// const onSubmit = () => {
-//   page.value = 1
-//   getTableData()
-// }
-
-// const handleCurrentChange = (val) => {
-//   page.value = val
-//   getTableData()
-// }
-
-// const handleSizeChange = (val) => {
-//   pageSize.value = val
-//   page.value = 1
-//   getTableData()
-// }
-
-// const SelectionChange = (rows) => {
-//   _parh.value = rows.map(item => item.old_image_url)
-// }
-
-// // 文生图生成函数
-// const generateTxtImg = () => {
-//   txtimgDialogVisible.value = false
-//   processImages(toRaw(_parh.value), '文生图', form.chinese_description)
-// }
-
-// const texttoimg = async () => {
-//   if (_parh.value.length === 0) {
-//     ElMessage.warning('请先选择要处理的图片')
-//     return
-//   }
-//   // 获取模型列表
-//   await fetchTxtImgModels()
-//   // 显示弹窗
-//   txtimgDialogVisible.value = true
-// }
-
-// const imgtoimg = () => {
-//   processImages(toRaw(_parh.value), '图生图')
-// }
-
-// // 是否执行几何图(默认不执行)
-// const executeKeywords = ref(false)
-
-// const processImages = async (files, type, prompt = '') => {
-//   if (!Array.isArray(files) || files.length === 0) {
-//     ElMessage.warning('请选择要处理的图片')
-//     return
-//   }
-
-//   const pathGroups = {}
-//   _parh.value.forEach(path => {
-//     const dir = path.replace(/\/[^\/]*$/, '')
-//     if (!pathGroups[dir]) pathGroups[dir] = []
-//     pathGroups[dir].push(path)
-//   })
-
-//   isLoading.value = true
-//   const failList = []
-
-//   for (const [dir, images] of Object.entries(pathGroups)) {
-//     const payload = {
-//       old_image_file: dir,
-//       type,
-//       selectedOption: selectedOption.value,
-//       txttotxt_selectedOption: txttotxt_selectedOption.value,
-//       batch: images,
-//       num: num.value,
-//       width: width.value,
-//       height: height.value,
-//       executeKeywords:executeKeywords.value,
-//     }
-
-//     try {
-//       await imageToText(payload)
-//       ElMessage.success(`处理目录:${dir},共 ${images.length} 张 * ${num.value} 次`)
-//     } catch (e) {
-//       console.warn('处理失败:', dir, e)
-//       images.forEach((_, i) => failList.push(`目录 ${dir} 第 ${i + 1} 张`))
-//     }
-//   }
-
-//   if (failList.length > 0) {
-//     ElMessage.warning('部分图片处理失败,请查看控制台')
-//   }
-
-//   await new Promise(resolve => setTimeout(resolve, 3000))
-//   isLoading.value = false
-// }
-
-// const previewImage = (url) => {
-//   currentImageUrl.value = url
-//   dialogVisible.value = true
-// }
 
 const onRowDblClick = async (row) => {
   try {
@@ -896,6 +851,37 @@ const handleTemplateButton = () => {
 
 
 
+// 图片预览相关
+const previewVisible = ref(false)
+const previewImageUrl = ref('')
+
+// 处理图片放大
+const handleImageZoom = (url) => {
+  previewImageUrl.value = url
+  previewVisible.value = true
+}
+
+// 下载模板图片
+const downloadTemplateImage = async (imageUrl) => {
+  try {
+    // 创建一个临时的a标签用于下载
+    const link = document.createElement('a')
+    link.href = imageUrl
+    // 设置文件名,从URL中提取或使用默认名
+    const fileName = imageUrl.split('/').pop() || `template_${Date.now()}.jpg`
+    link.download = fileName
+    // 触发下载
+    document.body.appendChild(link)
+    link.click()
+    // 清理
+    document.body.removeChild(link)
+    ElMessage.success('图片下载成功')
+  } catch (error) {
+    console.error('图片下载失败:', error)
+    ElMessage.error('图片下载失败,请稍后重试')
+  }
+}
+
 // 截断文本函数
 const truncateText = (text, length) => {
   if (!text) return '无描述'
@@ -1494,8 +1480,6 @@ const handleRemoveImage = () => {
   productForm.product_img = ''
 }
 
-
-
 // 暴露方法给父组件
 defineExpose({
   openDialog
@@ -1512,9 +1496,9 @@ defineExpose({
   :deep(.el-table td .cell) {
     line-height: 22px !important;
   }
-  :deep(.el-dialog__body) {
+  /* :deep(.el-dialog__body) {
     padding: 10px 20px;
-  }
+  } */
   .gva-pagination {
     margin-top: 10px;
     text-align: right;
@@ -1572,8 +1556,6 @@ defineExpose({
   
   .image-preview {
     flex: 1;
-    border: 1px solid #dcdfe6;
-    border-radius: 4px;
     overflow: hidden;
     display: flex;
     flex-direction: column;
@@ -1607,17 +1589,11 @@ defineExpose({
   
   .image-actions {
     display: flex;
-    gap: 10px;
     justify-content: center;
     padding: 10px 0;
   }
   
   .edit-section {
-    flex: 1;
-    border: 1px solid #e4e7ed;
-    border-radius: 4px;
-    padding: 15px;
-    min-height: 200px;
     overflow: hidden; /* 防止溢出 */
   }
   
@@ -1640,10 +1616,6 @@ defineExpose({
   }
   
   .right-column {
-    flex: 1;
-    border: 1px solid #e4e7ed;
-    border-radius: 4px;
-    padding: 15px;
     display: flex;
     flex-direction: column;
     min-height: 0; /* 防止溢出 */
@@ -1677,22 +1649,26 @@ defineExpose({
   .template-list {
     flex: 1;
     display: flex;
-    flex-direction: column;
+    flex-direction: row;
+    flex-wrap: wrap;
     gap: 10px;
     overflow-y: auto;
     min-height: 0; /* 防止溢出 */
+    padding: 5px;
   }
   
   .template-item {
     display: flex;
-    align-items: center;
+    flex-direction: column;
+    width: calc(33.33% - 7px); /* 一行显示3个,减去gap */
     padding: 10px;
-    border: 1px solid #e4e7ed;
+    border: 2px solid #e4e7ed;
     border-radius: 6px;
     cursor: pointer;
     transition: all 0.3s;
     background: white;
     flex-shrink: 0; /* 防止被压缩 */
+    box-sizing: border-box;
   }
   
   .template-item:hover {
@@ -1708,10 +1684,9 @@ defineExpose({
   
   .template-thumbnail {
     position: relative;
-    width: 160px;
-    height: 140px;
-    flex-shrink: 0;
-    margin-right: 12px;
+    width: 100%;
+    height: 120px;
+    margin-bottom: 8px;
     border-radius: 4px;
     overflow: hidden;
     background: #f5f7fa;
@@ -1723,6 +1698,57 @@ defineExpose({
     object-fit: cover;
   }
   
+  .image-container {
+    position: relative;
+    width: 100%;
+    height: 100%;
+    cursor: pointer;
+  }
+  
+  .zoom-icon {
+    position: absolute;
+    bottom: 8px;
+    right: 8px;
+    width: 28px;
+    height: 28px;
+    background: rgba(0, 0, 0, 0.6);
+    color: white;
+    border-radius: 50%;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    cursor: zoom-in;
+    opacity: 0;
+    transition: opacity 0.3s ease;
+  }
+  
+  .image-container:hover .zoom-icon {
+    opacity: 1;
+  }
+  
+  /* 商品信息项样式 */
+  .product-info-item {
+    margin-bottom: 10px;
+    display: flex;
+    align-items: center;
+  }
+  
+  .product-info-label {
+    font-size: 14px;
+    color: #000000;
+    font-weight: bold;
+    width: 90px;
+    text-align: left;
+  }
+  
+  .product-info-value {
+    font-size: 14px;
+    color: #000000;
+    flex: 1;
+    text-align: left;
+    word-break: break-all;
+  }
+  
   .template-id {
     position: absolute;
     top: 4px;
@@ -1735,6 +1761,11 @@ defineExpose({
     font-weight: bold;
   }
   
+  .image-preview:hover .image-download-btn,
+  .image-preview:hover .image-zoom-btn {
+    opacity: 1;
+  }
+  
   .template-desc {
     flex: 1;
     font-size: 12px;