浏览代码

first commit

liuhairui 1 周之前
父节点
当前提交
7a9944d975

+ 9 - 0
src/api/mes/job.js

@@ -1371,6 +1371,15 @@ export const getMerchantId = (params) => {
   })
 }
 
+// 删除产品
+export const productDelete = (params) => {
+  return service({
+    url: '/mes_server/product/productDelete',
+    method: 'post',
+    params
+  })
+}
+
 
 //查询获取任务数据
 export const GetImageStatus = (params) => {

文件差异内容过多而无法显示
+ 555 - 131
src/view/TemplateManagement/CreateTemplate.vue


+ 24 - 29
src/view/TemplateManagement/TemplateDesign.vue

@@ -69,6 +69,7 @@
                 <img
                   :src="formatImageUrl(template.thumbnail_image || template.template_image_url)"
                   :alt="template.template_name"
+                  loading="lazy"
                   @error="(e) => { e.target.onerror = null; e.target.src = 'data:image/svg+xml,%3Csvg xmlns=%22http://www.w3.org/2000/svg%22 width=%22200%22 height=%22150%22%3E%3Crect fill=%22%23f5f5f5%22 width=%22200%22 height=%22150%22/%3E%3C/svg%3E' }"
                 />
               <span v-if="libraryMenuActive === 'myWorks'" class="template-release-tag" :class="{ published: isPublished(template) }">
@@ -122,7 +123,7 @@ import { ElMessage } from 'element-plus'
 import { Plus, Picture, Search, MoreFilled, Loading, Delete } from '@element-plus/icons-vue'
 import { ElMessageBox } from 'element-plus'
 import { useUserStore } from '@/pinia/modules/user'
-import { Template_Material_Delete, Template_Material_Publish, Template_Material_Unpublish, product_template, GetHttpUrl } from '@/api/mes/job'
+import { Template_Material_Delete, Template_Material_Publish, Template_Material_Unpublish, product_template } from '@/api/mes/job'
 import CreateTemplate from './CreateTemplate.vue'
 
 const currentView = ref('library')
@@ -141,38 +142,25 @@ const userStore = useUserStore()
 
 const isPublished = (template) => template?.release === 1 || template?.release === '1'
 
-// 获取服务器地址(用于拼接图片 URL,显示用)
-const full_url = ref('')
-const fetchServerUrl = async () => {
-  try {
-    const res = await GetHttpUrl()
-    if (res.code === 0 && res.data && res.data.full_url) {
-      full_url.value = res.data.full_url || ''
-    }
-  } catch (error) {
-    console.error('获取服务器地址失败:', error)
-  }
-}
-
-// 显示用 base,必须用 9093 端口,不要用 9090(CLI 端口)
-function getDisplayBaseUrl() {
-  const base = import.meta.env.VITE_BASE_PATH || ''
-  const port = import.meta.env.VITE_UPLOADS_PORT || '9093'
-  const uploadsBase = base && port ? `${base.replace(/:(\d+)?$/, '')}:${port}` : ''
-  const fromApi = (full_url.value || '').replace(/\/$/, '')
-  if (fromApi && !fromApi.match(/:9090(?:$|\/)/)) return fromApi
-  return uploadsBase || ''
-}
-
+// 图片 URL:拼接 VITE_BASE_PATH + VITE_UPLOADS_PORT(如 http://39.108.146.216:8081/uploads/xxx)
 const formatImageUrl = (path) => {
   if (!path || typeof path !== 'string') return ''
   const p = path.trim()
   if (!p) return ''
-  if (p.startsWith('http://') || p.startsWith('https://') || p.startsWith('data:')) return p
-  const baseUrl = getDisplayBaseUrl()
+  if (p.startsWith('data:')) return p
+  if (p.startsWith('http://') || p.startsWith('https://')) {
+    try {
+      const u = new URL(p)
+      if (u.port === '9090') return `${u.protocol}//${u.hostname}:9093${u.pathname}${u.search}`
+    } catch { /* ignore */ }
+    return p
+  }
   const cleanPath = p.replace(/^public\//, '').replace(/^\//, '')
-  if (!baseUrl) return '/' + cleanPath
-  return `${baseUrl}/${cleanPath}`
+  const pathNorm = cleanPath.startsWith('/') ? cleanPath : '/' + cleanPath
+  const base = import.meta.env.VITE_BASE_PATH || ''
+  const port = import.meta.env.VITE_UPLOADS_PORT || '8081'
+  const uploadsBase = base && port ? `${base.replace(/:(\d+)?$/, '')}:${port}` : ''
+  return uploadsBase ? `${uploadsBase.replace(/\/$/, '')}${pathNorm}` : pathNorm
 }
 
 const fetchTemplates = async () => {
@@ -229,6 +217,14 @@ const handleCreateBack = () => {
 
 const handlePublish = async (template) => {
   if (!template?.id) return
+  const name = (template.template_name || '').trim()
+  if (!name || name === '未命名模版') {
+    await ElMessageBox.alert('请先命名模版名称', '提示', {
+      confirmButtonText: '知道了',
+      type: 'warning'
+    })
+    return
+  }
   try {
     publishLoading.value = template.id
     const res = await Template_Material_Publish({ template_id: template.id })
@@ -292,7 +288,6 @@ const handleDelete = async (template) => {
 }
 
 onMounted(() => {
-  fetchServerUrl()
   fetchTemplates()
 })
 

+ 0 - 8
src/view/TemplateManagement/WorkDetail.vue

@@ -1,8 +0,0 @@
-<template>
-</template>
-
-<script>
-</script>
-
-<style>
-</style>

+ 2 - 2
src/view/about/index.vue

@@ -15,7 +15,7 @@
                 <a href="https://github.com/flipped-aurora/gin-vue-admin">
                   <img
                     class="org-img dom-center"
-                    src="@/assets/logo.png"
+                    src="https://raw.githubusercontent.com/flipped-aurora/gin-vue-admin/main/web/src/assets/logo.png"
                     alt="gin-vue-admin"
                   >
                 </a>
@@ -65,7 +65,7 @@
                 <a href="https://github.com/flipped-aurora">
                   <img
                     class="org-img dom-center"
-                    src="@/assets/flipped-aurora.png"
+                    src="https://raw.githubusercontent.com/flipped-aurora/gin-vue-admin/main/web/src/assets/flipped-aurora.png"
                     alt="flipped-aurora"
                   >
                 </a>

+ 1 - 1
src/view/dashboard/dashboardCharts/echartsLine.vue

@@ -2,7 +2,7 @@
   <!-- <div class="dashboard-line-box"> -->
   <div class="dashboard-line-box">
     <div class="dashboard-line-title">
-      近一年工单数
+     
     </div>
     <div
       ref="echart"

+ 22 - 29
src/view/dashboard/index.vue

@@ -2,25 +2,25 @@
   <div class="page">
     <div class="gva-card-box">
         <div class="gva-card gva-top-card">
-          <div class="gva-top-card-content flex items-center">
-            <div class="dashboard-item">
+         <div class="gva-top-card-content flex items-center">
+          <!--  <div class="dashboard-item">
               <el-icon class="dashboard-icon">
                 <comment />
               </el-icon>
-              <!-- <label :for="id" class="label-text">计划中工单数: {{ labelValue1 }}</label> -->
+              <label :for="id" class="label-text">: {{ labelValue1 }}</label>
             </div>
             <div class="dashboard-item">
               <el-icon class="dashboard-icon">
                 <comment />
               </el-icon>
-              <!-- <label :for="id" class="label-text">制程中工单数: {{ labelValue3 }}</label> -->
+              <label :for="id" class="label-text">: {{ labelValue3 }}</label>
             </div>
             <div class="dashboard-item">
               <el-icon class="dashboard-icon">
                 <comment />
               </el-icon>
-              <!-- <label :for="id" class="label-text">已完工工单数: {{ labelValue4 }}</label> -->
-            </div>
+              <label :for="id" class="label-text">: {{ labelValue4 }}</label>
+            </div> -->
           </div>
           <img src="@/assets/dashboard.png" class="gva-top-card-right" alt>
         </div>
@@ -55,7 +55,7 @@
         </el-row>
       </div>
     </div>
-    <div class="gva-card-box">
+<!--    <div class="gva-card-box">
         <div class="gva-card">
           <div class="gva-card-title">数据统计</div>
           <div class="p-4">
@@ -75,7 +75,7 @@
             </el-row>
           </div>
         </div>
-      </div>
+      </div> -->
   </div>
 </template>
 
@@ -97,13 +97,6 @@ const weatherInfo = useWeatherInfo()
 
 const getindex = async () => {
     //接口调用函数
-    // const response  = await index();
-	// console.log(response.data.workOrderData["已完工"].toString())
-	// labelValue1.value = response.data.workOrderData["已完工"].toString();
-	// labelValue2.value = response.data.workOrderData["计划中"].toString();
-	// labelValue3.value = response.data.workOrderData["排程中"].toString();
-	// labelValue4.value = response.data.workOrderData["制程中"].toString();
-	
 }
 getindex()
 const labelValue1=ref()
@@ -132,20 +125,20 @@ const toolCards = ref([
     color: '#b37feb',
     bg: 'rgba(179, 127, 235,.3)'
   },
-  {
-    label: '代码生成器',
-    icon: 'cpu',
-    name: 'autoCode',
-    color: '#ffd666',
-    bg: 'rgba(255, 214, 102,.3)'
-  },
-  {
-    label: '表单生成器',
-    icon: 'document-checked',
-    name: 'formCreate',
-    color: '#ff85c0',
-    bg: 'rgba(255, 133, 192,.3)'
-  },
+  // {
+  //   label: '代码生成器',
+  //   icon: 'cpu',
+  //   name: 'autoCode',
+  //   color: '#ffd666',
+  //   bg: 'rgba(255, 214, 102,.3)'
+  // },
+  // {
+  //   label: '表单生成器',
+  //   icon: 'document-checked',
+  //   name: 'formCreate',
+  //   color: '#ff85c0',
+  //   bg: 'rgba(255, 133, 192,.3)'
+  // },
   {
     label: '关于我们',
     icon: 'user',

+ 2 - 1
src/view/layout/index.vue

@@ -17,7 +17,7 @@
           <img
             alt
             class="w-9 h-9 p-1 bg-white rounded-full"
-            :src="`http://20.0.16.128:9093/img/logo.png`"
+            :src="profileImg"
           >
           <div
             v-if="isSider"
@@ -190,6 +190,7 @@
 </template>
 
 <script setup>
+import profileImg from '@/assets/bjtx.png'
 import Aside from '@/view/layout/aside/index.vue'
 import HistoryComponent from '@/view/layout/aside/historyComponent/history.vue'
 import Search from '@/view/layout/search/search.vue'

+ 0 - 441
src/view/performance/QualityAssessment/Category.vue

@@ -1,441 +0,0 @@
-<template>
-  <div class="food-category">
-    <el-card shadow="hover">
-      <template #header>
-        <div class="card-header">
-          <span>食品数据管理</span>
-        </div>
-      </template>
-      
-      <!-- 搜索和筛选区域 -->
-      <div class="search-filter">
-        <el-form :model="searchForm" label-width="80px" inline>
-          <el-form-item label="食品名称">
-            <el-input 
-              v-model="searchForm.productName" 
-              placeholder="请输入食品名称" 
-              clearable
-              @keyup.enter="getProductList"
-            />
-          </el-form-item>
-          <el-form-item label="食品类型">
-            <el-select 
-              v-model="searchForm.foodType" 
-              placeholder="请选择食品类型" 
-              clearable
-            >
-              <el-option label="蔬菜" value="vegetable" />
-              <el-option label="水果" value="fruit" />
-              <el-option label="肉类" value="meat" />
-              <el-option label="海鲜" value="seafood" />
-              <el-option label="加工食品" value="processed" />
-            </el-select>
-          </el-form-item>
-          <el-form-item label="生成状态">
-            <el-select 
-              v-model="searchForm.status" 
-              placeholder="请选择状态" 
-              clearable
-            >
-              <el-option label="已生成" value="success" />
-              <el-option label="生成中" value="generating" />
-              <el-option label="生成失败" value="failed" />
-            </el-select>
-          </el-form-item>
-          <el-form-item>
-            <el-button type="primary" @click="getProductList">搜索</el-button>
-            <el-button @click="resetSearch">重置</el-button>
-          </el-form-item>
-        </el-form>
-      </div>
-      
-      <!-- 产品列表 -->
-      <div class="food-list">
-        <el-table 
-          :data="productList" 
-          style="width: 100%" 
-          stripe
-          @row-click="handleRowClick"
-        >
-          <el-table-column prop="id" label="食品ID" width="80" />
-          <el-table-column prop="productName" label="食品名称" width="200" />
-          <el-table-column prop="foodType" label="食品类型" width="120">
-            <template #default="scope">
-              <el-tag 
-                :type="scope.row.foodType === 'vegetable' ? 'success' : 
-                      scope.row.foodType === 'fruit' ? 'warning' : 
-                      scope.row.foodType === 'meat' ? 'danger' : 
-                      scope.row.foodType === 'seafood' ? 'primary' : 'info'"
-              >
-                {{ scope.row.foodType === 'vegetable' ? '蔬菜' : 
-                   scope.row.foodType === 'fruit' ? '水果' : 
-                   scope.row.foodType === 'meat' ? '肉类' : 
-                   scope.row.foodType === 'seafood' ? '海鲜' : '加工食品' }}
-              </el-tag>
-            </template>
-          </el-table-column>
-          <el-table-column prop="size" label="图片尺寸" width="120" />
-          <el-table-column prop="style" label="设计风格" width="120" />
-          <el-table-column prop="status" label="生成状态" width="120">
-            <template #default="scope">
-              <el-tag 
-                :type="scope.row.status === 'success' ? 'success' : 
-                      scope.row.status === 'generating' ? 'warning' : 'danger'"
-              >
-                {{ scope.row.status === 'success' ? '已生成' : 
-                   scope.row.status === 'generating' ? '生成中' : '生成失败' }}
-              </el-tag>
-            </template>
-          </el-table-column>
-          <el-table-column prop="createTime" label="创建时间" width="180" />
-          <el-table-column label="操作" width="200">
-            <template #default="scope">
-              <el-button type="primary" size="small" @click="viewProduct(scope.row)">查看详情</el-button>
-              <el-button type="danger" size="small" @click="deleteProduct(scope.row.id)">删除</el-button>
-            </template>
-          </el-table-column>
-        </el-table>
-        
-        <!-- 分页 -->
-        <div class="pagination">
-          <el-pagination
-            @size-change="handleSizeChange"
-            @current-change="handleCurrentChange"
-            :current-page="pagination.currentPage"
-            :page-sizes="[10, 20, 50, 100]"
-            :page-size="pagination.pageSize"
-            layout="total, sizes, prev, pager, next, jumper"
-            :total="pagination.total"
-          />
-        </div>
-      </div>
-    </el-card>
-    
-    <!-- 产品详情对话框 -->
-    <el-dialog
-      v-model="detailDialogVisible"
-      title="食品详情"
-      width="800px"
-      :before-close="handleDetailClose"
-    >
-      <div class="food-detail" v-if="selectedProduct">
-        <div class="detail-section">
-          <h3>基本信息</h3>
-          <el-descriptions :column="2" border>
-            <el-descriptions-item label="食品ID">{{ selectedProduct.id }}</el-descriptions-item>
-            <el-descriptions-item label="食品名称">{{ selectedProduct.productName }}</el-descriptions-item>
-            <el-descriptions-item label="食品类型">
-              <el-tag 
-                :type="selectedProduct.foodType === 'vegetable' ? 'success' : 
-                      selectedProduct.foodType === 'fruit' ? 'warning' : 
-                      selectedProduct.foodType === 'meat' ? 'danger' : 
-                      selectedProduct.foodType === 'seafood' ? 'primary' : 'info'"
-              >
-                {{ selectedProduct.foodType === 'vegetable' ? '蔬菜' : 
-                   selectedProduct.foodType === 'fruit' ? '水果' : 
-                   selectedProduct.foodType === 'meat' ? '肉类' : 
-                   selectedProduct.foodType === 'seafood' ? '海鲜' : '加工食品' }}
-              </el-tag>
-            </el-descriptions-item>
-            <el-descriptions-item label="产地">{{ selectedProduct.origin }}</el-descriptions-item>
-            <el-descriptions-item label="营养价值">{{ selectedProduct.nutrition }}</el-descriptions-item>
-            <el-descriptions-item label="图片尺寸">{{ selectedProduct.size }}</el-descriptions-item>
-            <el-descriptions-item label="设计风格">{{ selectedProduct.style }}</el-descriptions-item>
-            <el-descriptions-item label="生成状态">
-              <el-tag 
-                :type="selectedProduct.status === 'success' ? 'success' : 
-                      selectedProduct.status === 'generating' ? 'warning' : 'danger'"
-              >
-                {{ selectedProduct.status === 'success' ? '已生成' : 
-                   selectedProduct.status === 'generating' ? '生成中' : '生成失败' }}
-              </el-tag>
-            </el-descriptions-item>
-            <el-descriptions-item label="创建时间" :span="2">{{ selectedProduct.createTime }}</el-descriptions-item>
-          </el-descriptions>
-        </div>
-        
-        <div class="detail-section">
-          <h3>提示词信息</h3>
-          <el-input
-            v-model="selectedProduct.prompt"
-            type="textarea"
-            :rows="4"
-            readonly
-            style="background-color: #f5f7fa"
-          />
-        </div>
-        
-        <div class="detail-section">
-          <h3>生成结果</h3>
-          <div class="generated-image">
-            <el-image
-              v-if="selectedProduct.generatedImage"
-              :src="selectedProduct.generatedImage"
-              fit="contain"
-              style="max-width: 100%; max-height: 400px"
-            >
-              <template #error>
-                <div class="image-error">图片加载失败</div>
-              </template>
-            </el-image>
-            <el-empty v-else description="暂无生成图片" />
-          </div>
-        </div>
-      </div>
-    </el-dialog>
-  </div>
-</template>
-
-<script setup>
-import {ref,reactive,onMounted} from 'vue'
-import {ElMessage,ElMessageBox,ElEmpty,ElImage} from 'element-plus'
-import {Loading} from '@element-plus/icons-vue'
-import {useUserStore} from '@/pinia/modules/user'
-// 假设存在获取产品列表的API,需要根据实际情况修改
-// import {getProductListApi, deleteProductApi} from '@/api/mes/product'
-
-// 定义组件名称
-
-defineOptions({name: 'Category'})
-
-// 搜索表单
-const searchForm = reactive({
-  productName: '',
-  foodType: '',
-  status: ''
-})
-
-// 食品列表数据
-const productList = ref([])
-
-// 分页信息
-const pagination = reactive({
-  currentPage: 1,
-  pageSize: 10,
-  total: 0
-})
-
-// 加载状态
-const loading = ref(false)
-
-// 详情对话框
-const detailDialogVisible = ref(false)
-const selectedProduct = ref(null)
-
-// 模拟食品数据
-const mockProducts = [
-  {
-    id: 1,
-    productName: '有机胡萝卜',
-    foodType: 'vegetable',
-    origin: '山东寿光',
-    nutrition: '富含胡萝卜素、维生素A',
-    size: '1024x1024',
-    style: 'realistic',
-    status: 'success',
-    createTime: '2023-10-20 10:30:00',
-    prompt: '创建一张有机胡萝卜的宣传图片,展示新鲜的有机胡萝卜,背景使用自然土壤色调,突出健康、有机的主题。',
-    generatedImage: 'https://picsum.photos/seed/carrot1/1024/1024'
-  },
-  {
-    id: 2,
-    productName: '挪威三文鱼',
-    foodType: 'seafood',
-    origin: '挪威',
-    nutrition: '富含Omega-3脂肪酸、蛋白质',
-    size: '1024x1024',
-    style: 'realistic',
-    status: 'success',
-    createTime: '2023-10-21 11:45:00',
-    prompt: '设计一张挪威三文鱼的宣传海报,展示新鲜的三文鱼片,背景使用海洋元素,突出其新鲜和营养价值。',
-    generatedImage: 'https://picsum.photos/seed/salmon1/1024/1024'
-  },
-  {
-    id: 3,
-    productName: '原味鱼干',
-    foodType: 'processed',
-    origin: '福建厦门',
-    nutrition: '富含蛋白质、钙、磷',
-    size: '1024x1024',
-    style: 'realistic',
-    status: 'success',
-    createTime: '2023-10-23 09:00:00',
-    prompt: '创建一张原味鱼干的宣传图片,展示自然晾晒的鱼干,背景使用海边场景,突出其新鲜和传统工艺。',
-    generatedImage: 'https://images.unsplash.com/photo-1610486295123-078299c50e79?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1024&q=80'
-  }
-]
-
-// 获取食品列表
-const getProductList = async () => {
-  loading.value = true
-  try {
-    // 实际项目中这里应该调用API获取数据
-    // const res = await getProductListApi({
-    //   page: pagination.currentPage,
-    //   pageSize: pagination.pageSize,
-    //   productName: searchForm.productName,
-    //   foodType: searchForm.foodType,
-    //   status: searchForm.status
-    // })
-    
-    // 模拟API调用
-    await new Promise(resolve => setTimeout(resolve, 500))
-    
-    // 模拟筛选数据
-    let filteredProducts = [...mockProducts]
-    if (searchForm.productName) {
-      filteredProducts = filteredProducts.filter(p => p.productName.includes(searchForm.productName))
-    }
-    if (searchForm.foodType) {
-      filteredProducts = filteredProducts.filter(p => p.foodType === searchForm.foodType)
-    }
-    if (searchForm.status) {
-      filteredProducts = filteredProducts.filter(p => p.status === searchForm.status)
-    }
-    
-    productList.value = filteredProducts
-    pagination.total = filteredProducts.length
-    
-    ElMessage({ message: '获取食品列表成功', type: 'success' })
-  } catch (error) {
-    console.error('获取食品列表失败:', error)
-    ElMessage({ message: '获取食品列表失败', type: 'error' })
-  } finally {
-    loading.value = false
-  }
-}
-
-// 重置搜索
-const resetSearch = () => {
-  searchForm.productName = ''
-  searchForm.foodType = ''
-  searchForm.status = ''
-  pagination.currentPage = 1
-  getProductList()
-}
-
-// 分页处理
-const handleSizeChange = (size) => {
-  pagination.pageSize = size
-  pagination.currentPage = 1
-  getProductList()
-}
-
-const handleCurrentChange = (current) => {
-  pagination.currentPage = current
-  getProductList()
-}
-
-// 查看产品详情
-const viewProduct = (product) => {
-  selectedProduct.value = {...product}
-  detailDialogVisible.value = true
-}
-
-// 处理行点击
-const handleRowClick = (row) => {
-  viewProduct(row)
-}
-
-// 删除产品
-const deleteProduct = (id) => {
-  ElMessageBox.confirm('确定要删除该产品吗?', '提示', {
-    confirmButtonText: '确定',
-    cancelButtonText: '取消',
-    type: 'warning'
-  }).then(async () => {
-    try {
-      // 实际项目中这里应该调用API删除数据
-      // await deleteProductApi(id)
-      
-      // 模拟API调用
-      await new Promise(resolve => setTimeout(resolve, 300))
-      
-      // 从列表中移除
-      const index = productList.value.findIndex(p => p.id === id)
-      if (index > -1) {
-        productList.value.splice(index, 1)
-        pagination.total--
-      }
-      
-      ElMessage({ message: '删除成功', type: 'success' })
-    } catch (error) {
-      console.error('删除失败:', error)
-      ElMessage({ message: '删除失败', type: 'error' })
-    }
-  }).catch(() => {
-    // 取消删除
-  })
-}
-
-// 处理详情对话框关闭
-const handleDetailClose = () => {
-  detailDialogVisible.value = false
-  selectedProduct.value = null
-}
-
-// 页面挂载时获取产品列表
-onMounted(() => {
-  getProductList()
-})
-</script>
-
-<style scoped>
-.product-category {
-  padding: 20px;
-}
-
-.card-header {
-  display: flex;
-  justify-content: space-between;
-  align-items: center;
-}
-
-.search-filter {
-  margin-bottom: 20px;
-}
-
-.product-list {
-  margin-top: 20px;
-}
-
-.pagination {
-  margin-top: 20px;
-  text-align: right;
-}
-
-.product-detail {
-  padding: 10px 0;
-}
-
-.detail-section {
-  margin-bottom: 25px;
-}
-
-.detail-section h3 {
-  margin-bottom: 15px;
-  font-size: 16px;
-  font-weight: 600;
-  color: #303133;
-  border-bottom: 1px solid #ebeef5;
-  padding-bottom: 5px;
-}
-
-.generated-image {
-  margin-top: 10px;
-  padding: 20px;
-  background-color: #fafafa;
-  border-radius: 8px;
-  text-align: center;
-}
-
-.image-error {
-  display: flex;
-  justify-content: center;
-  align-items: center;
-  width: 100%;
-  height: 200px;
-  background-color: #f5f7fa;
-  color: #909399;
-}
-</style>

+ 0 - 970
src/view/performance/QualityAssessment/Newdialogue.vue

@@ -1,970 +0,0 @@
-<template>
-  <div class="chat-interface">
-    <!-- 生成类型选项卡 -->
-    <div class="generation-tabs">
-      <el-tabs v-model="activeTab" type="card">
-        <el-tab-pane label="视频生成" name="video">
-          <template #label>
-            <div class="tab-label">
-              <el-icon class="tab-icon"><VideoPlay /></el-icon>
-              <span>视频生成</span>
-            </div>
-          </template>
-        </el-tab-pane>
-        <el-tab-pane label="图片生成" name="image">
-          <template #label>
-            <div class="tab-label">
-              <el-icon class="tab-icon"><Picture /></el-icon>
-              <span>图片生成</span>
-            </div>
-          </template>
-        </el-tab-pane>
-      </el-tabs>
-    </div>
-
-    <!-- 输入区域容器 -->
-    <div class="input-container">
-      <!-- 上传区域:上传按钮和已上传图片水平排列 -->
-    <div class="upload-area">
-      <!-- 上传按钮 -->
-      <el-button 
-        type="default" 
-        class="add-btn"
-        @click="triggerUpload"
-        title="上传"
-      >
-        <el-icon><Plus /></el-icon>
-        <span>上传</span>
-      </el-button>
-
-      <!-- 已上传图片预览 -->
-      <div class="uploaded-images-container">
-        <div 
-          v-for="(img, index) in uploadedImages" 
-          :key="index"
-          class="message-image"
-        >
-          <!-- 使用自定义图片预览功能 -->
-          <el-image 
-            :src="img.url" 
-            fit="cover"
-            @click="handleImageClick(img)"
-          />
-          <el-button 
-            type="text" 
-            size="small" 
-            class="delete-img-btn"
-            @click.stop="removeImage(index)"
-          >
-            <el-icon><Delete /></el-icon>
-          </el-button>
-        </div>
-      </div>
-      
-      <!-- 隐藏的文件输入框 -->
-      <input
-        ref="fileInput"
-        type="file"
-        accept="image/*"
-        style="display: none"
-        @change="handleFileChange"
-      />
-    </div>
-
-      <!-- 输入区域:输入框和发送按钮 -->
-      <div class="input-wrapper">
-        <!-- 文本输入框 -->
-        <el-input 
-          v-model="prompt" 
-          type="textarea" 
-          :rows="3" 
-          :placeholder="getPlaceholder"
-          @paste="handlePaste"
-          class="chat-input"
-        />
-        
-        <!-- 右侧提交按钮 -->
-        <el-button type="primary" class="send-btn" @click="handleSubmit" :loading="uploading">
-          提交
-        </el-button>
-      </div>
-    </div>
-  </div>
-
-   <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-form-item>
-    </el-form>
-
-  <!-- 表格展示 -->
-    <el-table
-      ref="multipleTable"
-      style="width: 100%; height: 62vh;"
-      :row-style="{ height: '20px' }"
-      :header-cell-style="{ padding: '0px' }"
-      :cell-style="{ padding: '0px' }"
-      :header-row-style="{ height: '20px' }"
-      border tooltip-effect="dark"
-      :data="tableData1"
-      row-key="ID"
-      highlight-current-row
-      :cell-class-name="tableDataCellClass"
-      @selection-change="SelectionChange"
-      @row-dblclick="onRowDblClick"
-      :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="chinese_description" width="300" />
-      <el-table-column label="第二段" prop="english_description" width="300" />
-      <el-table-column label="图片名称" prop="img_name" width="300" />
-      <el-table-column label="原图" width="120">
-        <template #default="{ row }">
-          <el-image
-            :src="formatImageUrl(row.old_image_url)"
-            :preview-src-list="[formatImageUrl(row.old_image_url)]"
-            style="width: 90px; height: 70px;"
-            fit="contain"
-            preview-teleported
-          />
-        </template>
-      </el-table-column>
-	  
-	  
-	  <el-table-column
-	    v-if="tableData1.some(row => row.model === 'black-forest-labs/FLUX.1-kontext-pro')" 
-	    label="FLUX.1" 
-	    width="120">
-	    <template #default="{ row }">
-	      <el-image
-	        v-if="row.model === 'black-forest-labs/FLUX.1-kontext-pro'"
-	        :src="formatImageUrl(row.new_image_url)"
-	        :preview-src-list="[formatImageUrl(row.new_image_url)]"
-	        style="width: 90px; height: 70px;"
-	        fit="contain"
-	        preview-teleported
-	      />
-	      <span v-else>-</span>
-	    </template>
-	  </el-table-column>
-	  <el-table-column
-	    v-if="tableData1.some(row => row.model === 'dall-e-3')" 
-	    label="dall-e-3" 
-	    width="120">
-	    <template #default="{ row }">
-	      <el-image
-	        v-if="row.model === 'dall-e-3'"
-	        :src="formatImageUrl(row.new_image_url)"
-	        :preview-src-list="[formatImageUrl(row.new_image_url)]"
-	        style="width: 90px; height: 70px;"
-	        fit="contain"
-	        preview-teleported
-	      />
-	      <span v-else>-</span>
-	    </template>
-	  </el-table-column>
-	  <el-table-column 
-	    v-if="tableData1.some(row => row.model === 'gpt-image-1')" 
-	    label="gpt-image-1" 
-	    width="120">
-	    <template #default="{ row }">
-	      <el-image
-	        v-if="row.model === 'gpt-image-1'"
-	        :src="formatImageUrl(row.new_image_url)"
-	        :preview-src-list="[formatImageUrl(row.new_image_url)]"
-	        style="width: 90px; height: 70px;"
-	        fit="contain"
-	        preview-teleported
-	      />
-	      <span v-else>-</span>
-	    </template>
-	  </el-table-column>
-	  <el-table-column
-	    v-if="tableData1.some(row => row.model === 'MID_JOURNEY')" 
-	    label="MID_JOURNEY" 
-	    width="130">
-	    <template #default="{ row }">
-	      <el-image
-	        v-if="row.model === 'MID_JOURNEY'"
-	        :src="`https://chatapi.onechats.ai/mj/image/${row.taskId}`"  
-	        :preview-src-list="[`https://chatapi.onechats.ai/mj/image/${row.taskId}`]"
-	        style="width: 90px; height: 70px;"
-	        fit="contain"
-	        preview-teleported
-	      />
-	      <span v-else>-</span>
-	    </template>
-	  </el-table-column>
-      
-      <el-table-column label="图生图预览" width="120">
-        <template #default="{ row }">
-          <el-image
-            :src="formatImageUrl(row.imgtoimg_url)"
-            :preview-src-list="[formatImageUrl(row.imgtoimg_url)]"
-            style="width: 90px; height: 70px;"
-            fit="contain"
-            preview-teleported
-          />
-        </template>
-      </el-table-column>
-    </el-table>
-
-    <!-- 分页 -->
-    <div class="gva-pagination">
-      <el-pagination
-        @size-change="handleSizeChange"
-        @current-change="handleCurrentChange"
-        :current-page="page"
-        :page-sizes="[10, 30, 50, 100]"
-        :page-size="pageSize"
-        layout="total, sizes, prev, pager, next, jumper"
-        :total="total"
-      />
-    </div>
-</template>
-
-<script setup>
-import { ref, computed, onMounted } from 'vue'
-import { Delete, ZoomIn, CirclePlus, VideoPlay, Picture } from '@element-plus/icons-vue'
-import { ElMessage } from 'element-plus'
-import { useUserStore } from '@/pinia/modules/user'
-import { isImageMime } from '@/utils/image'
-import service from '@/utils/request'
-import {imageToText,getTable, Template_ids,txttoimg_moxing,GetHttpUrl,txttoimg_update, getSide} from '@/api/mes/job'
-
-//获取登录用户信息
-const userStore = useUserStore()
-const _username = ref('')
-_username.value = userStore.userInfo.userName + '/' + userStore.userInfo.nickName
-console.log('获取用户信息',_username.value)
-console.log('获取用户名称',userStore.userInfo.nickName)
-
-//获取服务器地址
-const baseUrl = ref('')
-const port = ref('')
-const full_url = ref('')
-// 从接口获取服务器地址
-const fetchServerUrl = async () => {
-  try {
-    const res = await GetHttpUrl()
-    if (res.code === 0 && res.data && res.data.full_url) {
-      full_url.value = res.data.full_url
-      baseUrl.value = res.data.baseUrl
-      port.value = res.data.port
-	  console.log('获取服务器地址',full_url.value)
-	  console.log('IP地址',baseUrl.value)
-	  console.log('端口',port.value)
-    }
-  } catch (error) {
-    console.error('获取服务器地址失败:', error)
-  }
-}
-fetchServerUrl();
-
-const tableData1 = ref([])
-const selectedFolder = ref('')
-const folderList = ref([])
-
-const getTableData = async () => {
-    const res = await getTable({
-      search: searchInfo.value,
-      limit: pageSize.value,
-      page: page.value,
-      folder: selectedFolder.value
-    })
-    tableData1.value = res.data.list
-    total.value = res.data.total
-    
-    // 更新文件夹列表
-    if (res.data.folder) {
-      folderList.value = res.data.folder
-    }
-
-    // const res_Template = await Template_ids({path:row['old_image_url']});
-    // height.value = res_Template.data.height
-    // width.value = res_Template.data.width
-}
-getTableData()
-
-// 处理文件夹选择
-const handleFolderCommand = (command) => {
-  selectedFolder.value = command
-  onSubmit()
-}
-
-// 消息内容
-const prompt = ref('')
-// 已上传图片列表
-const uploadedImages = ref([])
-// 文件输入框引用
-const fileInput = ref(null)
-// 上传状态
-const uploading = ref(false)
-// 激活的标签页
-const activeTab = ref('image')
-// 生成类型
-const generationType = computed(() => activeTab.value === 'video' ? '视频生成' : '图片生成')
-// API路径
-const path = ref(import.meta.env.VITE_BASE_API)
-
-// 触发文件上传
-const triggerUpload = () => {
-  fileInput.value?.click()
-}
-
-// 处理文件选择
-const handleFileChange = (e) => {
-  const file = e.target.files[0]
-  if (file) {
-    processImageFile(file)
-  }
-  // 清空文件输入
-  if (fileInput.value) {
-    fileInput.value.value = ''
-  }
-}
-
-// 处理粘贴事件
-const handlePaste = (e) => {
-  console.log('粘贴事件触发')
-  const items = e.clipboardData.items
-  console.log('剪贴板项目:', items)
-  
-  for (let i = 0; i < items.length; i++) {
-    console.log('项目', i, '类型:', items[i].type)
-    if (items[i].type.indexOf('image') !== -1) {
-      const file = items[i].getAsFile()
-      console.log('获取到图片文件:', file)
-      processImageFile(file)
-      break
-    }
-  }
-}
-
-// 处理图片文件
-const processImageFile = (file) => {
-  // 验证文件类型
-  if (!isImageMime(file.type)) {
-    ElMessage.error('请选择JPG、PNG或WebP格式的图片')
-    return
-  }
-  
-  // 验证文件大小(限制5MB)
-  const maxSize = 5 * 1024 * 1024
-  if (file.size > maxSize) {
-    ElMessage.error('图片大小不能超过5MB')
-    return
-  }
-  
-  // 读取文件并添加到上传列表
-  const reader = new FileReader()
-  reader.onload = (e) => {
-    const imageUrl = e.target.result
-    // 检查图片是否已存在
-    const isDuplicate = uploadedImages.value.some(img => img.url === imageUrl)
-    if (!isDuplicate) {
-      uploadedImages.value.push({
-        url: imageUrl,
-        file: file
-      })
-    }
-  }
-  reader.readAsDataURL(file)
-}
-
-// 删除图片(从已上传列表)
-const removeImage = (index) => {
-  uploadedImages.value.splice(index, 1)
-}
-
-// 处理图片点击(放大查看)
-const handleImageClick = (img) => {
-  // 创建自定义图片预览
-  const previewContainer = document.createElement('div')
-  previewContainer.className = 'custom-image-preview'
-  previewContainer.style.cssText = `
-    position: fixed;
-    top: 0;
-    left: 0;
-    right: 0;
-    bottom: 0;
-    background: rgba(0, 0, 0, 0.9);
-    z-index: 9999;
-    display: flex;
-    align-items: center;
-    justify-content: center;
-  `
-  
-  // 添加图片
-  const previewImage = document.createElement('img')
-  previewImage.src = img.url
-  previewImage.style.cssText = `
-    max-width: 90%;
-    max-height: 90%;
-    object-fit: contain;
-  `
-  
-  // 添加关闭按钮
-  const closeButton = document.createElement('button')
-  closeButton.innerHTML = '&times;'
-  closeButton.style.cssText = `
-    position: absolute;
-    top: 20px;
-    right: 20px;
-    font-size: 30px;
-    color: white;
-    background: transparent;
-    border: none;
-    cursor: pointer;
-    padding: 0;
-    width: 30px;
-    height: 30px;
-    display: flex;
-    align-items: center;
-    justify-content: center;
-  `
-  
-  // 组装预览组件
-  previewContainer.appendChild(previewImage)
-  previewContainer.appendChild(closeButton)
-  document.body.appendChild(previewContainer)
-  
-  // 关闭预览的处理
-  const closePreview = () => {
-    document.body.removeChild(previewContainer)
-  }
-  
-  closeButton.addEventListener('click', closePreview)
-  previewContainer.addEventListener('click', (e) => {
-    if (e.target === previewContainer) {
-      closePreview()
-    }
-  })
-  
-  // ESC键关闭
-  const handleEscKey = (e) => {
-    if (e.key === 'Escape') {
-      closePreview()
-      document.removeEventListener('keydown', handleEscKey)
-    }
-  }
-  document.addEventListener('keydown', handleEscKey)
-}
-
-
-// 提交处理
-const handleSubmit = async () => {
-  if (!prompt.value.trim() && uploadedImages.value.length === 0) {
-    ElMessage.warning('请输入消息或上传图片')
-    return
-  }
-  
-  try {
-    uploading.value = true
-    
-    // 准备提交数据
-    let status_val = ''
-    
-    // 根据标签页和上传内容确定生成类型
-    if (activeTab.value === 'image') {
-      // 图片生成
-      status_val = uploadedImages.value.length > 0 ? '图生图' : '文生图'
-    } else {
-      // 视频生成
-      status_val = uploadedImages.value.length > 0 ? '图生视频' : '文生视频'
-    }
-    
-    const payload = {
-      status_val: status_val,
-      batch: uploadedImages.value.map(item => item.file), // 图片数组
-      prompt: prompt.value
-    }
-    
-    // 打印调试区域
-    console.log(payload);
-    await new Promise(resolve => setTimeout(resolve, 2000));
-    uploading.value = false;
-    return;
-
-    const res = await imageToText(payload)
-    
-    // 处理接口返回结果
-    if (res.code === 0) {
-      ElMessage.success('提交成功')
-      console.log('接口返回结果:', res)
-      
-      // 清空输入和图片列表
-      prompt.value = ''
-      uploadedImages.value = []
-    } else {
-      ElMessage.error(res.msg || '提交失败')
-    }
-  } catch (error) {
-    console.error('提交失败:', error)
-    ElMessage.error('提交失败,请稍后重试')
-  } finally {
-    uploading.value = false
-  }
-}
-
-// 计算预览列表
-const previewList = computed(() => {
-  return uploadedImages.value.map(item => item.url)
-})
-
-// 计算已选图片数量
-const selectedImagesCount = computed(() => {
-  return uploadedImages.value.length
-})
-
-// 根据生成类型获取占位符
-const getPlaceholder = computed(() => {
-  if (generationType.value === '视频生成') {
-    return '输入视频生成的提示词'
-  } else {
-    return '输入图片生成的提示词'
-  }
-})
-
-// 将DataURL转换为File对象
-const dataURLtoFile = (dataurl, filename) => {
-  const arr = dataurl.split(',')
-  const mime = arr[0].match(/:(.*?);/)[1]
-  const bstr = atob(arr[1])
-  let n = bstr.length
-  const u8arr = new Uint8Array(n)
-  while (n--) {
-    u8arr[n] = bstr.charCodeAt(n)
-  }
-  return new File([u8arr], filename, { type: mime })
-}
-
-
-</script>
-
-<style scoped>
-/* 生成类型选项卡 */
-.generation-tabs {
-  margin-bottom: 10px;
-  width: 100%;
-}
-
-.generation-tabs :deep(.el-tabs__header) {
-  margin: 0;
-}
-
-.generation-tabs :deep(.el-tabs__nav-wrap) {
-  margin: 0;
-}
-
-.generation-tabs :deep(.el-tabs__nav) {
-  background: transparent;
-}
-
-.generation-tabs :deep(.el-tabs__item) {
-  padding: 0 20px;
-  height: 40px;
-  line-height: 40px;
-  font-size: 14px;
-  color: #606266;
-  border: none;
-  border-radius: 0;
-  transition: all 0.3s ease;
-}
-
-.generation-tabs :deep(.el-tabs__item.is-active) {
-  color: #409eff;
-  font-weight: 500;
-  background: transparent;
-}
-
-.generation-tabs :deep(.el-tabs__active-bar) {
-  background-color: #409eff;
-  height: 2px;
-}
-
-.generation-tabs :deep(.tab-label) {
-  display: flex;
-  align-items: center;
-  gap: 6px;
-}
-
-.generation-tabs :deep(.tab-icon) {
-  font-size: 16px;
-}
-
-/* 聊天界面样式 */
-.chat-interface {
-  display: flex;
-  flex-direction: column;
-  width: 70%;
-  margin: 0 auto;
-  padding: 20px;
-}
-
-/* 输入区域容器 */
-.input-container {
-  display: flex;
-  flex-direction: column;
-  border: 1px solid #e4e7ed;
-  border-radius: 12px;
-  overflow: hidden;
-  width: 100%;
-  box-shadow: 0 2px 12px rgba(0, 0, 0, 0.06);
-  background-color: #fff;
-}
-
-/* 上传图片列表容器 */
-.uploaded-images-container {
-  display: flex;
-  flex-wrap: wrap;
-  gap: 8px;
-  padding: 0;
-  min-height: auto;
-  max-height: 150px;
-  overflow-y: auto;
-}
-
-/* 单张图片样式 */
-.message-image {
-  position: relative;
-  width: 60px;
-  height: 60px;
-  border-radius: 4px;
-  overflow: hidden;
-  cursor: pointer;
-  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
-  transition: all 0.3s ease;
-}
-
-.message-image:hover {
-  transform: translateY(-1px);
-  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.15);
-}
-
-.message-image :deep(.el-image) {
-  width: 100%;
-  height: 100%;
-  object-fit: cover;
-  cursor: zoom-in;
-}
-
-/* 删除按钮 */
-.delete-img-btn {
-  position: absolute;
-  top: 2px;
-  right: 2px;
-  background-color: rgba(255, 255, 255, 0.8);
-  border-radius: 50%;
-  width: 20px;
-  height: 20px;
-  padding: 0;
-  display: flex;
-  justify-content: center;
-  align-items: center;
-  opacity: 0;
-  transition: opacity 0.3s ease;
-  font-size: 12px;
-  cursor: pointer;
-}
-
-/* 图片选择对话框样式 */
-.image-selector {
-  display: flex;
-  flex-direction: column;
-  gap: 15px;
-  height: 100%;
-  max-height: 600px;
-  overflow-y: auto;
-}
-
-.image-upload-area {
-  display: flex;
-  justify-content: center;
-  align-items: center;
-  height: 240px;
-  padding: 15px;
-  border: 1px dashed #dcdfe6;
-  border-radius: 8px;
-  background-color: #fafafa;
-  cursor: pointer;
-  transition: all 0.3s ease;
-}
-
-.upload-box {
-  display: flex;
-  flex-direction: column;
-  gap: 8px;
-  justify-content: center;
-  align-items: center;
-  height: 100%;
-}
-
-.upload-icon {
-  font-size: 24px;
-  color: #909399;
-  margin-bottom: 8px;
-}
-
-.upload-text {
-  font-size: 14px;
-  color: #606266;
-}
-
-.upload-hint {
-  font-size: 12px;
-  color: #909399;
-  margin-top: 4px;
-}
-
-.image-upload-area:hover {
-  border-color: #409eff;
-  color: #409eff;
-  background-color: #ecf5ff;
-}
-
-
-.image-upload-area:hover {
-  border-color: #409eff;
-  background-color: #ecf5ff;
-}
-
-.upload-box {
-  display: flex;
-  align-items: center;
-  gap: 12px;
-  color: #909399;
-}
-
-.upload-icon {
-  font-size: 24px;
-  color: #c0c4cc;
-}
-
-.upload-box span {
-  font-size: 14px;
-  font-weight: 500;
-}
-
-/* 移除AI绘图文字相关样式 */
-.image-overlay {
-  display: none;
-}
-
-.image-tags {
-  display: none;
-}
-
-/* 图片预览容器 */
-.image-preview-container {
-  display: flex;
-  justify-content: center;
-  align-items: center;
-  padding: 20px;
-  max-height: 70vh;
-  overflow: auto;
-}
-
-.full-size-image {
-  max-width: 100%;
-  max-height: 100%;
-  object-fit: contain;
-  border-radius: 4px;
-}
-
-.message-image:hover .delete-img-btn {
-  opacity: 1;
-}
-
-/* 上传区域:上传按钮和已上传图片水平排列 */
-.upload-area {
-  display: flex;
-  gap: 10px;
-  background-color: #fafafa;
-  border-bottom: 1px solid #e4e7ed;
-  margin-bottom: 0;
-  padding: 16px;
-}
-
-/* 上传按钮 */
-.add-btn {
-  display: flex;
-  align-items: center;
-  justify-content: center;
-  width: 60px;
-  height: 60px;
-  border: 2px dashed #dcdfe6;
-  border-radius: 8px;
-  background-color: #fff;
-  color: #909399;
-  font-size: 24px;
-  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
-}
-
-.add-btn:hover {
-  border-color: #409eff;
-  color: #409eff;
-  background-color: #ecf5ff;
-  box-shadow: 0 4px 12px rgba(64, 158, 255, 0.15);
-}
-
-.add-btn span {
-  display: none;
-}
-
-/* 已上传图片容器 */
-.uploaded-images-container {
-  display: flex;
-  gap: 10px;
-  flex-wrap: wrap;
-  align-items: center;
-}
-
-/* 消息图片 */
-.message-image {
-  position: relative;
-  width: 60px;
-  height: 60px;
-  border-radius: 8px;
-  overflow: hidden;
-  cursor: pointer;
-  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
-}
-
-.message-image .el-image {
-  width: 100%;
-  height: 100%;
-  border-radius: 8px;
-}
-
-.input-wrapper {
-  display: flex;
-  gap: 12px;
-  align-items: flex-end;
-  padding: 16px;
-  background-color: #fff;
-}
-
-.add-btn :deep(.el-icon) {
-  font-size: 24px;
-  margin-bottom: 4px;
-}
-
-/* 聊天输入框 */
-.chat-input {
-  flex: 1;
-  border: none;
-  border-radius: 4px;
-  resize: none;
-  outline: none;
-  font-size: 14px;
-  line-height: 1.5;
-}
-
-:deep(.el-textarea) {
-  width: 100%;
-  margin: 0;
-}
-
-:deep(.el-textarea__inner) {
-  border: 1px solid #e4e7ed;
-  border-radius: 8px;
-  resize: none;
-  padding: 12px 16px;
-  font-size: 14px;
-  line-height: 1.5;
-  background-color: #fff;
-  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
-  min-height: 80px;
-  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
-}
-
-:deep(.el-textarea__inner:focus) {
-  border-color: #409eff;
-  box-shadow: 0 0 0 2px rgba(64, 158, 255, 0.2);
-  outline: none;
-}
-
-/* 发送按钮 */
-.send-btn {
-  border-radius: 8px;
-  padding: 8px 16px;
-  display: flex;
-  justify-content: center;
-  align-items: center;
-  font-size: 14px;
-  background-color: #409eff;
-  border-color: #409eff;
-  transition: all 0.3s cubic-bezier(0.4, 0.0, 0.2, 1);
-  align-self: flex-end;
-  box-shadow: 0 2px 8px rgba(64, 158, 255, 0.2);
-}
-
-.send-btn:hover {
-  background-color: #66b1ff;
-  border-color: #66b1ff;
-  transform: translateY(-1px);
-  box-shadow: 0 4px 12px rgba(64, 158, 255, 0.3);
-}
-
-/* 响应式设计 */
-@media (max-width: 768px) {
-  /* 输入容器响应式 */
-  .input-container {
-    border-radius: 8px;
-  }
-  
-  /* 上传区域响应式 */
-  .upload-area {
-    padding: 12px;
-    gap: 8px;
-  }
-  
-  .add-btn {
-    width: 50px;
-    height: 50px;
-    font-size: 20px;
-  }
-  
-  .message-image {
-    width: 50px;
-    height: 50px;
-  }
-  
-  /* 输入区域响应式 */
-  .input-wrapper {
-    flex-direction: column;
-    align-items: stretch;
-    padding: 12px;
-    gap: 12px;
-  }
-  
-  .chat-input {
-    min-height: 70px;
-  }
-  
-  .send-btn {
-    width: 44px;
-    height: 44px;
-    font-size: 18px;
-  }
-}
-</style>

+ 0 - 2725
src/view/performance/QualityAssessment/Product.vue

@@ -1,2725 +0,0 @@
-<template>
-  <div>
-    <layout>
-      <layout-header>
-        <!-- 搜索区域 -->
-        <el-form inline>
-          <el-form-item>
-            <el-input v-model="searchInfo" placeholder="搜索关键字" clearable style="width: 300px;" />
-            <el-button type="primary" icon="search" @click="onSubmit" title="搜索查询">查询</el-button>
-            <el-button type="primary"  @click="onADD" >新增产品</el-button>
-          </el-form-item>
-        </el-form>
-      </layout-header>
-
-      <layout>
-        <!-- 左侧树形结构 -->
-        <template v-if="userStore.userInfo.nickName === '超级管理员'">
-        <layout-sider :resize-directions="['right']" :width="290" style="margin-right: 10px">
-          <div class="JKWTree-tree" style="height: 200px;">
-            <h3>商户名称</h3>
-            <el-tree :data="treeData" class="treecolor"   @node-click="handleNodeClick"></el-tree>
-          </div>
-        </layout-sider>
-      </template>
-        <!-- 右侧区域 -->
-        <layout-content>
-          <el-main style="padding: 0;">
-            <div class="gva-table-box">
-              <!-- 表格展示 -->
-              <el-table
-                ref="multipleTable"
-                style="width: 100%; height: 62vh;"
-                :row-style="{ height: '20px' }"
-                :header-cell-style="{ padding: '0px' }"
-                :cell-style="{ padding: '0px' }"
-                :header-row-style="{ height: '20px' }"
-                border tooltip-effect="dark"
-                :data="tableData1"
-                row-key="ID"
-                highlight-current-row
-                :cell-class-name="tableDataCellClass"
-                @selection-change="SelectionChange"
-                @row-dblclick="onRowDblClick"
-                :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" />
-                <el-table-column label="产品编码" prop="产品编码" width="300" />
-                <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>
-                </el-table-column>
-                <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>
-                  </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"
-                  @current-change="handleCurrentChange"
-                  :current-page="page"
-                  :page-sizes="[10, 30, 50, 100]"
-                  :page-size="pageSize"
-                  layout="total, sizes, prev, pager, next, jumper"
-                  :total="total"/>
-              </div>
-            </div>
-          </el-main>
-        </layout-content>
-      </layout>
-    </layout>
-
-<el-dialog  v-model="editDialogVisible"  title=""  fullscreen :modal="true" :show-close="false" @close="handleDialogClose">
-  <!-- 关闭按钮 -->
-  <div style="position: absolute; top: 10px; right: 20px; z-index: 1000;">
-    <el-button type="danger" size="large" @click="editDialogVisible = false">
-      <el-icon><Close /></el-icon>关闭
-    </el-button>
-  </div>
-  <div class="image-edit-container">
-    <!-- 左侧:原图新图 + 输入框 -->
-    <div class="left-column">
-      <!-- 标题 -->
-      <div style="font-size: 18px; font-weight: bold; color: white; margin-bottom: 10px; background-color: #404040; padding: 10px; border-radius: 4px; text-align: center;">②出图</div>
-        <!-- 图片对比区域 -->
-      <div class="image-comparison-section">
-        <!-- 原图区域 -->
-        <div class="image-preview" style="flex: 1; min-width: 120px; display: flex; flex-direction: column; align-items: center;">
-          <h3 style="margin-top: 0; margin-bottom: 8px; font-size: 14px; font-weight: bold; color: #303133; align-self: flex-start;">上传商品白底图</h3>
-          <div v-if="editFormData.original_image_url" class="upload-image-box">
-            <el-image
-              :src="formatImageUrl(editFormData.original_image_url)"
-              :preview-src-list="[formatImageUrl(editFormData.original_image_url)]"
-              style="width: 100%; height: 100%;"
-              fit="contain"
-              preview-teleported/>
-          </div>
-          <div v-else class="image-placeholder image-placeholder-small">
-            <el-icon :size="30"><Picture /></el-icon>
-            <span style="margin-top: 5px; font-size: 10px;">暂无原图</span>
-          </div>
-        </div>
-
-        <!-- 商品图例、案例:右侧一列,与图片等高上下对齐,不用固定 margin 避免小屏跑偏 -->
-        <div class="case-links-column">
-          <el-button type="text" size="small" @click="toggleProductExample" class="case-link-btn">
-            <template #icon>
-              <el-icon :size="16">
-                <component :is="productExampleVisible ? 'ArrowDown' : 'ArrowRight'" />
-              </el-icon>
-            </template>
-            商品图例
-          </el-button>
-          <el-button type="text" size="small" @click="toggleCaseExample" class="case-link-btn">
-            <template #icon>
-              <el-icon :size="16">
-                <component :is="caseExampleVisible ? 'ArrowDown' : 'ArrowRight'" />
-              </el-icon>
-            </template>
-            案例
-          </el-button>
-        </div>
-      </div>
-          
-    <!-- 输入框区域 -->
-    <div class="edit-section" style="border: 1px solid #e4e7ed; border-radius: 4px; display: flex; flex-direction: column; position: relative;">
-        <el-form :model="editFormData" label-width="80px" style="flex: 1; display: flex; flex-direction: column; min-height: 0;">
-            <el-input
-              type="textarea"
-              v-model="editFormData.chinese_description"
-              :rows="14"
-              placeholder="点击右侧模板图片可自动填充描述内容"
-              show-word-limit
-              maxlength="500"
-              style="width: 100%; resize: none;"
-              :disabled="loadingStatus"
-            />
-        </el-form>
-        <!-- 加载遮罩 -->
-        <div v-if="loadingStatus" style="position: absolute; top: 0; left: 0; right: 0; bottom: 0; background: rgba(255, 255, 255, 0.8); display: flex; align-items: center; justify-content: center; border-radius: 4px; z-index: 10;">
-            <el-icon style="font-size: 24px; color: #409eff;"><Loading /></el-icon>
-            <span style="margin-left: 10px; color: #409eff;">正在生成中...</span>
-        </div>
-        
-        <!-- 按钮放在表单下方 -->
-        <div style="margin-top: 15px; padding-top: 15px; border-top: 1px solid #e4e7ed;">
-        <!-- 尺寸选择区域 -->
-        <div style="margin-bottom: 15px;">
-          <div style="display: flex; gap: 15px; flex-wrap: wrap; align-items: center;">
-            <div v-for="ratio in [ '1:1','4:3','3:2','2:3','16:9']" :key="ratio" style="display: flex; align-items: center; gap: 5px;">
-              <el-radio v-model="selectedSize" :label="ratio" @change="handleSizeChange" border style="border-radius: 2px;">
-                {{ ratio }}
-              </el-radio>
-            </div>
-            <!-- <div style="display: flex; align-items: center; gap: 5px;">
-              <el-radio v-model="selectedSize" label="custom" @change="handleSizeChange" border style="border-radius: 2px;">
-                自由尺寸
-              </el-radio>
-            </div> -->
-          </div>
-          
-          <!-- 自由尺寸的像素输入 -->
-          <div v-if="selectedSize === 'custom'" style="display: flex; align-items: center; gap: 12px; margin-top: 15px; padding-top: 10px; border-top: 1px dashed #ebeef5;">
-            <span style="font-size: 14px; color: #606266; white-space: nowrap;">自定义尺寸:</span>
-            <el-input 
-              v-model="customWidth" 
-              size="small" 
-              style="width: 100px;" 
-              placeholder="宽度" 
-              @input="validateCustomSize">
-              <template #append>px</template>
-            </el-input>
-            <span style="color: #909399;">×</span>
-            <el-input 
-              v-model="customHeight" 
-              size="small" 
-              style="width: 100px;" 
-              placeholder="高度" 
-              @input="validateCustomSize">
-              <template #append>px</template>
-            </el-input>
-          </div>
-          
-          <!-- 显示当前尺寸信息 -->
-          <div v-if="selectedSize !== 'custom'" style="font-size: 13px; color: #909399; margin-top: 10px; padding-top: 10px; border-top: 1px dashed #ebeef5;">
-            当前尺寸: {{ getSizeInfo(selectedSize) }}
-          </div>
-        </div>
-
-        <!-- 操作按钮 -->
-        <div style="display: flex; justify-content: flex-end; gap: 12px;">
-          <!-- <el-button size="medium" @click="clearInput">清空</el-button> -->
-          <el-button size="medium" type="success" @click="optimizeContent" :loading="loadingStatus || pollStatus === 'optimizing'">
-            {{ loadingStatus || pollStatus === 'optimizing' ? '正在生成中' : '扩写提示词' }} <span style="margin-left: 8px;">⚡ 25 <span style="font-size: 12px;"></span></span>
-            </el-button>
-          <el-button size="medium" type="primary" @click="generateImage" :loading="loadingStatus || pollStatus === 'polling'">
-            {{ loadingStatus || pollStatus === 'polling' ? '正在生成中' : '立即生成' }} <span style="margin-left: 8px;">⚡ 150 <span style="font-size: 12px;"></span></span>
-          </el-button>
-        </div>
-      </div>
-    </div>
-    </div>
-    
-   <!-- 中间:产品信息和历史记录(保证两侧边框可见,不与其他列重叠) -->
-<div class="middle-column">
-  <!-- 历史记录覆盖层 -->
-  <div v-if="showHistoryPanel" style="position: absolute; top: 0; left: 0; right: 0; height: 100%; background: #ffffff; border-radius: 0; z-index: 1000; display: flex; justify-content: center; align-items: flex-start; box-shadow: 4px 0 20px rgba(0,0,0,0.15); border-right: 1px solid #e4e7ed;">
-    <div style="width: 95%; height: 100%; overflow-y: auto;">
-      <div style="padding: 20px;">
-        <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; padding-bottom: 10px; border-bottom: 1px solid #e4e7ed;">
-          <h3 style="margin: 0; font-size: 16px; font-weight: bold; color: #303133;">历史记录</h3>
-          <el-button type="danger" size="small" @click="toggleHistoryPanel">
-            <el-icon><Close /></el-icon>关闭
-          </el-button>
-        </div>
-        
-        <!-- 模板分类树 -->
-        <el-tree
-          :data="templateTreeData"
-          node-key="id"
-          default-expand-all
-          @node-click="handleTemplateTreeClick"
-          style="margin-bottom: 20px;"
-        >
-          <template #default="{ node, data }">
-            <span>{{ data.label }}</span>
-            <span style="margin-left: 10px; font-size: 12px; color: #909399;">({{ data.count }}张)</span>
-          </template>
-        </el-tree>
-        
-        <!-- 选中模板的历史图片 -->
-        <div>
-          <h5 style="margin: 0 0 10px 0; font-size: 13px; font-weight: bold;">
-            {{ currentTemplateName || '历史图片' }}
-          </h5>
-          <div class="history-images-list" style="display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 15px;">
-            <div v-for="(image, index) in filteredImages" :key="index" class="history-image-item" style="border: 1px solid #e4e7ed; border-radius: 4px; overflow: hidden; padding: 10px;">
-              <div style="height: 120px; display: flex; justify-content: center; align-items: center; background: #f9f9f9; border-radius: 4px; overflow: hidden;">
-                <el-image
-                  :src="formatImageUrl(image.url)"
-                  :preview-src-list="[formatImageUrl(image.url)]"
-                  style="width: 100%; height: 100%;"
-                  fit="contain"
-                  preview-teleported
-                />
-              </div>
-              <div style="margin-top: 10px; font-size: 12px; color: #606266; line-height: 1.4; height: 50px; overflow: hidden;">
-                {{ image.product_content || '' }}
-              </div>
-              <div style="margin-top: 5px; font-size: 11px; color: #909399; text-align: right;">
-                {{ image.createTime || '' }}
-              </div>
-            </div>
-            <div v-if="filteredImages.length === 0" style="text-align: center; padding: 40px; color: #909399; font-size: 14px; grid-column: 1 / -1;">
-              暂无历史图片
-            </div>
-          </div>
-        </div>
-      </div>
-    </div>
-  </div>
- <!-- 标题 -->
- <div style="font-size: 18px; font-weight: bold; color: white; margin-bottom: 15px; background-color: #404040; padding: 10px; border-radius: 4px; text-align: center; display: flex; justify-content: space-between; align-items: center;">
-    <span>③效果图</span>
-    <el-button type="primary" size="small" @click="toggleHistoryPanel">
-      {{ showHistoryPanel ? '隐藏历史记录' : '显示历史记录' }}
-    </el-button>
-  </div>
-  
-  <!-- 主内容区域 -->
-  <div style="display: flex; height: calc(100% - 90px);">
-    <!-- 左侧:历史记录面板 (已移至覆盖层) -->
-    
-    <!-- 右侧:原始内容 -->
-    <div class="original-content" style="flex: 1; overflow-y: auto; min-width: 0;">
-      <!-- 商品图例覆盖层 -->
-      <div v-if="productExampleVisible" style="position: absolute; top: 0; left: 0; right: 0; height: 100%; background: #ffffff; border-radius: 0; z-index: 1000; display: flex; justify-content: center; align-items: flex-start; box-shadow: 4px 0 20px rgba(0,0,0,0.15); border-right: 1px solid #e4e7ed;">
-        <div style="width: 95%; height: 100%; overflow-y: auto;">
-          <div style="padding: 20px;">
-            <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; padding-bottom: 10px; border-bottom: 1px solid #e4e7ed;">
-              <h3 style="margin: 0; font-size: 16px; font-weight: bold; color: #303133;">商品图例</h3>
-              <el-button type="text" size="small" @click="toggleProductExample">
-                <el-icon><Close /></el-icon>
-              </el-button>
-            </div>
-            
-            <p style="margin: 0 0 20px 0; color: #606266; line-height: 1.5; font-size: 14px;">
-              建议上传商品单一、完整清晰、占据画面中心的白底图,否则可能会影响商品识别效果和生成的背景图质量。
-            </p>
-            <!-- 商品图例对比 -->
-            <div style="margin-bottom: 20px;">
-              <div style="display: flex; gap: 15px;">
-                <!-- 正确示例 -->
-                <div style="flex: 1; background: white; padding: 15px; border-radius: 6px; box-shadow: 0 2px 4px rgba(0,0,0,0.05); border: 1px solid #e4e7ed;">
-                  <div style="display: flex; align-items: center; margin-bottom: 10px;">
-                    <el-icon :size="14" style="color: #67c23a; margin-right: 8px;"><SuccessFilled /></el-icon>
-                    <span style="font-weight: 500; color: #303133; font-size: 13px;">商品单一</span>
-                  </div>
-                  <div style="height: 120px; display: flex; justify-content: center; align-items: center; background: #f9f9f9; border-radius: 4px; overflow: hidden; border: 1px solid #e4e7ed;">
-                    <el-image
-                      :src="`/src/assets/ai案例图/001.png`"
-                      style="width: 100%; height: 100%;"
-                      fit="contain"
-                    >
-                      <template #error>
-                        <div style="width: 100%; height: 100%; display: flex; justify-content: center; align-items: center; color: #909399; font-size: 12px;">
-                          <span>图片占位</span>
-                        </div>
-                      </template>
-                    </el-image>
-                  </div>
-                </div>
-                
-                <!-- 错误示例 -->
-                <div style="flex: 1; background: white; padding: 15px; border-radius: 6px; box-shadow: 0 2px 4px rgba(0,0,0,0.05); border: 1px solid #e4e7ed;">
-                  <div style="display: flex; align-items: center; margin-bottom: 10px;">
-                    <el-icon :size="14" style="color: #f56c6c; margin-right: 8px;"><Close /></el-icon>
-                    <span style="font-weight: 500; color: #303133; font-size: 13px;">画面包含多件商品</span>
-                  </div>
-                  <div style="height: 120px; display: flex; justify-content: center; align-items: center; background: #f9f9f9; border-radius: 4px; overflow: hidden; border: 1px solid #e4e7ed;">
-                    <el-image
-                      :src="`/src/assets/ai案例图/002.png`"
-                      style="width: 100%; height: 100%;"
-                      fit="contain"
-                    >
-                      <template #error>
-                        <div style="width: 100%; height: 100%; display: flex; justify-content: center; align-items: center; color: #909399; font-size: 12px;">
-                          <span>图片占位</span>
-                        </div>
-                      </template>
-                    </el-image>
-                  </div>
-                </div>
-              </div>
-            </div>
-
-            <div style="margin-bottom: 20px;">
-              <div style="display: flex; gap: 15px;">
-                <!-- 正确示例 -->
-                <div style="flex: 1; background: white; padding: 15px; border-radius: 6px; box-shadow: 0 2px 4px rgba(0,0,0,0.05); border: 1px solid #e4e7ed;">
-                  <div style="display: flex; align-items: center; margin-bottom: 10px;">
-                    <el-icon :size="14" style="color: #67c23a; margin-right: 8px;"><SuccessFilled /></el-icon>
-                    <span style="font-weight: 500; color: #303133; font-size: 13px;">画面完整清晰</span>
-                  </div>
-                  <div style="height: 120px; display: flex; justify-content: center; align-items: center; background: #f9f9f9; border-radius: 4px; overflow: hidden; border: 1px solid #e4e7ed;">
-                    <el-image
-                      :src="`/src/assets/ai案例图/003.png`"
-                      style="width: 100%; height: 100%;"
-                      fit="contain"
-                    >
-                      <template #error>
-                        <div style="width: 100%; height: 100%; display: flex; justify-content: center; align-items: center; color: #909399; font-size: 12px;">
-                          <span>图片占位</span>
-                        </div>
-                      </template>
-                    </el-image>
-                  </div>
-                </div>
-                
-                <!-- 错误示例 -->
-                <div style="flex: 1; background: white; padding: 15px; border-radius: 6px; box-shadow: 0 2px 4px rgba(0,0,0,0.05); border: 1px solid #e4e7ed;">
-                  <div style="display: flex; align-items: center; margin-bottom: 10px;">
-                    <el-icon :size="14" style="color: #f56c6c; margin-right: 8px;"><Close /></el-icon>
-                    <span style="font-weight: 500; color: #303133; font-size: 13px;">商品残缺/遮挡</span>
-                  </div>
-                  <div style="height: 120px; display: flex; justify-content: center; align-items: center; background: #f9f9f9; border-radius: 4px; overflow: hidden; border: 1px solid #e4e7ed;">
-                    <el-image
-                      :src="`/src/assets/ai案例图/004.png`"
-                      style="width: 100%; height: 100%;"
-                      fit="contain"
-                    >
-                      <template #error>
-                        <div style="width: 100%; height: 100%; display: flex; justify-content: center; align-items: center; color: #909399; font-size: 12px;">
-                          <span>图片占位</span>
-                        </div>
-                      </template>
-                    </el-image>
-                  </div>
-                </div>
-              </div>
-            </div>
-
-            <div style="margin-bottom: 20px;">
-              <div style="display: flex; gap: 15px;">
-                <!-- 正确示例 -->
-                <div style="flex: 1; background: white; padding: 15px; border-radius: 6px; box-shadow: 0 2px 4px rgba(0,0,0,0.05); border: 1px solid #e4e7ed;">
-                  <div style="display: flex; align-items: center; margin-bottom: 10px;">
-                    <el-icon :size="14" style="color: #67c23a; margin-right: 8px;"><SuccessFilled /></el-icon>
-                    <span style="font-weight: 500; color: #303133; font-size: 13px;">商品占据画面中心</span>
-                  </div>
-                  <div style="height: 120px; display: flex; justify-content: center; align-items: center; background: #f9f9f9; border-radius: 4px; overflow: hidden; border: 1px solid #e4e7ed;">
-                    <el-image
-                    :src="`/src/assets/ai案例图/005.jpg`" 
-                      style="width: 100%; height: 100%;"
-                      fit="contain"
-                    >
-                      <template #error>
-                        <div style="width: 100%; height: 100%; display: flex; justify-content: center; align-items: center; color: #909399; font-size: 12px;">
-                          <span>图片占位</span>
-                        </div>
-                      </template>
-                    </el-image>
-                  </div>
-                </div>
-                
-                <!-- 错误示例 -->
-                <div style="flex: 1; background: white; padding: 15px; border-radius: 6px; box-shadow: 0 2px 4px rgba(0,0,0,0.05); border: 1px solid #e4e7ed;">
-                  <div style="display: flex; align-items: center; margin-bottom: 10px;">
-                    <el-icon :size="14" style="color: #f56c6c; margin-right: 8px;"><Close /></el-icon>
-                    <span style="font-weight: 500; color: #303133; font-size: 13px;">商铺主题不突出</span>
-                  </div>
-                  <div style="height: 120px; display: flex; justify-content: center; align-items: center; background: #f9f9f9; border-radius: 4px; overflow: hidden; border: 1px solid #e4e7ed;">
-                    <el-image
-                      :src="`/src/assets/ai案例图/006.jpg`"
-                      style="width: 100%; height: 100%;"
-                      fit="contain"
-                    >
-                      <template #error>
-                        <div style="width: 100%; height: 100%; display: flex; justify-content: center; align-items: center; color: #909399; font-size: 12px;">
-                          <span>图片占位</span>
-                        </div>
-                      </template>
-                    </el-image>
-                  </div>
-                </div>
-              </div>
-            </div>
-          </div>
-        </div>
-      </div>
-      
-      <!-- 案例覆盖层 -->
-      <div v-if="caseExampleVisible" style="position: absolute; top: 0; left: 0; right: 0; width: 100%; max-width: 600px; height: 100%; background: #ffffff; border-radius: 0; z-index: 1000; display: flex; justify-content: center; align-items: flex-start; box-shadow: 4px 0 20px rgba(0,0,0,0.15); border-right: 1px solid #e4e7ed;">
-        <div style="width: 95%; height: 100%; overflow-y: auto;">
-          <div style="padding: 20px;">
-            <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; padding-bottom: 10px; border-bottom: 1px solid #e4e7ed;">
-              <h3 style="margin: 0; font-size: 16px; font-weight: bold; color: #303133;">合成商品图例</h3>
-              <el-button type="text" size="small" @click="toggleCaseExample">
-                <el-icon><Close /></el-icon>
-              </el-button>
-            </div>
-            
-            <div style="display: flex; margin-bottom: 15px; padding: 10px 0; border-bottom: 1px solid #e4e7ed;">
-              <div style="flex: 1; font-weight: 600; color: #303133; font-size: 14px; text-align: center;">原图</div>
-              <div style="width: 40px;"></div>
-              <div style="flex: 1; font-weight: 500; color: #606266; font-size: 14px; text-align: center;">标准模式</div>
-              <div style="width: 40px;"></div>
-              <div style="flex: 1; font-weight: 500; color: #606266; font-size: 14px; text-align: center;">专业模式</div>
-            </div>
-            
-            <!-- 案例图片网格 -->
-            <div style="display: flex; flex-direction: column; gap: 15px;">
-              <!-- 案例1 -->
-              <div style="display: flex; align-items: center; gap: 10px;">
-                <div style="flex: 1; height: 80px; display: flex; justify-content: center; align-items: center; background: #f9f9f9; border-radius: 4px; overflow: hidden; border: 1px solid #e4e7ed;">
-                  <el-image
-                    :src="`/src/assets/ai案例图/007.png`"
-                    style="width: 100%; height: 100%;"
-                    fit="contain"
-                  >
-                    <template #error>
-                      <div style="width: 100%; height: 100%; display: flex; justify-content: center; align-items: center; color: #909399; font-size: 12px;">
-                        <span>图片占位</span>
-                      </div>
-                    </template>
-                  </el-image>
-                </div>
-                <div style="width: 40px; display: flex; justify-content: center;">
-                  <el-icon style="color: #409eff;"><ArrowRight /></el-icon>
-                </div>
-                <div style="flex: 1; height: 80px; display: flex; justify-content: center; align-items: center; background: #f9f9f9; border-radius: 4px; overflow: hidden; border: 1px solid #e4e7ed;">
-                  <el-image
-                  :src="`/src/assets/ai案例图/008.png`" 
-                    style="width: 100%; height: 100%;"
-                    fit="contain"
-                  >
-                    <template #error>
-                      <div style="width: 100%; height: 100%; display: flex; justify-content: center; align-items: center; color: #909399; font-size: 12px;">
-                        <span>图片占位</span>
-                      </div>
-                    </template>
-                  </el-image>
-                </div>
-                <div style="width: 40px; display: flex; justify-content: center;">
-                  <el-icon style="color: #409eff;"><ArrowRight /></el-icon>
-                </div>
-                <div style="flex: 1; height: 80px; display: flex; justify-content: center; align-items: center; background: #f9f9f9; border-radius: 4px; overflow: hidden; border: 1px solid #e4e7ed;">
-                  <el-image
-                    :src="`/src/assets/ai案例图/009.png`"
-                    style="width: 100%; height: 100%;"
-                    fit="contain"
-                  >
-                    <template #error>
-                      <div style="width: 100%; height: 100%; display: flex; justify-content: center; align-items: center; color: #909399; font-size: 12px;">
-                        <span>图片占位</span>
-                      </div>
-                    </template>
-                  </el-image>
-                </div>
-              </div>
-              
-              <!-- 案例2 -->
-              <div style="display: flex; align-items: center; gap: 10px;">
-                <div style="flex: 1; height: 80px; display: flex; justify-content: center; align-items: center; background: #f9f9f9; border-radius: 4px; overflow: hidden; border: 1px solid #e4e7ed;">
-                  <el-image
-                  :src="`/src/assets/ai案例图/010.jpg`"
-                    style="width: 100%; height: 100%;"
-                    fit="contain"
-                  >
-                    <template #error>
-                      <div style="width: 100%; height: 100%; display: flex; justify-content: center; align-items: center; color: #909399; font-size: 12px;">
-                        <span>图片占位</span>
-                      </div>
-                    </template>
-                  </el-image>
-                </div>
-                <div style="width: 40px; display: flex; justify-content: center;">
-                  <el-icon style="color: #409eff;"><ArrowRight /></el-icon>
-                </div>
-                <div style="flex: 1; height: 80px; display: flex; justify-content: center; align-items: center; background: #f9f9f9; border-radius: 4px; overflow: hidden; border: 1px solid #e4e7ed;">
-                  <el-image
-                    :src="`/src/assets/ai案例图/011.png`"
-                    style="width: 100%; height: 100%;"
-                    fit="contain"
-                  >
-                    <template #error>
-                      <div style="width: 100%; height: 100%; display: flex; justify-content: center; align-items: center; color: #909399; font-size: 12px;">
-                        <span>图片占位</span>
-                      </div>
-                    </template>
-                  </el-image>
-                </div>
-                <div style="width: 40px; display: flex; justify-content: center;">
-                  <el-icon style="color: #409eff;"><ArrowRight /></el-icon>
-                </div>
-                <div style="flex: 1; height: 80px; display: flex; justify-content: center; align-items: center; background: #f9f9f9; border-radius: 4px; overflow: hidden; border: 1px solid #e4e7ed;">
-                  <el-image
-                  :src="`/src/assets/ai案例图/012.png`" 
-                    style="width: 100%; height: 100%;"
-                    fit="contain"
-                  >
-                    <template #error>
-                      <div style="width: 100%; height: 100%; display: flex; justify-content: center; align-items: center; color: #909399; font-size: 12px;">
-                        <span>图片占位</span>
-                      </div>
-                    </template>
-                  </el-image>
-                </div>
-              </div>
-              
-              <!-- 案例3 -->
-              <div style="display: flex; align-items: center; gap: 10px;">
-                <div style="flex: 1; height: 80px; display: flex; justify-content: center; align-items: center; background: #f9f9f9; border-radius: 4px; overflow: hidden; border: 1px solid #e4e7ed;">
-                  <el-image
-                  :src="`/src/assets/ai案例图/013.jpg`" 
-                    style="width: 100%; height: 100%;"
-                    fit="contain"
-                  >
-                    <template #error>
-                      <div style="width: 100%; height: 100%; display: flex; justify-content: center; align-items: center; color: #909399; font-size: 12px;">
-                        <span>图片占位</span>
-                      </div>
-                    </template>
-                  </el-image>
-                </div>
-                <div style="width: 40px; display: flex; justify-content: center;">
-                  <el-icon style="color: #409eff;"><ArrowRight /></el-icon>
-                </div>
-                <div style="flex: 1; height: 80px; display: flex; justify-content: center; align-items: center; background: #f9f9f9; border-radius: 4px; overflow: hidden; border: 1px solid #e4e7ed;">
-                  <el-image
-                    :src="`/src/assets/ai案例图/014.png`"
-                    style="width: 100%; height: 100%;"
-                    fit="contain"
-                  >
-                    <template #error>
-                      <div style="width: 100%; height: 100%; display: flex; justify-content: center; align-items: center; color: #909399; font-size: 12px;">
-                        <span>图片占位</span>
-                      </div>
-                    </template>
-                  </el-image>
-                </div>
-                <div style="width: 40px; display: flex; justify-content: center;">
-                  <el-icon style="color: #409eff;"><ArrowRight /></el-icon>
-                </div>
-                <div style="flex: 1; height: 80px; display: flex; justify-content: center; align-items: center; background: #f9f9f9; border-radius: 4px; overflow: hidden; border: 1px solid #e4e7ed;">
-                  <el-image
-                    :src="`/src/assets/ai案例图/015.png`"
-                    style="width: 100%; height: 100%;"
-                    fit="contain"
-                  >
-                    <template #error>
-                      <div style="width: 100%; height: 100%; display: flex; justify-content: center; align-items: center; color: #909399; font-size: 12px;">
-                        <span>图片占位</span>
-                      </div>
-                    </template>
-                  </el-image>
-                </div>
-              </div>
-              
-              <!-- 案例4 -->
-              <div style="display: flex; align-items: center; gap: 10px;">
-                <div style="flex: 1; height: 80px; display: flex; justify-content: center; align-items: center; background: #f9f9f9; border-radius: 4px; overflow: hidden; border: 1px solid #e4e7ed;">
-                  <el-image
-                    :src="`/src/assets/ai案例图/016.png`"
-                    style="width: 100%; height: 100%;"
-                    fit="contain"
-                  >
-                    <template #error>
-                      <div style="width: 100%; height: 100%; display: flex; justify-content: center; align-items: center; color: #909399; font-size: 12px;">
-                        <span>图片占位</span>
-                      </div>
-                    </template>
-                  </el-image>
-                </div>
-                <div style="width: 40px; display: flex; justify-content: center;">
-                  <el-icon style="color: #409eff;"><ArrowRight /></el-icon>
-                </div>
-                <div style="flex: 1; height: 80px; display: flex; justify-content: center; align-items: center; background: #f9f9f9; border-radius: 4px; overflow: hidden; border: 1px solid #e4e7ed;">
-                  <el-image
-                    :src="`/src/assets/ai案例图/017.png`"
-                    style="width: 100%; height: 100%;"
-                    fit="contain"
-                  >
-                    <template #error>
-                      <div style="width: 100%; height: 100%; display: flex; justify-content: center; align-items: center; color: #909399; font-size: 12px;">
-                        <span>图片占位</span>
-                      </div>
-                    </template>
-                  </el-image>
-                </div>
-                <div style="width: 40px; display: flex; justify-content: center;">
-                  <el-icon style="color: #409eff;"><ArrowRight /></el-icon>
-                </div>
-                <div style="flex: 1; height: 80px; display: flex; justify-content: center; align-items: center; background: #f9f9f9; border-radius: 4px; overflow: hidden; border: 1px solid #e4e7ed;">
-                  <el-image
-                    :src="`/src/assets/ai案例图/018.png`"
-                    style="width: 100%; height: 100%;"
-                    fit="contain"
-                  >
-                    <template #error>
-                      <div style="width: 100%; height: 100%; display: flex; justify-content: center; align-items: center; color: #909399; font-size: 12px;">
-                        <span>图片占位</span>
-                      </div>
-                    </template>
-                  </el-image>
-                </div>
-              </div>
-            </div>
-          </div>
-        </div>
-      </div>
-      
-      <div style="height: 100%; display: flex; flex-direction: column; width: 100%; min-width: 0; align-items: center;">
-        <!-- 上:留出的空白区域 -->
-        <div style="width: 100%; height: 90px; background-image: url('/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; width: 100%;">
-          <!-- 产品图片显示(默认) -->
-          <div style="width: 100%; height: 290px; max-width: 430px; display: flex; justify-content: center; align-items: center; background-color: white; border-radius: 4px;">
-            <el-carousel v-if="newImages.length > 0" indicator-position="outside" style="width: 100%; height: 100%;">
-              <el-carousel-item v-for="(image, index) in newImages" :key="index">
-                <el-image
-                  :src="formatImageUrl(image.url)"
-                  :preview-src-list="[formatImageUrl(image.url)]"
-                  style="width: 100%; height: 100%; object-fit: fill;"
-                  fit="fill"
-                  preview-teleported
-                >
-                  <template #error>
-                    <div style="width: 100%; height: 100%; background-color: white;" />
-                  </template>
-                </el-image>
-              </el-carousel-item>
-            </el-carousel>
-            <el-image
-              v-else-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
-            >
-              <template #error>
-                <div style="width: 100%; height: 100%; background-color: white;" />
-              </template>
-            </el-image>
-            <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>
-        <!-- 中:商品信息表单(宽度 100% 含边框,避免右侧边框被裁) -->
-        <div class="product-info-container" style="width: 100%; max-width: 430px; height: 320px; border: 12px solid #f6E0dd; border-radius: 4px; padding: 15px; box-sizing: border-box;">
-          <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: 100%; max-width: 430px; height: 61px;"></div>
-      </div>
-    </div>
-  </div>
-</div>
-    
-    <!-- 右侧:模版列表(与中间列左右留白一致) -->
-    <div class="right-column">
-      <div class="right-template" style="height: 100%; display: flex; flex-direction: column;">
-        <!-- 标题 -->
-        <div style="font-size: 18px; font-weight: bold; color: white; margin-bottom: 15px; background-color: #404040; padding: 10px; border-radius: 4px; text-align: center;margin-top:15px">①模版</div>
-        
-        <!-- 搜索框 -->
-        <div class="template-search" style="margin-bottom: 15px;">
-          <el-input v-model="searchKeyword" placeholder="请描述你想搜索的模版关键字..." clearable @input="handleSearch" @clear="handleClearSearch">
-            <template #prefix>
-              <el-icon><Search /></el-icon>
-            </template>
-            <template #append>
-              <el-button @click="handleSearch" >搜索</el-button>
-            </template>
-          </el-input>
-        </div>
-
-        <!-- 关键词搜索次数最多的 -->
-        
-
-        <!-- 模板列表 -->
-        <div style="flex: 1; min-height: 0;">
-          <h4 style="margin-bottom: 10px;margin: 0px 0px 20px 0px;padding: 0px;">模版分类 ({{ templateList.length }})</h4>
-          <el-scrollbar style="height: 100%;">
-            <div class="template-list">
-              <!-- 搜索无结果提示 -->
-              <div v-if="!searchLoading && searchKeyword && templateList.length === 0" class="empty-search">
-                <el-icon :size="50"><Search /></el-icon>
-                <p>未找到相关模板</p>
-              </div>
-              
-              <!-- 模板项 -->
-              <div  v-for="template in templateList" 
-                :key="template.id" class="template-item"
-                :class="{ 'active': currentTemplateId === template.id }"
-                @click="selectTemplate(template)" >
-                <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="contain"
-                    >
-                      <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) }}
-                </div>
-              </div>
-              
-              <!-- 初始无数据提示 -->
-              <div v-if="!searchKeyword && !searchLoading && templateList.length === 0" class="empty-templates">
-                <el-icon :size="40"><Picture /></el-icon>
-                <p>暂无模板数据</p>
-              </div>
-            </div>
-          </el-scrollbar>
-          <!-- 图片预览组件 -->
-          <el-image-viewer
-            v-if="previewVisible"
-            :url-list="previewImageUrl ? [previewImageUrl] : []"
-            :hide-on-click-modal="true"
-            @close="previewVisible = false"
-          />
-        </div>
-      </div>
-    </div>
-    
-    <!-- 商品图例右侧面板 (已移至中间列) -->
-    <div v-if="false" class="product-example-panel" style="width: 420px; border-left: 1px solid #e4e7ed; padding: 20px; background: #ffffff; overflow-y: auto; box-shadow: -2px 0 10px rgba(0,0,0,0.05);">
-      <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px;">
-        <h3 style="margin: 0; font-size: 16px; font-weight: bold; color: #303133;">商品图例</h3>
-        <el-button type="text" size="small" @click="toggleProductExample">
-          <el-icon><Close /></el-icon>
-        </el-button>
-      </div>
-      
-      <p style="margin: 0 0 15px 0; color: #606266; line-height: 1.5;">
-        建议上传商品单一、完整清晰、占据画面中心的白底图,否则可能会影响商品识别效果和生成的背景图质量。
-      </p>
-      
-      <!-- 商品单一 -->
-      <div style="margin-bottom: 20px;">
-        <div style="font-weight: 600; color: #303133; margin-bottom: 10px;">商品单一</div>
-        <div style="background: white; padding: 15px; border-radius: 6px; box-shadow: 0 2px 4px rgba(0,0,0,0.05); margin-bottom: 10px;">
-          <div style="display: flex; align-items: center; margin-bottom: 8px;">
-            <el-icon :size="16" style="color: #67c23a; margin-right: 8px;"><SuccessFilled /></el-icon>
-            <span style="font-weight: 500; color: #303133;">商品完整清晰</span>
-          </div>
-          <div style="height: 180px; display: flex; justify-content: center; align-items: center; background: #f9f9f9; border-radius: 4px; overflow: hidden;">
-            <el-image
-              :src="'@/assets/ai案例图/001.png'" 
-              style="width: 100%; height: 100%;"
-              fit="contain"
-            >
-              <template #error>
-                <div style="width: 100%; height: 100%; display: flex; justify-content: center; align-items: center; color: #909399;">
-                  <span>图片占位</span>
-                </div>
-              </template>
-            </el-image>
-          </div>
-        </div>
-        
-        <div style="background: white; padding: 15px; border-radius: 6px; box-shadow: 0 2px 4px rgba(0,0,0,0.05);">
-          <div style="display: flex; align-items: center; margin-bottom: 8px;">
-            <el-icon :size="16" style="color: #67c23a; margin-right: 8px;"><SuccessFilled /></el-icon>
-            <span style="font-weight: 500; color: #303133;">商品占据画面中心</span>
-          </div>
-          <div style="height: 180px; display: flex; justify-content: center; align-items: center; background: #f9f9f9; border-radius: 4px; overflow: hidden;">
-            <el-image
-              :src="'@/assets/ai案例图/002.png'" 
-              style="width: 100%; height: 100%;"
-              fit="contain"
-            >
-              <template #error>
-                <div style="width: 100%; height: 100%; display: flex; justify-content: center; align-items: center; color: #909399;">
-                  <span>图片占位</span>
-                </div>
-              </template>
-            </el-image>
-          </div>
-        </div>
-      </div>
-      
-      <!-- 画面包含多件商品 -->
-      <div style="margin-bottom: 20px;">
-        <div style="font-weight: 600; color: #303133; margin-bottom: 10px;">画面包含多件商品</div>
-        <div style="background: white; padding: 15px; border-radius: 6px; box-shadow: 0 2px 4px rgba(0,0,0,0.05);">
-          <div style="display: flex; align-items: center; margin-bottom: 8px;">
-            <el-icon :size="16" style="color: #f56c6c; margin-right: 8px;"><Close /></el-icon>
-            <span style="font-weight: 500; color: #303133;">不推荐</span>
-          </div>
-          <div style="height: 180px; display: flex; justify-content: center; align-items: center; background: #f9f9f9; border-radius: 4px; overflow: hidden;">
-            <el-image
-              :src="'@/assets/ai案例图/003.png'" 
-              style="width: 100%; height: 100%;"
-              fit="contain"
-            >
-              <template #error>
-                <div style="width: 100%; height: 100%; display: flex; justify-content: center; align-items: center; color: #909399;">
-                  <span>图片占位</span>
-                </div>
-              </template>
-            </el-image>
-          </div>
-        </div>
-      </div>
-      
-      <!-- 商品残缺/遮挡 -->
-      <div style="margin-bottom: 20px;">
-        <div style="font-weight: 600; color: #303133; margin-bottom: 10px;">商品残缺/遮挡</div>
-        <div style="background: white; padding: 15px; border-radius: 6px; box-shadow: 0 2px 4px rgba(0,0,0,0.05);">
-          <div style="display: flex; align-items: center; margin-bottom: 8px;">
-            <el-icon :size="16" style="color: #e6a23c; margin-right: 8px;"><WarningFilled /></el-icon>
-            <span style="font-weight: 500; color: #303133;">商品主体不突出</span>
-          </div>
-          <div style="height: 180px; display: flex; justify-content: center; align-items: center; background: #f9f9f9; border-radius: 4px; overflow: hidden;">
-            <el-image
-              :src="'@/assets/ai案例图/004.png'" 
-              style="width: 100%; height: 100%;"
-              fit="contain"
-            >
-              <template #error>
-                <div style="width: 100%; height: 100%; display: flex; justify-content: center; align-items: center; color: #909399;">
-                  <span>图片占位</span>
-                </div>
-              </template>
-            </el-image>
-          </div>
-        </div>
-      </div>
-    </div>
-  </div>
-</el-dialog>
-
-    <!-- 图片预览 -->
-    <el-dialog v-model="dialogVisible" title="图片预览" width="70%" top="5vh" destroy-on-close>
-      <div style="text-align: center;">
-        <el-image :src="currentImageUrl" style="max-width: 100%; max-height: 70vh;" fit="contain" />
-      </div>
-    </el-dialog>
-
-
-
-    <el-dialog
-    v-model="AdddialogVisible"
-    title="新增产品"
-    width="600px"
-    :close-on-click-modal="false"
-    @close="handleClose"
-  >
-    <el-form
-      ref="productFormRef"
-      :model="productForm"
-      label-width="100px"
-      label-position="right"
-      size="medium"
-    >
-      <!-- 产品名称 -->
-      <el-form-item label="产品名称" prop="product_name">
-        <el-input
-          v-model="productForm.product_name"
-          placeholder="请输入产品名称"
-          clearable
-          show-word-limit
-        />
-      </el-form-item>
-
-      <!-- 产品编码 -->
-      <el-form-item label="产品编码" prop="product_code">
-        <el-input
-          v-model="productForm.product_code"
-          placeholder="请输入产品编码"
-          clearable
-          show-word-limit
-        />
-      </el-form-item>
-
-
-
-      <!-- 商户 -->
-      <el-form-item label="商户" prop="merchant_id">
-        <el-input
-          v-model="productForm.merchant_id"
-          placeholder="请选择商户"
-          style="width: 100%"
-          clearable
-          filterable
-        >
-        </el-input>
-      </el-form-item>
-
-      <!-- 产品图片 -->
-      <el-form-item label="产品图片" prop="product_img">
-        <div class="add-dialog-upload-wrap">
-          <!-- 已上传:预览 + 替换/删除 -->
-          <div v-if="productForm.product_img" class="add-dialog-preview-box">
-            <div class="add-dialog-preview-img">
-              <img
-                v-if="addDialogPreviewSrc"
-                :src="addDialogPreviewSrc"
-                class="add-dialog-preview-img-inner"
-                alt="产品图片预览"
-              />
-            </div>
-            <div class="add-dialog-preview-actions">
-              <el-upload
-                :show-file-list="false"
-                :before-upload="handleAddDialogSelectImage"
-                accept="image/jpeg,image/png,image/jpg,image/webp"
-              >
-                <el-button type="primary" size="small">
-                  <el-icon><Upload /></el-icon>
-                  替换
-                </el-button>
-              </el-upload>
-              <el-button type="danger" size="small" plain @click="handleRemoveImage">
-                删除
-              </el-button>
-            </div>
-          </div>
-          <!-- 未上传:点击上传区域 -->
-          <el-upload
-            v-else
-            class="add-dialog-upload-area"
-            :show-file-list="false"
-            :before-upload="handleAddDialogSelectImage"
-            accept="image/jpeg,image/png,image/jpg,image/webp"
-          >
-            <div class="add-dialog-upload-inner">
-              <el-icon class="add-dialog-upload-icon"><Plus /></el-icon>
-              <span class="add-dialog-upload-text">点击上传图片</span>
-              <span class="add-dialog-upload-tip">支持 JPG、PNG,不超过 5MB</span>
-            </div>
-          </el-upload>
-        </div>
-      </el-form-item>
-    </el-form>
-
-    <template #footer>
-      <span class="dialog-footer">
-        <el-button @click="handleClose">取消</el-button>
-        <el-button type="primary" :loading="submitLoading" @click="handleSubmit">
-          确定
-        </el-button>
-      </span>
-    </template>
-  </el-dialog>
-
-
-
-  </div>
-</template>
-
-<script setup>
-import { ref, reactive, computed, toRaw, onMounted, watch } from 'vue'
-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,GetImageStatus } from '@/api/mes/job'
-import { useUserStore } from '@/pinia/modules/user'
-import {  ZoomIn, Camera, SuccessFilled, WarningFilled, More, ArrowRight, ArrowDown, Loading, Plus, Upload, Picture } from '@element-plus/icons-vue'
-import { Layout, LayoutHeader, LayoutSider, LayoutContent } from '@arco-design/web-vue'
-
-
-
-// 商品图例显示状态
-const productExampleVisible = ref(false)
-const caseExampleVisible = ref(false)
-
-// 图片历史记录相关状态
-const templateTreeData = ref([])
-const currentTemplateId = ref(null)
-const currentTemplateName = ref('')
-const filteredImages = ref([])
-const showHistoryPanel = ref(false)
-
-// 切换历史记录面板显示
-const toggleHistoryPanel = () => {
-  showHistoryPanel.value = !showHistoryPanel.value
-}
-
-// 切换商品图例显示
-const toggleProductExample = () => {
-  productExampleVisible.value = !productExampleVisible.value
-  if (productExampleVisible.value) {
-    caseExampleVisible.value = false
-  }
-}
-
-// 切换案例显示
-const toggleCaseExample = () => {
-  caseExampleVisible.value = !caseExampleVisible.value
-  if (caseExampleVisible.value) {
-    productExampleVisible.value = false
-  }
-}
-
-
-
-
-
-
-
-const props = defineProps({
-  editFormData: {
-    type: Object,
-    default: () => ({})
-  }
-})
-//获取登录用户信息
-const userStore = useUserStore()
-const _username = ref('')
-_username.value = userStore.userInfo.userName + '/' + userStore.userInfo.nickName
-console.log('获取用户信息',_username.value)
-console.log('获取用户名称',userStore.userInfo.nickName)
-
-//获取服务器地址
-const baseUrl = ref('')
-const port = ref('')
-const full_url = ref('')
-// 从接口获取服务器地址
-const fetchServerUrl = async () => {
-  try {
-    const res = await GetHttpUrl()
-    if (res.code === 0 && res.data && res.data.full_url) {
-      full_url.value = res.data.full_url
-      baseUrl.value = res.data.baseUrl
-      port.value = res.data.port
-    console.log('获取服务器地址',full_url.value)
-    console.log('IP地址',baseUrl.value)
-    console.log('端口',port.value)
-    }
-  } catch (error) {
-    console.error('获取服务器地址失败:', error)
-  }
-}
-fetchServerUrl();
-
-const searchInfo = ref('')
-const tableData1 = ref([])
-const total = ref(0)
-const page = ref(1)
-const pageSize = ref(50)
-const dialogVisible = ref(false)
-const currentImageUrl = ref('')
-const width = ref('')
-const height = ref('')
-const isLoading = ref(false)
-const txttotxt_selectedOption = ref('gemini-2.0-flash')
-const selectedOption = ref('dall-e-3')
-const num = ref(1)
-const _parh = ref([])
-const folderList = ref([])
-const selectedFolder = ref('')
-
-// 左侧树形数据
-const treeData = ref([])
-
-const getTreeData = async () => {
-  try {
-    const data  = await merchantGetab();
-    console.log(data)
-    
-    treeData.value = data.data.map(item => {
-      return {
-        label: item.tab || item.merchant_name,
-        value: item.merchant_code,
-        // 如果需要原始数据可以保留
-        originalData: item
-      }
-    })
-    
-  } catch (error) {
-    console.error(error)
-    treeData.value = [] // 出错时清空数据
-  }
-}
-
-getTreeData();
-
-const defaultProps = {
-  children: 'children',
-  label: 'label'
-}
-
-const editDialogVisible = ref(false)
-const editFormData = reactive({
-  id: '',
-  chinese_description: '',
-  english_description: '',
-  new_image_url: '',
-  new_video_url: '',
-  imgtoimg_url: '',
-  img_name: '',
-  video_name: ''
-})
-
-// 定义文生图表单对象
-const form = reactive({
-  chinese_description: ''
-})
-
-// 控制产品信息部分图片是否显示
-const showProductImage = ref(false)
-
-// 存储生成的多个新图
-const newImages = ref([])
-
-// 加载状态控制
-const loadingStatus = ref(false)
-
-const formatImageUrl = (path) => {
-  if (!path) return ''
-  // 检查path是否已经是完整的URL
-  if (path.startsWith('http://') || path.startsWith('https://')) {
-    console.log('路径已经是完整的URL:', path)
-    return path
-  }
-  // 确保生成的URL不会有双斜杠
-  const baseUrl = full_url.value.replace(/\/$/, '') // 移除末尾的斜杠
-  const cleanPath = path.replace(/^public\//, '').replace(/^\//, '') // 移除开头的斜杠
-  const formattedUrl = `${baseUrl}/${cleanPath}`
-  console.log('生成的完整URL:', { path, full_url: full_url.value, baseUrl, cleanPath, formattedUrl })
-  return formattedUrl
-}
-
-// 点击图片时更新产品信息部分的图片和对应的product_content
-const updateProductImage = (imageUrl) => {
-  editFormData.new_image_url = imageUrl
-  showProductImage.value = true
-  // 查找对应的图片对象,更新product_content到输入框
-  const selectedImage = newImages.value.find(img => img.url === imageUrl)
-  if (selectedImage && selectedImage.product_content) {
-    editFormData.chinese_description = selectedImage.product_content
-  }
-  // ElMessage.success('图片已更新到产品信息区域')
-}
-
-const txttoimg_modelList = ref([]); // 存储所有模型数据
-const txtimgselectedModel = ref(''); // 当前选中的模型名称
-const usedId = ref(null); // 当前使用的模型ID(兼容旧代码)
-const selectedId = ref(null); // 用户选择的模型ID(兼容旧代码)
-const isGenerating = ref(false); // 文生图生成中状态
-const usedIds = ref({}); // 当前使用的模型ID集合
-const selectedIds = ref({}); // 用户选择的模型ID集合
-
-// 获取文生图模型列表
-const fetchTxtImgModels = async () => {
-  try {
-    const response = await txttoimg_moxing();
-    txttoimg_modelList.value = response.data.models.wenshengtu;
-    // 获取当前使用的模型ID
-    usedIds.value = response.data.used_ids;
-    const currentUsedId = usedIds.value.wenshengtu;
-    
-    // 设置默认选中的模型
-    const defaultModel = txttoimg_modelList.value.find(item => item.id === currentUsedId);
-    if (defaultModel) {
-      txtimgselectedModel.value = defaultModel.txttoimg;
-      usedId.value = defaultModel.id;
-      selectedId.value = defaultModel.id; 
-      selectedIds.value.wenshengtu = defaultModel.id;
-      selectedOption.value = defaultModel.txttoimg;
-    }
-    
-    console.log('文生图模型列表:', txttoimg_modelList.value);
-    console.log('当前使用的模型ID:', currentUsedId);
-    console.log('默认选中的模型:', defaultModel);
-  } catch (error) {
-    console.error('获取文生图模型列表失败:', error);
-    ElMessage.error('获取模型列表失败');
-  }
-}
-fetchTxtImgModels();
-
-// const getTableData = async () => {
-//     const res = await getTable({
-//       search: searchInfo.value,
-//       limit: pageSize.value,
-//       page: page.value,
-//       folder: selectedFolder.value
-//     })
-//     tableData1.value = res.data.list
-//     total.value = res.data.total
-    
-//     // 更新文件夹列表
-//     if (res.data.folder) {
-//       folderList.value = res.data.folder
-//     }
-// }
-
-const nodeid = ref('')
-// 处理树节点点击
-const handleNodeClick = async(node) => {
-  console.log('点击的节点:', node.value);
-  nodeid.value = node.value;
-  
-  const res = await productList({
-    search: searchInfo.value,
-    limit: pageSize.value,
-    page: page.value,
-    code: node.value
-  });
-  
-  if (res.code === 0) {
-    // 按照ID进行排序,保持数据顺序
-    const sortedData = res.data.list.sort((b, a) => a.id - b.id);
-    tableData1.value = sortedData;
-    total.value = res.data.total;
-  }
-};
-
-// 当选择模型变化时
-const handleModelChange = (modelName) => {
-  const model = txttoimg_modelList.value.find(item => item.txttoimg === modelName);
-  if (model) {
-    selectedId.value = model.id;
-    selectedIds.value.wenshengtu = model.id;
-    selectedOption.value = model.txttoimg;
-    console.log('选择的模型ID:', model.id);
-  }
-}
-// 设置默认模型
-const setActive = async (type) => {
-  const id = selectedIds.value[type]
-  if (id) {
-    try {
-      // 调用API设置默认模型
-      const res = await txttoimg_update({ id: id,type:"wenshengtu"})
-      if (res.code === 0) {
-        usedIds.value[type] = id
-        ElMessage.success('默认模型设置成功')
-      } else {
-        ElMessage.error(res.msg || '设置默认模型失败')
-      }
-    } catch (error) {
-      console.error('设置默认模型失败', error)
-      ElMessage.error('设置默认模型失败')
-    }
-  }
-}
-
-
-// 处理模板分类树数据
-const processTemplateTreeData = (images) => {
-  // 按template_id分组
-  const templateMap = {}
-  images.forEach(item => {
-    if (item.template_id) {
-      if (!templateMap[item.template_id]) {
-        templateMap[item.template_id] = []
-      }
-      templateMap[item.template_id].push(item)
-    }
-  })
-  
-  // 构建树结构数据
-  const treeData = []
-  Object.keys(templateMap).forEach(templateId => {
-    treeData.push({
-      id: templateId,
-      label: `模板 ${templateId}`,
-      count: templateMap[templateId].length
-    })
-  })
-  
-  templateTreeData.value = treeData
-  
-  // 默认选中第一个模板
-  if (treeData.length > 0) {
-    currentTemplateId.value = treeData[0].id
-    currentTemplateName.value = treeData[0].label
-    filterImagesByTemplate(treeData[0].id)
-  }
-}
-
-// 根据模板ID过滤图片
-const filterImagesByTemplate = (templateId) => {
-  filteredImages.value = newImages.value.filter(image => image.template_id == templateId)
-}
-
-// 处理模板树点击事件
-const handleTemplateTreeClick = (data) => {
-  currentTemplateId.value = data.id
-  currentTemplateName.value = data.label
-  filterImagesByTemplate(data.id)
-}
-
-const onRowDblClick = async (row) => {
-    // 打开新产品前先清空上一产品的历史与展示,避免残留
-    showHistoryPanel.value = false
-    newImages.value = []
-    templateTreeData.value = []
-    filteredImages.value = []
-    currentTemplateId.value = null
-    currentTemplateName.value = ''
-
-    // 设置编辑表单ID
-    editFormData.id = row.id
-    editDialogVisible.value = true
-
-    // 1. 获取产品详情并设置原图
-    const detailResponse = await productDetail({ id: row.id })
-    if (detailResponse.code === 0 && detailResponse.data) {
-      editFormData.original_image_url = detailResponse.data['产品图片']
-      editFormData.new_image_url = detailResponse.data['产品效果图']
-      editFormData.original_name = detailResponse.data['产品名称']
-      editFormData.product_name = detailResponse.data['产品名称']
-      editFormData.product_code = detailResponse.data['产品编码']
-
-      // 如果有新图片,自动显示到产品信息区域
-      if (detailResponse.data['产品效果图']) {
-        showProductImage.value = true
-      } else {
-        showProductImage.value = false
-      }
-
-      // 获取image数组数据
-      if (detailResponse.image && Array.isArray(detailResponse.image)) {
-        detailResponse.image.forEach(item => {
-          if (item.product_new_img) {
-            newImages.value.push({
-              url: item.product_new_img,
-              product_content: item.product_content || '',
-              template_id: item.template_id,
-              createTime: item.createTime
-            })
-          }
-        })
-
-        // 如果有image数据,默认显示第一个的product_content
-        if (newImages.value.length > 0 && newImages.value[0].product_content) {
-          editFormData.chinese_description = newImages.value[0].product_content
-        }
-
-        // 处理模板分类树数据
-        processTemplateTreeData(detailResponse.image)
-      } else {
-        editFormData.chinese_description = ''
-      }
-    }
-
-    // 2. 获取所有模板数据
-    await fetchTemplates()
-}
-
-// 存储所有模板数据
-const templateList = ref([])
-
-// 获取所有模板
-const fetchTemplates = async () => {
-    const response = await product_template()
-    if (response.code === 0 && response.data) {
-      templateList.value = response.data.map(item => ({
-        id: item.id,
-        template_image_url: item.template_image_url,
-        chinese_description: item.chinese_description || '',
-        english_description: item.english_description || ''
-      }))
-      
-      // 默认选中第一个模板
-      // if (templateList.value.length > 0) {
-      //   selectTemplate(templateList.value[0])
-      // }
-      if (newImages.value.length > 0) {
-        updateProductImage(newImages.value[0].url)
-      }
-    }
-}
-
-// 选择模板
-const selectTemplate = (template) => {
-  currentTemplateId.value = template.id
-  editFormData.template_image_url = template.template_image_url
-  editFormData.template_id = template.id
-  editFormData.chinese_description = template.chinese_description
-}
-
-// 处理图片加载错误
-const handleTemplateImageError = (event) => {
-  event.target.src = 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTAwIiBoZWlnaHQ9IjEwMCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cmVjdCB3aWR0aD0iMTAwIiBoZWlnaHQ9IjEwMCIgZmlsbD0iI2YwZjBmMCIvPjx0ZXh0IHg9IjUwIiB5PSI1MCIgZm9udC1mYW1pbHk9IkFyaWFsIiBmb250LXNpemU9IjEyIiBmaWxsPSIjY2NjIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBkeT0iLjNlbSI+SW1hZ2UgRXJyb3I8L3RleHQ+PC9zdmc+'
-}
-
-
-
-// 修改后的 selectTemplate 函数(如果需要保留按钮)
-const handleTemplateButton = () => {
-  // 可以留空或给提示
-  ElMessage.info('请直接点击上方的模板图片')
-}
-
-
-
-// 图片预览相关
-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 ''
-  if (text.length <= length) return text
-  return text.substring(0, length) + '...'
-}
-
-
-
-
-// 清空输入框内容
-const clearInput = () => {
-  editFormData.chinese_description = ''
-  ElMessage.success('已清空输入框内容')
-}
-
-// 内容优化(使用轮询机制)
-const optimizeContent = async () => {
-  try {
-    if (!editFormData.chinese_description) {
-      ElMessage.warning('请输入要优化的内容')
-      return
-    }
-    
-    // 设置加载状态
-    loadingStatus.value = true
-    
-    // 重置状态
-    pollStatus.value = 'optimizing'
-    pollCount.value = 0
-    
-    // 第一步:调用生成接口触发生成任务
-    const generateResponse = await GetTxtToTxt({ 
-      status_val: '文生文',
-      prompt: editFormData.chinese_description,
-      model: 'gemini-3-pro-preview',
-      id: editFormData.id,
-      path: editFormData.original_image_url,
-    })
-    
-    if (generateResponse.code === 0) {
-      ElMessage.success('内容优化任务已开始,请稍候...')
-      
-      // 清除之前的定时器
-      if (pollInterval.value) {
-        clearInterval(pollInterval.value)
-      }
-      
-      // 开始轮询查询结果
-      pollInterval.value = setInterval(async () => {
-        pollCount.value++
-        
-        try {
-          // 调用查询接口
-          const checkResponse = await GetProductFind({ id: editFormData.id })
-          
-          if (checkResponse.code === 0 && checkResponse.data) {
-            // 检查是否有content字段
-            if (checkResponse.data.content) {
-              // 停止轮询
-              clearInterval(pollInterval.value)
-              pollInterval.value = null
-              pollStatus.value = 'success'
-              loadingStatus.value = false
-              
-              // 更新内容到输入框
-              editFormData.chinese_description = checkResponse.data.content
-              ElMessage.success(`内容优化成功!耗时约${pollCount.value * 10}秒`)
-              return
-            }
-          }
-          
-          // 如果轮询超过30次(5分钟),停止轮询
-          if (pollCount.value >= 30) {
-            clearInterval(pollInterval.value)
-            pollInterval.value = null
-            pollStatus.value = 'error'
-            loadingStatus.value = false
-            ElMessage.warning('优化超时,请稍后手动检查结果')
-          }
-          
-        } catch (pollError) {
-          console.error('优化轮询查询失败:', pollError)
-          // 轮询失败继续尝试
-        }
-      }, 5000) // 每5秒轮询一次
-      
-    } else {
-      pollStatus.value = 'error'
-      loadingStatus.value = false
-      ElMessage.error('优化任务启动失败: ' + (generateResponse.msg || '未知错误'))
-    }
-    
-  } catch (generateError) {
-    pollStatus.value = 'error'
-    loadingStatus.value = false
-    console.error('内容优化失败:', generateError)
-    ElMessage.error('内容优化失败: ' + (generateError.message || '未知错误'))
-  }
-}
-
-// 在script中定义
-const pollStatus = ref(null) // 轮询状态:'polling', 'success', 'error'
-const pollCount = ref(0) // 轮询次数
-const pollInterval = ref(null) // 轮询定时器
-const task_id = ref('')
-// 生成图片(简化版,只做轮询)
-const generateImage = async () => {
-  try {
-    if (!editFormData.template_id) {
-      ElMessage.warning('请先选择模版')
-      return
-    }
-
-    if (!editFormData.chinese_description) {
-      ElMessage.warning('请输入描述内容')
-      return
-    }
-
-    // 设置加载状态
-    loadingStatus.value = true
-    
-    // 重置状态
-    pollStatus.value = 'polling'
-    pollCount.value = 0
-    console.log(editFormData.template_id)
-    // 第一步:调用生成接口触发生成任务
-    const generateResponse = await GetTxtToTxt({ 
-      status_val: '文生图',
-      prompt: editFormData.chinese_description,
-      model: 'gemini-3-pro-image-preview',
-      id: editFormData.id,
-      size: selectedSize.value,
-      template_id:editFormData.template_id,
-    })
-    
-    if (generateResponse.code === 0) {
-      ElMessage.success('图片生成任务已开始,请稍候...')
-      task_id.value = generateResponse.data.task_id
-    
-
-      // 稍后在轮询中使用GetImageStatus接口
-      
-      // 清除之前的定时器
-      if (pollInterval.value) {
-        clearInterval(pollInterval.value)
-      }
-      
-      // 开始轮询查询结果
-      pollInterval.value = setInterval(async () => {
-        pollCount.value++
-        
-        try {
-          // 调用GetImageStatus接口查询生成状态
-          const statusResponse = await GetImageStatus({ task_id: task_id.value })
-          
-          if (statusResponse.code === 0 && statusResponse.data) {
-            // 如果获取到数据且有图片URL
-            if (statusResponse.data.image_url) {
-              // 停止轮询
-              clearInterval(pollInterval.value)
-              pollInterval.value = null
-              pollStatus.value = 'success'
-              loadingStatus.value = false
-              
-              // 更新新图URL
-              const imageUrl = statusResponse.data.image_url
-              editFormData.new_image_url = imageUrl
-              editFormData.img_name = `生成图片_${new Date().getTime()}.jpg`
-              
-              // 更新历史记录
-              const newImageItem = {
-                url: imageUrl,
-                product_content: editFormData.chinese_description || '',
-                template_id: editFormData.template_id,
-                createTime: statusResponse.data.completed_at || new Date().toISOString()
-              }
-              
-              // 添加到newImages数组(走马灯轮播)
-              newImages.value.unshift(newImageItem)
-              
-              // 处理模板分类树数据
-              processTemplateTreeData([newImageItem])
-              
-              ElMessage.success(`图片生成成功!耗时约${pollCount.value * 5}秒`)
-            } else if (statusResponse.data.error) {
-              // 如果返回错误
-              clearInterval(pollInterval.value)
-              pollInterval.value = null
-              pollStatus.value = 'error'
-              loadingStatus.value = false
-              ElMessage.error('图片生成失败: ' + statusResponse.data.error)
-            }
-          } else {
-            // 如果接口返回错误
-            clearInterval(pollInterval.value)
-            pollInterval.value = null
-            pollStatus.value = 'error'
-            loadingStatus.value = false
-            ElMessage.error('查询生成状态失败: ' + (statusResponse.msg || '未知错误'))
-          }
-          
-          // 如果轮询超过30次(2.5分钟),停止轮询
-          if (pollCount.value >= 30) {
-            clearInterval(pollInterval.value)
-            pollInterval.value = null
-            pollStatus.value = 'error'
-            loadingStatus.value = false
-            ElMessage.warning('生成超时,请稍后手动检查结果')
-          }
-          
-        } catch (pollError) {
-          console.error('轮询查询失败:', pollError)
-          // 轮询失败继续尝试
-        }
-      }, 5000) // 每5秒轮询一次
-      
-    } else {
-      pollStatus.value = 'error'
-      loadingStatus.value = false
-      ElMessage.error('生成任务启动失败: ' + (generateResponse.msg || '未知错误'))
-    }
-    
-  } catch (generateError) {
-    pollStatus.value = 'error'
-    loadingStatus.value = false
-    console.error('生成图片失败:', generateError)
-    ElMessage.error('生成图片失败: ' + (generateError.message || '未知错误'))
-  }
-}
-
-// 尺寸相关的数据
-const selectedSize = ref('1:1') // 默认选择1:1
-const customWidth = ref('')
-const customHeight = ref('')
-const sizePresets = {
-  '1:1': { width: 1024, height: 1024 },
-  '4:3': { width: 1024, height: 768 },
-  '3:2': { width: 1024, height: 683 },
-  '2:3': { width: 683, height: 1024 },
-  '9:16': { width: 675, height: 1200 },
-  '16:9': { width: 1200, height: 675 },
-  '21:9': { width: 1200, height: 514 },
-  '3:4': { width: 768, height: 1024 }
-}
-
-// 获取尺寸信息
-const getSizeInfo = (size) => {
-  if (size === 'custom') return '自定义尺寸'
-  const preset = sizePresets[size]
-  return `${preset.width}×${preset.height}`
-}
-
-// 尺寸变化处理
-const handleSizeChange = (value) => {
-  const selectedValue = value || selectedSize.value
-  if (selectedValue !== 'custom') {
-    // 如果是预设尺寸,可以在这里执行相关操作
-    console.log('选择了尺寸:', selectedValue, sizePresets[selectedValue])
-    // 可以更新生成图片的参数
-  }
-}
-
-// 验证自定义尺寸
-const validateCustomSize = () => {
-  // 确保输入的是数字
-  if (customWidth.value && !/^\d+$/.test(customWidth.value)) {
-    customWidth.value = customWidth.value.replace(/\D/g, '')
-  }
-  if (customHeight.value && !/^\d+$/.test(customHeight.value)) {
-    customHeight.value = customHeight.value.replace(/\D/g, '')
-  }
-  
-  // 限制最大最小值
-  const maxSize = 4096
-  const minSize = 64
-  
-  if (customWidth.value) {
-    let width = parseInt(customWidth.value)
-    if (width > maxSize) customWidth.value = maxSize.toString()
-    if (width < minSize) customWidth.value = minSize.toString()
-  }
-  
-  if (customHeight.value) {
-    let height = parseInt(customHeight.value)
-    if (height > maxSize) customHeight.value = maxSize.toString()
-    if (height < minSize) customHeight.value = minSize.toString()
-  }
-}
-
-// 获取当前选择的尺寸
-const getCurrentSize = () => {
-  if (selectedSize.value === 'custom') {
-    return {
-      type: 'custom',
-      width: customWidth.value ? parseInt(customWidth.value) : 1024,
-      height: customHeight.value ? parseInt(customHeight.value) : 1024
-    }
-  } else {
-    return {
-      type: selectedSize.value,
-      ...sizePresets[selectedSize.value]
-    }
-  }
-}
-
-
-
-// 可选:添加常用尺寸按钮
-const quickSizes = [
-  { label: '512×512', width: 512, height: 512 },
-  { label: '768×768', width: 768, height: 768 },
-  { label: '1024×1024', width: 1024, height: 1024 },
-  { label: '1920×1080', width: 1920, height: 1080 }
-]
-
-const selectQuickSize = (size) => {
-  selectedSize.value = 'custom'
-  customWidth.value = size.width.toString()
-  customHeight.value = size.height.toString()
-}
-
-
-const downloadImage = async (type) => {
-  console.log('开始下载...')
-  
-  let imagePath = ''
-  let originalFileName = ''
-  
-  if (type === 'original') {
-    imagePath = editFormData.original_image_url
-    originalFileName = editFormData.original_name || ''
-    
-    if (!imagePath) {
-      ElMessage.warning('原图不存在')
-      return
-    }
-    
-  } else if (type === 'new') {
-    imagePath = editFormData.new_image_url
-    originalFileName = editFormData.img_name || ''
-    
-    if (!imagePath) {
-      ElMessage.warning('新图不存在')
-      return
-    }
-  } else {
-    console.error('未知的下载类型:', type)
-    ElMessage.error('未知的下载类型')
-    return
-  }
-  
-  console.log(`下载${type}图信息:`, { imagePath, originalFileName })
-  
-  // 获取完整URL
-  const fullUrl = formatImageUrl(imagePath)
-  console.log('完整下载URL:', fullUrl)
-  
-  // 生成安全的文件名
-  const safeFileName = generateSafeFilename(originalFileName, imagePath, type)
-  console.log('安全文件名:', safeFileName)
-  
-  try {
-    // 调用下载
-    await downloadWithBlob(fullUrl, safeFileName)
-    console.log('下载函数调用成功')
-  } catch (error) {
-    console.error('下载函数调用失败:', error)
-    ElMessage.error('下载过程中发生错误')
-  }
-}
-
-// 生成安全的文件名(处理中文和特殊字符)
-const generateSafeFilename = (originalName, imagePath, type) => {
-  // 如果有原始文件名,使用它(但需要处理中文)
-  if (originalName && originalName.trim()) {
-    // 如果文件名包含中文,转换为拼音或使用安全字符
-    if (/[\u4e00-\u9fa5]/.test(originalName)) {
-      // 方法1:直接使用中文(现代浏览器支持)
-      // 方法2:转换为拼音(需要拼音库)或使用时间戳
-      return encodeURIComponent(originalName) // 对中文进行编码
-    }
-    return originalName
-  }
-  
-  // 从路径提取文件名
-  const pathParts = imagePath.split('/')
-  const lastPart = pathParts[pathParts.length - 1]
-  
-  if (lastPart && lastPart.includes('.')) {
-    return lastPart
-  }
-  
-  // 默认使用时间戳
-  const timestamp = Date.now()
-  const extension = getFileExtension(imagePath)
-  return `${type}_${timestamp}.${extension}`
-}
-
-// 获取文件扩展名
-const getFileExtension = (filepath) => {
-  if (!filepath) return 'jpg'
-  const match = filepath.match(/\.([a-zA-Z0-9]+)(?:\?.*)?$/)
-  return match ? match[1].toLowerCase() : 'jpg'
-}
-
-// 直接下载函数(备用方案)
-const directDownload = (url, filename) => {
-  try {
-    const link = document.createElement('a')
-    link.href = url
-    link.download = filename
-    link.style.display = 'none'
-    document.body.appendChild(link)
-    link.click()
-    document.body.removeChild(link)
-    ElMessage.success('下载成功!')
-  } catch (error) {
-    console.error('直接下载失败:', error)
-    throw error
-  }
-}
-
-// 添加时间戳避免缓存
-const addTimestamp = (url) => {
-  if (!url) return url
-  const separator = url.includes('?') ? '&' : '?'
-  return `${url}${separator}t=${Date.now()}`
-}
-
-// 使用Blob下载(推荐,支持中文文件名)
-const downloadWithBlob = async (url, filename) => {
-  try {
-    console.log('开始Blob下载:', { url, filename })
-    
-    // 添加时间戳避免缓存
-    const urlWithTimestamp = addTimestamp(url)
-    
-    const response = await fetch(urlWithTimestamp, {
-      method: 'GET',
-      headers: {
-        'Cache-Control': 'no-cache'
-      }
-    })
-    
-    if (!response.ok) {
-      throw new Error(`HTTP ${response.status}: ${response.statusText}`)
-    }
-    
-    const blob = await response.blob()
-    
-    // 检查blob类型
-    if (blob.size === 0) {
-      throw new Error('文件内容为空')
-    }
-    
-    // 创建blob URL
-    const blobUrl = window.URL.createObjectURL(blob)
-    
-    // 创建下载链接
-    const link = document.createElement('a')
-    link.href = blobUrl
-    
-    // 处理文件名:现代浏览器支持中文文件名
-    // 如果需要更兼容,可以编码文件名
-    link.download = filename
-    link.style.display = 'none'
-    
-    document.body.appendChild(link)
-    link.click()
-    
-    // 清理
-    setTimeout(() => {
-      window.URL.revokeObjectURL(blobUrl)
-      document.body.removeChild(link)
-    }, 100)
-    
-    ElMessage.success('下载成功!')
-    
-  } catch (error) {
-    console.error('Blob下载失败:', error)
-    
-    // 备用方案1:直接下载
-    try {
-      console.log('尝试直接下载...')
-      directDownload(url, filename)
-    } catch (directError) {
-      console.error('直接下载失败:', directError)
-      
-      // 备用方案2:使用更简单的下载方法
-      try {
-        console.log('尝试使用简单下载方法...')
-        const link = document.createElement('a')
-        link.href = url
-        link.download = filename
-        link.style.display = 'none'
-        document.body.appendChild(link)
-        link.click()
-        document.body.removeChild(link)
-        ElMessage.success('下载成功!')
-      } catch (simpleError) {
-        console.error('所有方法都失败:', simpleError)
-        ElMessage.error('下载失败,请检查网络或联系管理员')
-      }
-    }
-  }
-}
-
-const searchKeyword = ref('')
-const handleSearch = async () => {
-  try {
-    const response = await product_template({ search: searchKeyword.value })
-    if (response.code === 0 && response.data) {
-      templateList.value = response.data.map(item => ({
-        id: item.id,
-        template_image_url: item.template_image_url,
-        chinese_description: item.chinese_description || '',
-        english_description: item.english_description || ''
-      }))
-      
-      // 默认选中第一个模板
-      if (templateList.value.length > 0) {
-        selectTemplate(templateList.value[0])
-      }
-    }
-  } catch (error) {
-    console.error('获取模板失败:', error)
-    templateList.value = []
-  }
-}
-
-
-
-
-
-
-
-// 弹窗显示控制
-const AdddialogVisible = ref(false)
-const productFormRef = ref()
-const submitLoading = ref(false)
-// 新增产品:选中的图片文件(点确定时随 productAdd 一起提交,不单独调 ImgUpload)
-const productImageFile = ref(null)
-
-// 表单数据
-const productForm = reactive({
-  product_name: '',
-  product_code: '',
-  create_name: '',
-  merchant_id: '',
-  product_img: '' // 预览用:blob URL 或空
-})
-
-
-
-const onADD = async() => {
-  if (!nodeid.value) {
-    ElMessage.error('请先选择商户')
-    return
-  }
-  if (productForm.product_img && productForm.product_img.startsWith('blob:')) {
-    URL.revokeObjectURL(productForm.product_img)
-  }
-  productForm.product_img = ''
-  productImageFile.value = null
-  AdddialogVisible.value = true
-  const res = await getMerchantId({
-    merchant_code: nodeid.value,
-  })
-  if (res.code === 0) {
-    productForm.merchant_id = res.data
-  }
-}
-
-
-// 将 File 转为 data:image/xxx;base64,... 字符串
-const fileToDataUrl = (file) => {
-  return new Promise((resolve, reject) => {
-    const reader = new FileReader()
-    reader.onload = () => resolve(reader.result)
-    reader.onerror = reject
-    reader.readAsDataURL(file)
-  })
-}
-
-const handleSubmit = async()=>{
-  if (!productImageFile.value) {
-    ElMessage.warning('请先选择产品图片')
-    return
-  }
-  productForm.create_name = userStore.userInfo.nickName
-  try {
-    submitLoading.value = true
-    const productImgBase64 = await fileToDataUrl(productImageFile.value)
-    const payload = {
-      product_name: productForm.product_name,
-      product_code: productForm.product_code,
-      merchant_id: productForm.merchant_id,
-      create_name: productForm.create_name,
-      product_img: productImgBase64
-    }
-    const response = await productAdd(payload)
-    if (response.code === 0) {
-      ElMessage.success('新增成功')
-      handleClose()
-    } else {
-      ElMessage.error(response.message || response.msg || '新增失败')
-    }
-  } catch (error) {
-    console.error('新增失败:', error)
-    ElMessage.error('新增失败,请联系管理员')
-  } finally {
-    submitLoading.value = false
-  }
-}
-
-// 新增产品弹窗:预览图地址(blob 或后端返回的 URL)
-const addDialogPreviewSrc = computed(() => {
-  const p = productForm.product_img
-  if (!p) return ''
-  if (p.startsWith('blob:')) return p
-  return formatImageUrl(p)
-})
-
-// 新增产品:选择图片仅做本地预览,不调上传接口;点确定时随 productAdd 一起提交
-const handleAddDialogSelectImage = (file) => {
-  const isImage = file.type.startsWith('image/')
-  const isLt5M = file.size / 1024 / 1024 < 5
-  if (!isImage) {
-    ElMessage.error('只能上传图片文件')
-    return false
-  }
-  if (!isLt5M) {
-    ElMessage.error('图片大小不能超过 5MB')
-    return false
-  }
-  if (productForm.product_img && productForm.product_img.startsWith('blob:')) {
-    URL.revokeObjectURL(productForm.product_img)
-  }
-  productImageFile.value = file
-  productForm.product_img = URL.createObjectURL(file)
-  return false // 阻止 el-upload 默认上传
-}
-
-// 打开弹窗方法(外部调用)
-const openDialog = () => {
-  // 清空表单
-  Object.keys(productForm).forEach(key => {
-    productForm[key] = ''
-  })
-  
-  dialogVisible.value = true
-  
-  // 如果有默认值可以在这里设置
-  // productForm.create_name = '默认创建人'
-}
-
-// 关闭新增产品弹窗并重置表单
-const handleClose = () => {
-  if (productForm.product_img && productForm.product_img.startsWith('blob:')) {
-    URL.revokeObjectURL(productForm.product_img)
-  }
-  productForm.product_img = ''
-  productForm.product_name = ''
-  productForm.product_code = ''
-  productImageFile.value = null
-  submitLoading.value = false
-  productFormRef.value?.resetFields()
-  AdddialogVisible.value = false
-}
-
-// 删除图片(仅清空预览与文件,不调接口)
-const handleRemoveImage = () => {
-  if (productForm.product_img && productForm.product_img.startsWith('blob:')) {
-    URL.revokeObjectURL(productForm.product_img)
-  }
-  productForm.product_img = ''
-  productImageFile.value = null
-}
-
-// 暴露方法给父组件
-defineExpose({
-  openDialog
-})
-
-
-// onMounted(() => {
-//   getTableData()
-// })
-</script>
-
-<style scoped>
-  /* 保持原有通用样式 */
-  :deep(.el-table td .cell) {
-    line-height: 22px !important;
-  }
-  /* :deep(.el-dialog__body) {
-    padding: 10px 20px;
-  } */
-  .gva-pagination {
-    margin-top: 10px;
-    text-align: right;
-  }
-
-  /* 新增产品弹窗 - 上传与预览 */
-  .add-dialog-upload-wrap {
-    width: 100%;
-  }
-  .add-dialog-preview-box {
-    border: 1px solid #e4e7ed;
-    border-radius: 8px;
-    overflow: hidden;
-    background: #fafafa;
-  }
-  .add-dialog-preview-img {
-    width: 100%;
-    height: 200px;
-    display: flex;
-    align-items: center;
-    justify-content: center;
-    background: #f5f7fa;
-  }
-  .add-dialog-preview-img-inner {
-    max-width: 100%;
-    max-height: 200px;
-    width: auto;
-    height: auto;
-    object-fit: contain;
-    display: block;
-  }
-  .add-dialog-preview-actions {
-    display: flex;
-    align-items: center;
-    justify-content: center;
-    gap: 12px;
-    padding: 12px;
-    border-top: 1px solid #e4e7ed;
-    background: #fff;
-  }
-  .add-dialog-upload-area {
-    width: 100%;
-  }
-  .add-dialog-upload-area :deep(.el-upload) {
-    width: 100%;
-    display: block;
-  }
-  .add-dialog-upload-inner {
-    width: 100%;
-    height: 160px;
-    border: 2px dashed #dcdfe6;
-    border-radius: 8px;
-    display: flex;
-    flex-direction: column;
-    align-items: center;
-    justify-content: center;
-    gap: 8px;
-    background: #fafafa;
-    color: #606266;
-    transition: border-color 0.2s, background 0.2s;
-  }
-  .add-dialog-upload-inner:hover {
-    border-color: #409eff;
-    background: #ecf5ff;
-    color: #409eff;
-  }
-  .add-dialog-upload-icon {
-    font-size: 36px;
-    color: #c0c4cc;
-  }
-  .add-dialog-upload-inner:hover .add-dialog-upload-icon {
-    color: #409eff;
-  }
-  .add-dialog-upload-text {
-    font-size: 14px;
-    font-weight: 500;
-  }
-  .add-dialog-upload-tip {
-    font-size: 12px;
-    color: #909399;
-  }
-  :deep(.el-table__body tr.current-row) > td {
-    background: #ff80ff !important;
-  }
-  .JKWTree-tree {
-    background-color: #fff;
-    padding: 10px;
-    border-right: 1px solid #e4e7ed;
-  }
-  .JKWTree-tree h3 {
-    font-size: 15px;
-    font-weight: 700;
-    margin: 10px 0;
-    padding-bottom: 10px;
-    border-bottom: 1px solid #e4e7ed;
-  }
-  
-  /* 编辑弹窗三列布局:自适应,小屏横向滚动防跑偏 */
-  .image-edit-container {
-    display: flex;
-    height: 94vh;
-    padding-top: 20px;
-    gap: 0;
-    width: 100%;
-    overflow-x: auto;
-    overflow-y: hidden;
-    box-sizing: border-box;
-  }
-
-  .left-column {
-    flex: 0.7;
-    min-width: 280px;
-    max-width: 560px;
-    display: flex;
-    flex-direction: column;
-    gap: 15px;
-    padding: 15px;
-    overflow-y: auto;
-    overflow-x: hidden;
-    flex-shrink: 1;
-  }
-
-  .middle-column {
-    width: 430px;
-    min-width: 380px;
-    flex-shrink: 0;
-    border-left: 1px solid #e4e7ed;
-    border-right: 1px solid #e4e7ed;
-    padding: 15px 12px;
-    position: relative;
-    box-sizing: border-box;
-    background: #fff;
-    overflow-y: auto;
-    overflow-x: hidden;
-  }
-
-  .right-column {
-    flex: 1;
-    min-width: 280px;
-    min-height: 0;
-    flex-shrink: 1;
-    padding: 0 12px 0 15px;
-    display: flex;
-    flex-direction: column;
-    overflow: hidden;
-  }
-  
-  .image-comparison-section {
-    flex: none;
-    display: flex;
-    flex-direction: row;
-    align-items: flex-start;
-    gap: 16px;
-    min-height: 200px;
-  }
-
-  .upload-image-box {
-    width: 200px;
-    height: 200px;
-    max-width: 100%;
-    display: flex;
-    justify-content: center;
-    align-items: center;
-    background-color: #f9f9f9;
-    border-radius: 4px;
-    overflow: hidden;
-    border: 1px solid #e4e7ed;
-  }
-
-  .image-placeholder-small {
-    width: 100px;
-    height: 100px;
-    display: flex;
-    flex-direction: column;
-    justify-content: center;
-    align-items: center;
-    background-color: #f9f9f9;
-    border-radius: 4px;
-    border: 1px solid #e4e7ed;
-  }
-
-  .case-links-column {
-    display: flex;
-    flex-direction: column;
-    align-items: flex-start;
-    justify-content: space-between;
-    flex-shrink: 0;
-    height: 200px;
-  }
-
-  .case-link-btn {
-    padding: 0 !important;
-    font-size: 14px !important;
-    font-weight: normal !important;
-    color: #409eff !important;
-  }
-  
-  .image-item {
-    flex: 1;
-    display: flex;
-    flex-direction: column;
-    min-height: 0; /* 防止溢出 */
-  }
-  
-  .image-title {
-    font-weight: bold;
-    margin-bottom: 10px;
-    color: #409eff;
-  }
-  
-  .image-preview {
-    flex: 1;
-    overflow: hidden;
-    display: flex;
-    flex-direction: column;
-    min-height: 0; /* 防止溢出 */
-  }
-  
-  .image-preview img {
-    width: 100%;
-    height: 160px; /* 固定高度,确保不占满屏幕 */
-    object-fit: contain;
-    background: #f5f7fa;
-  }
-  
-  .image-placeholder {
-    height: 160px;
-    display: flex;
-    flex-direction: column;
-    align-items: center;
-    justify-content: center;
-    background: #f5f7fa;
-    color: #909399;
-  }
-  
-  .image-info {
-    padding: 8px;
-    background: #f5f7fa;
-    font-size: 12px;
-    color: #606266;
-    border-top: 1px solid #dcdfe6;
-  }
-  
-  .image-actions {
-    display: flex;
-    justify-content: center;
-    padding: 10px 0;
-  }
-  
-  .edit-section {
-    overflow: hidden; /* 防止溢出 */
-  }
-  
-  .edit-form {
-    height: 100%;
-  }
-  
-  .edit-form :deep(.el-form) {
-    height: 100%;
-  }
-  
-  .edit-form :deep(.el-form-item) {
-    height: 100%;
-    margin-bottom: 0;
-  }
-  
-  .edit-form :deep(.el-textarea__inner) {
-    height: 100% !important;
-    resize: none;
-  }
-  
-  :deep(.el-textarea__inner) {
-    resize: none !important;
-  }
-  
-  .right-column {
-    display: flex;
-    flex-direction: column;
-    min-height: 0; /* 防止溢出 */
-  }
-  
-  .right-template {
-    flex: 1;
-    display: flex;
-    flex-direction: column;
-    min-height: 0; /* 防止溢出 */
-  }
-  
-  .template-header {
-    margin-bottom: 15px;
-    padding-bottom: 10px;
-    border-bottom: 1px solid #e4e7ed;
-  }
-  
-  .template-header h4 {
-    margin: 0;
-    font-size: 16px;
-  }
-  
-  .template-list-container {
-    flex: 1;
-    min-height: 0;
-    display: flex;
-    flex-direction: column;
-  }
-  
-  .template-list {
-    flex: 1;
-    display: flex;
-    flex-direction: row;
-    flex-wrap: wrap;
-    gap: 10px;
-    overflow-y: auto;
-    min-height: 0; /* 防止溢出 */
-    padding: 5px;
-  }
-  
-  .template-item {
-    display: flex;
-    flex-direction: column;
-    width: calc(33.33% - 7px);
-    min-width: 100px; /* 笔记本小屏时不被压得过窄 */
-    padding: 10px;
-    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 {
-    border-color: #409eff;
-    background: #f5faff;
-  }
-  
-  .template-item.active {
-    border-color: #409eff;
-    background: #ecf5ff;
-    border-width: 2px;
-  }
-  
-  .template-thumbnail {
-    position: relative;
-    width: 100%;
-    height: 120px;
-    margin-bottom: 8px;
-    border-radius: 4px;
-    overflow: hidden;
-    background: #f5f7fa;
-  }
-  
-  .template-thumbnail img {
-    width: 100%;
-    height: 100%;
-    object-fit: contain;
-  }
-  
-  .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;
-    left: 4px;
-    background: rgba(0, 0, 0, 0.7);
-    color: white;
-    padding: 2px 6px;
-    border-radius: 3px;
-    font-size: 11px;
-    font-weight: bold;
-  }
-  
-  .image-preview .image-download-btn {
-    opacity: 0;
-  }
-  
-  .image-preview:hover .image-download-btn,
-  .image-preview > div:hover .image-download-btn,
-  .image-preview .image-download-btn:hover {
-    opacity: 1 !important;
-  }
-  
-  .image-download-btn:hover {
-    background: rgba(0, 0, 0, 0.8) !important;
-  }
-  
-  /* 修改单选框为方形 */
-  .el-radio__input.is-border {
-    border-radius: 2px !important;
-  }
-  
-  .el-radio__input.is-border .el-radio__inner {
-    border-radius: 2px !important;
-  }
-  
-  .template-desc {
-    flex: 1;
-    font-size: 12px;
-    color: #606266;
-    line-height: 1.4;
-    overflow: hidden;
-    text-overflow: ellipsis;
-    display: -webkit-box;
-    -webkit-line-clamp: 2;
-    -webkit-box-orient: vertical;
-  }
-  
-  .empty-templates {
-    flex: 1;
-    display: flex;
-    flex-direction: column;
-    align-items: center;
-    justify-content: center;
-    color: #909399;
-  }
-  
-  .empty-templates .el-icon {
-    margin-bottom: 10px;
-  }
-  
-  .empty-search {
-    width: 100%;
-    height: 100%;
-    display: flex;
-    flex-direction: column;
-    align-items: center;
-    justify-content: center;
-    padding: 50px 20px;
-    color: #909399;
-  }
-  
-  .empty-search .el-icon {
-    margin-bottom: 15px;
-    color: #c0c4cc;
-  }
-  
-  .empty-search p {
-    margin: 0;
-    font-size: 14px;
-  }
-  </style>

+ 59 - 0
src/view/performance/QualityAssessment/ProductDesign.vue

@@ -0,0 +1,59 @@
+<template>
+  <div class="product-design-page">
+    <div class="product-design-header">
+      <el-button type="primary" plain @click="$emit('back')">
+        <el-icon><ArrowLeft /></el-icon>
+        返回
+      </el-button>
+      <span class="product-design-title">新增产品</span>
+    </div>
+    <div class="product-design-body">
+      <p class="product-design-tip">此处为产品设计页面,可根据业务需要补充表单或设计内容。</p>
+      <p v-if="nodeId" class="product-design-info">当前商户:{{ nodeId }}</p>
+      <p v-if="merchantId" class="product-design-info">商户ID:{{ merchantId }}</p>
+    </div>
+  </div>
+</template>
+
+<script setup>
+import { ArrowLeft } from '@element-plus/icons-vue'
+
+defineProps({
+  nodeId: { type: String, default: '' },
+  merchantId: { type: String, default: '' }
+})
+defineEmits(['back'])
+</script>
+
+<style scoped>
+.product-design-page {
+  min-height: 100%;
+  background: #fff;
+  padding: 16px;
+}
+.product-design-header {
+  display: flex;
+  align-items: center;
+  gap: 16px;
+  margin-bottom: 20px;
+  padding-bottom: 12px;
+  border-bottom: 1px solid #e5e5e5;
+}
+.product-design-title {
+  font-size: 18px;
+  font-weight: 600;
+  color: #303133;
+}
+.product-design-body {
+  padding: 24px 0;
+}
+.product-design-tip {
+  color: #606266;
+  margin-bottom: 12px;
+}
+.product-design-info {
+  font-size: 13px;
+  color: #909399;
+  margin: 4px 0;
+}
+</style>

+ 0 - 551
src/view/performance/QualityAssessment/Shop.vue

@@ -1,551 +0,0 @@
-<template>
-  <div>
-    <!-- <warning-bar title="注:右上角头像下拉可切换角色" /> -->
-    <div class="gva-table-box">
-      <div class="gva-btn-list">
-        <el-button
-          type="primary"
-          icon="plus"
-          @click="addUser"
-        >新增商户</el-button>
-      </div>
-      <el-table
-        :data="tableData"
-        row-key="ID"
-      >
-        <!-- <el-table-column
-          align="left"
-          label="头像"
-          min-width="75"
-        >
-          <template #default="scope">
-            <CustomPic
-              style="margin-top:8px"
-              :pic-src="scope.row.headerImg"
-            />
-          </template>
-        </el-table-column> -->
-        <el-table-column
-          align="left"
-          label="ID"
-          min-width="50"
-          prop="id"
-        />
-        <el-table-column
-          align="left"
-          label="商户名"
-          min-width="150"
-          prop="商户名"
-        />
-        <el-table-column
-          align="left"
-          label="商户编码"
-          min-width="150"
-          prop="商户编码"
-        />
-        <el-table-column
-          align="left"
-          label="联系人"
-          min-width="180"
-          prop="联系人"
-        />
-        <el-table-column
-          align="left"
-          label="联系电话"
-          min-width="180"
-          prop="联系电话"
-        />
-        <el-table-column
-          align="left"
-          label="地址"
-          min-width="180"
-          prop="地址"
-        />
-        <el-table-column
-          align="left"
-          label="邮箱"
-          min-width="180"
-          prop="邮箱"
-        />
-        <el-table-column
-          align="left"
-          label="备注"
-          min-width="180"
-          prop="备注"
-        />
-        <el-table-column
-          align="left"
-          label="创建时间"
-          min-width="180"
-          prop="创建时间"
-        />
-        <el-table-column
-          align="left"
-          label="创建人"
-          min-width="180"
-          prop="创建人"
-        />
-        <el-table-column
-          align="left"
-          label="更新时间"
-          min-width="180"
-          prop="更新时间"
-        />
-        <el-table-column
-          align="left"
-          label="状态"
-          min-width="180"
-          prop="状态"
-        />
-        <!-- <el-table-column
-          align="left"
-          label="启用"
-          min-width="150"
-        >
-          <template #default="scope">
-            <el-switch
-              v-model="scope.row.enable"
-              inline-prompt
-              :active-value="1"
-              :inactive-value="2"
-              @change="()=>{switchEnable(scope.row)}"
-            />
-          </template>
-        </el-table-column> -->
-
-        <el-table-column
-          label="操作"
-          min-width="250"
-          fixed="right"
-        >
-          <template #default="scope">
-            <el-popover
-              v-model:visible="scope.row.visible"
-              placement="top"
-              width="160"
-            >
-              <p>确定要删除此用户吗</p>
-              <div style="text-align: right; margin-top: 8px;">
-                <el-button
-                  type="primary"
-                  link
-                  @click="scope.row.visible = false"
-                >取消</el-button>
-                <el-button
-                  type="primary"
-                  @click="deleteUserFunc(scope.row)"
-                >确定</el-button>
-              </div>
-              <template #reference>
-                <el-button
-                  type="primary"
-                  link
-                  icon="delete"
-                >删除</el-button>
-              </template>
-            </el-popover>
-            <el-button
-              type="primary"
-              link
-              icon="edit"
-              @click="openEdit(scope.row)"
-            >编辑</el-button>
-            <el-button
-              type="primary"
-              link
-              icon="magic-stick"
-              @click="resetPasswordFunc(scope.row)"
-            >重置密码</el-button>
-          </template>
-        </el-table-column>
-
-      </el-table>
-      <div class="gva-pagination">
-        <el-pagination
-          :current-page="page"
-          :page-size="pageSize"
-          :page-sizes="[10, 30, 50, 100]"
-          :total="total"
-          layout="total, sizes, prev, pager, next, jumper"
-          @current-change="handleCurrentChange"
-          @size-change="handleSizeChange"
-        />
-      </div>
-    </div>
-    <el-dialog
-      v-model="addUserDialog"
-      title="商户"
-      :show-close="false"
-      :close-on-press-escape="false"
-      :close-on-click-modal="false"
-    >
-      <div style="height:60vh;overflow:auto;padding:0 12px;">
-        <el-form
-          ref="userForm"
-          :rules="rules"
-          :model="userInfo"
-          label-width="80px"
-        >
-          <el-form-item
-            label="商户名"
-            prop="商户名称"
-          >
-            <el-input v-model="userInfo.merchant_name" />
-          </el-form-item>
-
-          <el-form-item
-            label="商户编码"
-            prop="merchant_code"
-          >
-            <el-input v-model="userInfo.merchant_code" />
-          </el-form-item>
-
-          <!-- <el-form-item
-            v-if="dialogFlag === 'add'"
-            label="密码"
-            prop="password"
-          >
-            <el-input v-model="userInfo.password" />
-          </el-form-item> -->
-
-          <el-form-item
-            label="联系人"
-            prop="联系人"
-          >
-            <el-input v-model="userInfo.contact_person" />
-          </el-form-item>
-          <el-form-item
-            label="联系电话"
-            prop="联系号码"
-          >
-            <el-input v-model="userInfo.contact_phone" />
-          </el-form-item>
-
-          <el-form-item
-            label="地址"
-            prop="address"
-          >
-            <el-input v-model="userInfo.address" />
-          </el-form-item>
-
-          <el-form-item
-            label="邮箱"
-            prop="email"
-          >
-            <el-input v-model="userInfo.email" />
-          </el-form-item>
-
-          <el-form-item
-            label="备注"
-            prop="remark"
-          >
-            <el-input v-model="userInfo.remark" />
-          </el-form-item>
-
-        </el-form>
-
-      </div>
-
-      <template #footer>
-        <div class="dialog-footer">
-          <el-button @click="closeAddUserDialog">取 消</el-button>
-          <el-button
-            type="primary"
-            @click="enterAddUserDialog"
-          >确 定</el-button>
-        </div>
-      </template>
-    </el-dialog>
-    <ChooseImg
-      ref="chooseImg"
-      :target="userInfo"
-      :target-key="`headerImg`"
-    />
-  </div>
-</template>
-
-
-<script setup>
-
-import {
-  getUserList,
-  setUserAuthorities,
-  register,
-  deleteUser
-} from '@/api/user'
-
-import { getAuthorityList } from '@/api/authority'
-
-import { merchantList, merchantDetail,merchantAdd,merchantEdit,merchantDelete, merchantChangeStatus, merchantBatchChangeStatus, LogList } from '@/api/mes/job'
-import CustomPic from '@/components/customPic/index.vue'
-import ChooseImg from '@/components/chooseImg/index.vue'
-import WarningBar from '@/components/warningBar/warningBar.vue'
-import { setUserInfo, resetPassword } from '@/api/user.js'
-import { useUserStore } from '@/pinia/modules/user'
-import { nextTick, ref, watch } from 'vue'
-import { ElMessage, ElMessageBox } from 'element-plus'
-
-defineOptions({
-  name: 'User',
-})
-//获取登录用户信息
-const userStore = useUserStore()
-const _username = ref('')
-_username.value = userStore.userInfo.userName + '/' + userStore.userInfo.nickName
-console.log('获取用户信息',_username.value)
-console.log('获取用户名称',userStore.userInfo.nickName)
-
-const path = ref(import.meta.env.VITE_BASE_API + '/')
-// 初始化相关
-const setAuthorityOptions = (AuthorityData, optionsData) => {
-  AuthorityData &&
-        AuthorityData.forEach(item => {
-          if (item.children && item.children.length) {
-            const option = {
-              authorityId: item.authorityId,
-              authorityName: item.authorityName,
-              children: []
-            }
-            setAuthorityOptions(item.children, option.children)
-            optionsData.push(option)
-          } else {
-            const option = {
-              authorityId: item.authorityId,
-              authorityName: item.authorityName
-            }
-            optionsData.push(option)
-          }
-        })
-}
-
-const page = ref(1)
-const total = ref(0)
-const pageSize = ref(10)
-const tableData = ref([])
-// 分页
-const handleSizeChange = (val) => {
-  pageSize.value = val
-  getTableData()
-}
-
-const handleCurrentChange = (val) => {
-  page.value = val
-  getTableData()
-}
-
-// 查询
-const getTableData = async() => {
-  const table = await merchantList({ page: page.value, pageSize: pageSize.value })
-  if (table.code === 0) {
-    tableData.value = table.data.data
-    total.value = table.data.count
-    // page.value = table.data.page
-    // pageSize.value = table.data.pageSize
-  }
-}
-
-watch(() => tableData.value, () => {
-  setAuthorityIds()
-})
-
-const initPage = async() => {
-  getTableData()
-  const res = await getAuthorityList({ page: 1, pageSize: 999 })
-  setOptions(res.data.list)
-}
-
-initPage()
-
-const resetPasswordFunc = (row) => {
-  ElMessageBox.confirm(
-    '是否将此用户密码重置为123456?',
-    '警告',
-    {
-      confirmButtonText: '确定',
-      cancelButtonText: '取消',
-      type: 'warning',
-    }
-  ).then(async() => {
-    const res = await resetPassword({
-      ID: row.ID,
-    })
-    if (res.code === 0) {
-      ElMessage({
-        type: 'success',
-        message: res.msg,
-      })
-    } else {
-      ElMessage({
-        type: 'error',
-        message: res.msg,
-      })
-    }
-  })
-}
-const setAuthorityIds = () => {
-  tableData.value && tableData.value.forEach((user) => {
-    user.authorityIds = user.authorities && user.authorities.map(i => {
-      return i.authorityId
-    })
-  })
-}
-
-const chooseImg = ref(null)
-const openHeaderChange = () => {
-  chooseImg.value.open()
-}
-
-const authOptions = ref([])
-const setOptions = (authData) => {
-  authOptions.value = []
-  setAuthorityOptions(authData, authOptions.value)
-}
-
-const deleteUserFunc = async(row) => {
-  const res = await deleteUser({ id: row.ID })
-  if (res.code === 0) {
-    ElMessage.success('删除成功')
-    row.visible = false
-    await getTableData()
-  }
-}
-
-// 弹窗相关
-const userInfo = ref({})
-
-const rules = ref({
-  userName: [
-    { required: true, message: '请输入用户名', trigger: 'blur' },
-    { min: 3, message: '最低3位字符', trigger: 'blur' }
-  ],
-  password: [
-    { required: true, message: '请输入用户密码', trigger: 'blur' },
-    { min: 0, message: '最低0位字符', trigger: 'blur' }
-  ],
-  nickName: [
-    { required: true, message: '请输入用户昵称', trigger: 'blur' }
-  ],
-  phone: [
-    { pattern: /^1([38][0-9]|4[014-9]|[59][0-35-9]|6[2567]|7[0-8])\d{8}$/, message: '请输入合法手机号', trigger: 'blur' },
-  ],
-  email: [
-    { pattern: /^([0-9A-Za-z\-_.]+)@([0-9a-z]+\.[a-z]{2,3}(\.[a-z]{2})?)$/g, message: '请输入正确的邮箱', trigger: 'blur' },
-  ],
-  authorityId: [
-    { required: true, message: '请选择用户角色', trigger: 'blur' }
-  ]
-})
-const userForm = ref(null)
-const enterAddUserDialog = async() => {
-  userInfo.value.createName = userStore.userInfo.nickName
-  userInfo.value.createCode = userStore.userInfo.userName
-  userForm.value.validate(async valid => {
-    if (valid) {
-      const req = {
-        ...userInfo.value
-      }
-      if (dialogFlag.value === 'add') {
-        console.log('创建用户', req)
-
-        const res = await merchantAdd(req)
-        if (res.code === 0) {
-          ElMessage({ type: 'success', message: '创建成功' })
-          await getTableData()
-          closeAddUserDialog()
-        }
-      }
-      if (dialogFlag.value === 'edit') {
-        console.log('编辑用户', req)
-        return;
-        const res = await merchantEdit(req)
-        if (res.code === 0) {
-          ElMessage({ type: 'success', message: '编辑成功' })
-          await getTableData()
-          closeAddUserDialog()
-        }
-      }
-    }
-  })
-}
-
-const addUserDialog = ref(false)
-const closeAddUserDialog = () => {
-  userForm.value.resetFields()
-  addUserDialog.value = false
-}
-
-const dialogFlag = ref('add')
-
-const addUser = () => {
-  dialogFlag.value = 'add'
-  addUserDialog.value = true
-}
-
-// const tempAuth = {}
-// const changeAuthority = async(row, flag, removeAuth) => {
-//   if (flag) {
-//     if (!removeAuth) {
-//       tempAuth[row.ID] = [...row.authorityIds]
-//     }
-//     return
-//   }
-//   await nextTick()
-//   const res = await setUserAuthorities({
-//     ID: row.ID,
-//     authorityIds: row.authorityIds
-//   })
-//   if (res.code === 0) {
-//     ElMessage({ type: 'success', message: '角色设置成功' })
-//   } else {
-//     if (!removeAuth) {
-//       row.authorityIds = [...tempAuth[row.ID]]
-//       delete tempAuth[row.ID]
-//     } else {
-//       row.authorityIds = [removeAuth, ...row.authorityIds]
-//     }
-//   }
-// }
-
-const openEdit = async(row) => {
-  dialogFlag.value = 'edit'
-  console.log('编辑用户', row)
-  const res = await merchantDetail({ id: row.id })
-  if (res.code === 0) {
-    // 将中文字段映射到英文变量名
-    userInfo.value = {
-      merchant_name: res.data.商户名称,
-      merchant_code: res.data.商户编码,
-      contact_person: res.data.联系人,
-      contact_phone: res.data.联系号码,
-      address: res.data.地址,
-      email: res.data.邮箱,
-      remark: res.data.备注,
-      id: res.data.id
-    }
-    console.log('编辑用户', userInfo.value)
-  }
-  addUserDialog.value = true
-}
-
-// const switchEnable = async(row) => {
-//   userInfo.value = JSON.parse(JSON.stringify(row))
-//   await nextTick()
-//   const req = {
-//     ...userInfo.value
-//   }
-//   const res = await setUserInfo(req)
-//   if (res.code === 0) {
-//     ElMessage({ type: 'success', message: `${req.enable === 2 ? '禁用' : '启用'}成功` })
-//     await getTableData()
-//     userInfo.value.headerImg = ''
-//     userInfo.value.authorityIds = []
-//   }
-// }
-
-</script>
-
-<style lang="scss">
-  .header-img-box {
-    @apply w-52 h-52 border border-solid border-gray-300 rounded-xl flex justify-center items-center cursor-pointer;
- }
-</style>

+ 0 - 170
src/view/performance/QualityAssessment/patternList.vue

@@ -1,170 +0,0 @@
-<template>
-  <div>
-    <div class="gva-table-box">
-      <el-form :inline="true" style="padding: 20px;">
-        <!-- 店铺下拉 -->
-        <el-form-item label="选择店铺">
-          <el-select v-model="shopValue" placeholder="请选择店铺" clearable style="width: 180px;">
-            <el-option v-for="item in shopOptions" :key="item.value" :label="item.label" :value="item.value" />
-          </el-select>
-        </el-form-item>
-
-        <!-- SKC输入 -->
-        <el-form-item label="SKC编码">
-          <el-input v-model="searchInfo" placeholder="请输入SKC编码" clearable style="width: 180px;" />
-        </el-form-item>
-
-        <!-- 查询按钮 -->
-        <el-form-item>
-          <el-button type="primary" @click="onSubmit">查询</el-button>
-        </el-form-item>
-      </el-form>
-
-      <!-- 表格 -->
-      <el-table
-        ref="multipleTable"
-        style="width: 100%; height: 65vh"
-        :row-style="{ height: '20px' }"
-        :header-cell-style="{ padding: '0px' }"
-        :cell-style="{ padding: '0px' }"
-        :header-row-style="{ height: '20px' }"
-        border
-        tooltip-effect="dark"
-        :data="tableData"
-        row-key="ID"
-        highlight-current-row="true"
-        :cell-class-name="tableDataCellClass"
-        @row-click="Clickonthetable"
-        @row-dblclick="Doubleclickonthetable"
-        @selection-change="cjsSelectionChange"
-        :show-overflow-tooltip="true"
-      >
-        <el-table-column align="center" type="selection" width="30" />
-        <el-table-column align="left" sortable label="订单编号" prop="订单编号" width="105" />
-      </el-table>
-
-      <!-- 分页 -->
-      <div class="gva-pagination">
-        <el-pagination
-          @size-change="handleSizeChange"
-          @current-change="handleCurrentChange"
-          :current-page="page"
-          :page-sizes="[10, 30, 50, 100]"
-          :page-size="pageSize"
-          layout="total, sizes, prev, pager, next, jumper"
-          :total="total"
-        />
-      </div>
-    </div>
-  </div>
-</template>
-
-<script setup>
-import { ref, reactive, onMounted } from 'vue'
-import { ElMessage } from 'element-plus'
-import { useUserStore } from '@/pinia/modules/user'
-import {PatternApi} from '@/api/mes/job'
-defineOptions({ name: '06PackingDocuments' })
-
-// 用户信息
-const userStore = useUserStore()
-const _username = ref(`${userStore.userInfo.userName}/${userStore.userInfo.nickName}`)
-console.log('用户名称:', _username.value)
-
-// 当前日期
-const today = new Date()
-const year = today.getFullYear()
-const month = String(today.getMonth() + 1).padStart(2, '0')
-const day = String(today.getDate()).padStart(2, '0')
-const hours = String(today.getHours()).padStart(2, '0')
-const minutes = String(today.getMinutes()).padStart(2, '0')
-const seconds = String(today.getSeconds()).padStart(2, '0')
-const currentDate = `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`
-const currentDates = `${year}-${month}-${day}`
-
-// 下拉框
-const shopValue = ref('')
-const shopOptions = ref([
-  { label: 'hengda xiaodian', value: '634418222212751' },
-  { label: 'LuxePanels', value: 'LuxePanels' }
-])
-
-// 搜索框
-const searchInfo = ref('')
-
-// 表格数据
-const tableData = reactive([])
-
-// 分页
-const total = ref(0)
-const page = ref(1)
-const pageSize = ref(10)
-
-// 查询逻辑
-const onSubmit = async () => {
-  console.log('查询触发:')
-  console.log('店铺:', shopValue.value)
-  console.log('SKC:', searchInfo.value)
-  
-  const res = await PatternApi({ pattern_id: shopValue.value });
-  console.log(res)
-}
-
-// 表格交互
-const Clickonthetable = (row) => {
-  console.log('点击行:', row)
-}
-const Doubleclickonthetable = (row) => {
-  console.log('双击行:', row)
-}
-const cjsSelectionChange = (row) => {
-  console.log('选择变更:', row)
-}
-const tableDataCellClass = () => {
-  return ''
-}
-
-// 分页事件
-const handleCurrentChange = (val) => {
-  page.value = val
-}
-const handleSizeChange = (val) => {
-  pageSize.value = val
-}
-</script>
-
-<style scoped>
-:deep(.el-table__body .warning-row) {
-  background: #FFFF80 !important;
-}
-:deep(.el-table__body tr.current-row)>td {
-  background: #ff80ff !important;
-}
-:deep(.el-table .bg-yellow) {
-  background: yellow;
-}
-:deep(.el-table td .cell) {
-  line-height: 25px !important;
-}
-:deep(.el-tabs__header) {
-  margin-bottom: 0;
-}
-.search {
-  margin-left: 0px !important;
-  margin-right: 10px !important;
-}
-.bt {
-  margin-left: 2px !important;
-  padding: 3px !important;
-  font-size: 12px;
-}
-.el-tabs__header {
-  margin: 0px !important;
-}
-.gva-table-box {
-  padding: 0px !important;
-}
-.mab {
-  margin-bottom: 5px;
-}
-</style>

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