|
@@ -16,7 +16,7 @@
|
|
|
<!-- 左侧树形结构 -->
|
|
<!-- 左侧树形结构 -->
|
|
|
<template v-if="userStore.userInfo.nickName === '超级管理员'">
|
|
<template v-if="userStore.userInfo.nickName === '超级管理员'">
|
|
|
<layout-sider :resize-directions="['right']" :width="290" style="margin-right: 10px">
|
|
<layout-sider :resize-directions="['right']" :width="290" style="margin-right: 10px">
|
|
|
- <div class="JKWTree-tree" style="height: 200px;width:100vh">
|
|
|
|
|
|
|
+ <div class="JKWTree-tree" style="height: 200px;">
|
|
|
<h3>商户名称</h3>
|
|
<h3>商户名称</h3>
|
|
|
<el-tree :data="treeData" class="treecolor" @node-click="handleNodeClick"></el-tree>
|
|
<el-tree :data="treeData" class="treecolor" @node-click="handleNodeClick"></el-tree>
|
|
|
</div>
|
|
</div>
|
|
@@ -95,19 +95,27 @@
|
|
|
</layout>
|
|
</layout>
|
|
|
|
|
|
|
|
<el-dialog v-model="editDialogVisible" title="" fullscreen :modal="true" :show-close="false" @close="handleDialogClose">
|
|
<el-dialog v-model="editDialogVisible" title="" fullscreen :modal="true" :show-close="false" @close="handleDialogClose">
|
|
|
- <div class="image-edit-container" style="display: flex; height: 94vh; overflow: hidden;">
|
|
|
|
|
|
|
+ <!-- 关闭按钮 -->
|
|
|
|
|
+ <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" style="display: flex; height: 94vh; overflow: hidden; padding-top: 20px;">
|
|
|
<!-- 左侧:原图新图 + 输入框 -->
|
|
<!-- 左侧:原图新图 + 输入框 -->
|
|
|
- <div class="left-column" style="flex: 1; display: flex; flex-direction: column; gap: 15px; padding: 15px; overflow-y: hidden;">
|
|
|
|
|
|
|
+ <div class="left-column" style="flex: 0.7; display: flex; flex-direction: column; gap: 15px; padding: 15px; overflow-y: hidden;">
|
|
|
|
|
+ <!-- 标题 -->
|
|
|
|
|
+ <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" style="display: flex; gap: 20px;">
|
|
<div class="image-comparison-section" style="display: flex; gap: 20px;">
|
|
|
<!-- 原图区域 -->
|
|
<!-- 原图区域 -->
|
|
|
- <div class="image-preview" style="flex: 1; min-width: 120px;">
|
|
|
|
|
- <h3 style="margin-top: 0; margin-bottom: 8px; font-size: 14px; font-weight: bold; color: #303133;">上传商品白底图</h3>
|
|
|
|
|
|
|
+ <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>
|
|
|
<el-button
|
|
<el-button
|
|
|
type="text"
|
|
type="text"
|
|
|
size="small"
|
|
size="small"
|
|
|
@click="toggleProductExample"
|
|
@click="toggleProductExample"
|
|
|
- style="padding: 0; font-size: 14px; font-weight: normal; color: #409eff;margin-left:330px"
|
|
|
|
|
|
|
+ style="padding: 0; font-size: 14px; font-weight: normal; color: #409eff; align-self: flex-end; margin-bottom: 10px;margin-right: 110px;"
|
|
|
>
|
|
>
|
|
|
<template #icon>
|
|
<template #icon>
|
|
|
<el-icon :size="16">
|
|
<el-icon :size="16">
|
|
@@ -147,51 +155,28 @@
|
|
|
</el-button>
|
|
</el-button>
|
|
|
</div>
|
|
</div>
|
|
|
|
|
|
|
|
- <!-- 新图区域 -->
|
|
|
|
|
- <div class="image-preview" style="flex: 1; min-width: 120px;">
|
|
|
|
|
- <h3 style="margin-top: 0; margin-bottom: 8px; font-size: 14px; font-weight: bold; color: #303133;">生成效果图</h3>
|
|
|
|
|
- <div v-if="newImages.length > 0" style="display: flex; gap: 8px; flex-wrap: wrap;">
|
|
|
|
|
- <div v-for="(image, index) in newImages" :key="index" style="flex: 0 0 100px; height: 100px;">
|
|
|
|
|
- <div style="width: 100%; height: 100%; display: flex; justify-content: center; align-items: center; background-color: #f9f9f9; border-radius: 4px; overflow: hidden; border: 1px solid #e4e7ed;">
|
|
|
|
|
- <el-image
|
|
|
|
|
- :src="formatImageUrl(image.url)"
|
|
|
|
|
- style="width: 100%; height: 100%; cursor: pointer;"
|
|
|
|
|
- fit="contain"
|
|
|
|
|
- @click="updateProductImage(image.url)"
|
|
|
|
|
- />
|
|
|
|
|
- </div>
|
|
|
|
|
- </div>
|
|
|
|
|
- </div>
|
|
|
|
|
- <div v-else-if="editFormData.new_image_url" style="width: 200px; height: 200px; display: flex; justify-content: center; align-items: center; background-color: #f9f9f9; border-radius: 4px; overflow: hidden; border: 1px solid #e4e7ed;">
|
|
|
|
|
- <el-image
|
|
|
|
|
- :src="formatImageUrl(editFormData.new_image_url)"
|
|
|
|
|
- style="width: 100%; height: 100%; cursor: pointer;"
|
|
|
|
|
- fit="contain"
|
|
|
|
|
- @click="updateProductImage(editFormData.new_image_url)"
|
|
|
|
|
- />
|
|
|
|
|
- </div>
|
|
|
|
|
- <div v-else class="image-placeholder" style="width: 200px; height: 200px; display: flex; flex-direction: column; justify-content: center; align-items: center; background-color: #f9f9f9; border-radius: 4px; border: 1px solid #e4e7ed;">
|
|
|
|
|
- <el-icon :size="30"><Picture /></el-icon>
|
|
|
|
|
- <span style="margin-top: 5px; font-size: 10px;">暂无新图</span>
|
|
|
|
|
- </div>
|
|
|
|
|
-
|
|
|
|
|
- </div>
|
|
|
|
|
|
|
|
|
|
</div>
|
|
</div>
|
|
|
|
|
|
|
|
<!-- 输入框区域 -->
|
|
<!-- 输入框区域 -->
|
|
|
- <div class="edit-section" style="border: 1px solid #e4e7ed; border-radius: 4px; display: flex; flex-direction: column;">
|
|
|
|
|
|
|
+ <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-form :model="editFormData" label-width="80px" style="flex: 1; display: flex; flex-direction: column; min-height: 0;">
|
|
|
<el-input
|
|
<el-input
|
|
|
type="textarea"
|
|
type="textarea"
|
|
|
v-model="editFormData.chinese_description"
|
|
v-model="editFormData.chinese_description"
|
|
|
- :rows="12"
|
|
|
|
|
|
|
+ :rows="14"
|
|
|
placeholder="点击右侧模板图片可自动填充描述内容"
|
|
placeholder="点击右侧模板图片可自动填充描述内容"
|
|
|
show-word-limit
|
|
show-word-limit
|
|
|
maxlength="500"
|
|
maxlength="500"
|
|
|
style="width: 100%; resize: none;"
|
|
style="width: 100%; resize: none;"
|
|
|
|
|
+ :disabled="loadingStatus"
|
|
|
/>
|
|
/>
|
|
|
</el-form>
|
|
</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-top: 15px; padding-top: 15px; border-top: 1px solid #e4e7ed;">
|
|
@@ -203,11 +188,11 @@
|
|
|
{{ ratio }}
|
|
{{ ratio }}
|
|
|
</el-radio>
|
|
</el-radio>
|
|
|
</div>
|
|
</div>
|
|
|
- <div style="display: flex; align-items: center; gap: 5px;">
|
|
|
|
|
|
|
+ <!-- <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 v-model="selectedSize" label="custom" @change="handleSizeChange" border style="border-radius: 2px;">
|
|
|
自由尺寸
|
|
自由尺寸
|
|
|
</el-radio>
|
|
</el-radio>
|
|
|
- </div>
|
|
|
|
|
|
|
+ </div> -->
|
|
|
</div>
|
|
</div>
|
|
|
|
|
|
|
|
<!-- 自由尺寸的像素输入 -->
|
|
<!-- 自由尺寸的像素输入 -->
|
|
@@ -241,21 +226,91 @@
|
|
|
<!-- 操作按钮 -->
|
|
<!-- 操作按钮 -->
|
|
|
<div style="display: flex; justify-content: flex-end; gap: 12px;">
|
|
<div style="display: flex; justify-content: flex-end; gap: 12px;">
|
|
|
<!-- <el-button size="medium" @click="clearInput">清空</el-button> -->
|
|
<!-- <el-button size="medium" @click="clearInput">清空</el-button> -->
|
|
|
- <el-button size="medium" type="success" @click="optimizeContent">
|
|
|
|
|
- 扩写提示词 <span style="margin-left: 8px;">⚡ 25 <span style="font-size: 12px;"></span></span>
|
|
|
|
|
|
|
+ <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>
|
|
|
- <el-button size="medium" type="primary" @click="generateImage">
|
|
|
|
|
- 立即生成 <span style="margin-left: 8px;">⚡ 150 <span style="font-size: 12px;"></span></span>
|
|
|
|
|
|
|
+ <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>
|
|
</el-button>
|
|
|
</div>
|
|
</div>
|
|
|
</div>
|
|
</div>
|
|
|
</div>
|
|
</div>
|
|
|
</div>
|
|
</div>
|
|
|
|
|
|
|
|
- <!-- 中间:产品信息 -->
|
|
|
|
|
- <div class="middle-column" style="width: 430px; border-left: 1px solid #e4e7ed; border-right: 1px solid #e4e7ed; padding: 0 20px; position: relative;">
|
|
|
|
|
|
|
+ <!-- 中间:产品信息和历史记录 -->
|
|
|
|
|
+<div class="middle-column" style="width: 430px; border-left: 1px solid #e4e7ed; border-right: 1px solid #e4e7ed; padding: 15px 20px; position: relative;">
|
|
|
|
|
+ <!-- 历史记录覆盖层 -->
|
|
|
|
|
+ <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="text" 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;">
|
|
|
<!-- 商品图例覆盖层 -->
|
|
<!-- 商品图例覆盖层 -->
|
|
|
- <div v-if="productExampleVisible" style="position: absolute; top: 0; left: 0; 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 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="width: 95%; height: 100%; overflow-y: auto;">
|
|
|
<div style="padding: 20px;">
|
|
<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;">
|
|
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; padding-bottom: 10px; border-bottom: 1px solid #e4e7ed;">
|
|
@@ -485,7 +540,7 @@
|
|
|
<div style="display: flex; align-items: center; gap: 10px;">
|
|
<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;">
|
|
<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
|
|
<el-image
|
|
|
- :src="`/src/assets/ai案例图/010.jpg`"
|
|
|
|
|
|
|
+ :src="`/src/assets/ai案例图/010.jpg`"
|
|
|
style="width: 100%; height: 100%;"
|
|
style="width: 100%; height: 100%;"
|
|
|
fit="contain"
|
|
fit="contain"
|
|
|
>
|
|
>
|
|
@@ -637,94 +692,21 @@
|
|
|
<div style="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="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;">
|
|
<div style="display: flex; flex-direction: column; align-items: center;">
|
|
|
- <!-- 商品图例面板(已移至覆盖层) -->
|
|
|
|
|
- <div v-if="false" style="width: 430px; height: 450px; background: #ffffff; border-radius: 4px; overflow-y: auto; box-shadow: 0 2px 10px rgba(0,0,0,0.1); border: 1px solid #e4e7ed; z-index: 100; position: relative;">
|
|
|
|
|
- <div style="padding: 16px;">
|
|
|
|
|
- <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 16px;">
|
|
|
|
|
- <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 16px 0; color: #606266; line-height: 1.5; font-size: 14px;">
|
|
|
|
|
- 建议上传商品单一、完整清晰、占据画面中心的白底图,否则可能会影响商品识别效果和生成的背景图质量。
|
|
|
|
|
- </p>
|
|
|
|
|
-
|
|
|
|
|
- <!-- 商品单一 -->
|
|
|
|
|
- <div style="margin-bottom: 16px;">
|
|
|
|
|
- <div style="font-weight: 600; color: #303133; margin-bottom: 8px; font-size: 14px;">商品单一</div>
|
|
|
|
|
- <div style="background: white; padding: 12px; border-radius: 6px; box-shadow: 0 2px 4px rgba(0,0,0,0.05); margin-bottom: 8px; border: 1px solid #e4e7ed;">
|
|
|
|
|
- <div style="display: flex; align-items: center; margin-bottom: 8px;">
|
|
|
|
|
- <el-icon :size="14" style="color: #67c23a; margin-right: 6px;"><SuccessFilled /></el-icon>
|
|
|
|
|
- <span style="font-weight: 500; color: #303133; font-size: 13px;">商品完整清晰</span>
|
|
|
|
|
- </div>
|
|
|
|
|
- <div style="height: 80px; display: flex; justify-content: center; align-items: center; background: #f9f9f9; border-radius: 4px; overflow: hidden; border: 1px solid #e4e7ed;">
|
|
|
|
|
- <el-image
|
|
|
|
|
- :src="''"
|
|
|
|
|
- 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="background: white; padding: 12px; 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: 8px;">
|
|
|
|
|
- <el-icon :size="14" style="color: #67c23a; margin-right: 6px;"><SuccessFilled /></el-icon>
|
|
|
|
|
- <span style="font-weight: 500; color: #303133; font-size: 13px;">商品占据画面中心</span>
|
|
|
|
|
- </div>
|
|
|
|
|
- <div style="height: 80px; display: flex; justify-content: center; align-items: center; background: #f9f9f9; border-radius: 4px; overflow: hidden; border: 1px solid #e4e7ed;">
|
|
|
|
|
- <el-image
|
|
|
|
|
- :src="''"
|
|
|
|
|
- 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 style="margin-bottom: 16px;">
|
|
|
|
|
- <div style="font-weight: 600; color: #303133; margin-bottom: 8px; font-size: 14px;">画面包含多件商品</div>
|
|
|
|
|
- <div style="background: white; padding: 12px; 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: 8px;">
|
|
|
|
|
- <el-icon :size="14" style="color: #f56c6c; margin-right: 6px;"><Close /></el-icon>
|
|
|
|
|
- <span style="font-weight: 500; color: #303133; font-size: 13px;">不推荐</span>
|
|
|
|
|
- </div>
|
|
|
|
|
- <div style="height: 80px; display: flex; justify-content: center; align-items: center; background: #f9f9f9; border-radius: 4px; overflow: hidden; border: 1px solid #e4e7ed;">
|
|
|
|
|
- <el-image
|
|
|
|
|
- :src="''"
|
|
|
|
|
- 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 v-else style="width: 430px; height: 290px; display: flex; justify-content: center; align-items: center; background-color: white; border-radius: 4px;">
|
|
|
|
|
|
|
+ <div style="width: 430px; height: 290px; 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
|
|
|
|
|
+ />
|
|
|
|
|
+ </el-carousel-item>
|
|
|
|
|
+ </el-carousel>
|
|
|
<el-image
|
|
<el-image
|
|
|
- v-if="editFormData.new_image_url && showProductImage"
|
|
|
|
|
|
|
+ v-else-if="editFormData.new_image_url && showProductImage"
|
|
|
:src="formatImageUrl(editFormData.new_image_url)"
|
|
:src="formatImageUrl(editFormData.new_image_url)"
|
|
|
:preview-src-list="[formatImageUrl(editFormData.new_image_url)]"
|
|
:preview-src-list="[formatImageUrl(editFormData.new_image_url)]"
|
|
|
style="width: 100%; height: 100%; object-fit: fill;"
|
|
style="width: 100%; height: 100%; object-fit: fill;"
|
|
@@ -738,7 +720,7 @@
|
|
|
</div>
|
|
</div>
|
|
|
</div>
|
|
</div>
|
|
|
<!-- 中:商品信息表单 -->
|
|
<!-- 中:商品信息表单 -->
|
|
|
- <div class="product-info-container" style="height: 320px;border: 12px solid #f6E0dd; border-radius: 4px; padding: 15px;">
|
|
|
|
|
|
|
+ <div class="product-info-container" style="width: 430px; height: 320px;border: 12px solid #f6E0dd; border-radius: 4px; padding: 15px;">
|
|
|
<div class="product-info-item">
|
|
<div class="product-info-item">
|
|
|
<span class="product-info-label">商品条码:</span>
|
|
<span class="product-info-label">商品条码:</span>
|
|
|
<span class="product-info-value">{{ editFormData.barcode || '-' }}</span>
|
|
<span class="product-info-value">{{ editFormData.barcode || '-' }}</span>
|
|
@@ -765,19 +747,18 @@
|
|
|
</div>
|
|
</div>
|
|
|
</div>
|
|
</div>
|
|
|
<!-- 下:空出来的部分 -->
|
|
<!-- 下:空出来的部分 -->
|
|
|
- <div style="width: 430px; height: 61px;">
|
|
|
|
|
- </div>
|
|
|
|
|
|
|
+ <div style="width: 430px; height: 61px;"></div>
|
|
|
</div>
|
|
</div>
|
|
|
</div>
|
|
</div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+</div>
|
|
|
|
|
|
|
|
<!-- 右侧:模板列表 -->
|
|
<!-- 右侧:模板列表 -->
|
|
|
<div class="right-column" style="flex: 1;">
|
|
<div class="right-column" style="flex: 1;">
|
|
|
<div class="right-template" style="height: 100%; display: flex; flex-direction: column;">
|
|
<div class="right-template" style="height: 100%; display: flex; flex-direction: column;">
|
|
|
- <div style="margin-bottom: 10px;margin: 0px 0px 20px 0px;padding: 0px;display: flex;justify-content: flex-end;">
|
|
|
|
|
- <el-button type="danger" size="large" @click="editDialogVisible = false">
|
|
|
|
|
- <el-icon><Close /></el-icon>关闭
|
|
|
|
|
- </el-button>
|
|
|
|
|
- </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;margin-top:15px">①模版</div>
|
|
|
|
|
+
|
|
|
<!-- 搜索框 -->
|
|
<!-- 搜索框 -->
|
|
|
<div class="template-search" style="margin-bottom: 15px;">
|
|
<div class="template-search" style="margin-bottom: 15px;">
|
|
|
<el-input v-model="searchKeyword" placeholder="请描述你想搜索的模版关键字..." clearable @input="handleSearch" @clear="handleClearSearch">
|
|
<el-input v-model="searchKeyword" placeholder="请描述你想搜索的模版关键字..." clearable @input="handleSearch" @clear="handleClearSearch">
|
|
@@ -1082,9 +1063,9 @@
|
|
|
import { ref, reactive, toRaw, onMounted ,watch } from 'vue'
|
|
import { ref, reactive, toRaw, onMounted ,watch } from 'vue'
|
|
|
import { ElMessage, ElLoading} from 'element-plus'
|
|
import { ElMessage, ElLoading} from 'element-plus'
|
|
|
import { getTable, imageToText, Template_ids,txttoimg_moxing,GetHttpUrl,txttoimg_update, getSide,merchantGetab,productList,productDetail,
|
|
import { getTable, imageToText, Template_ids,txttoimg_moxing,GetHttpUrl,txttoimg_update, getSide,merchantGetab,productList,productDetail,
|
|
|
- product_template,GetTxtToTxt,GetProductFind,productAdd,getMerchantId } from '@/api/mes/job'
|
|
|
|
|
|
|
+ product_template,GetTxtToTxt,GetProductFind,productAdd,getMerchantId,GetImageStatus } from '@/api/mes/job'
|
|
|
import { useUserStore } from '@/pinia/modules/user'
|
|
import { useUserStore } from '@/pinia/modules/user'
|
|
|
-import { ZoomIn, Camera,SuccessFilled, WarningFilled, More, ArrowRight, ArrowDown } from '@element-plus/icons-vue'
|
|
|
|
|
|
|
+import { ZoomIn, Camera,SuccessFilled, WarningFilled, More, ArrowRight, ArrowDown, Loading } from '@element-plus/icons-vue'
|
|
|
import { Layout, LayoutHeader, LayoutSider, LayoutContent } from '@arco-design/web-vue'
|
|
import { Layout, LayoutHeader, LayoutSider, LayoutContent } from '@arco-design/web-vue'
|
|
|
|
|
|
|
|
|
|
|
|
@@ -1093,6 +1074,18 @@ import { Layout, LayoutHeader, LayoutSider, LayoutContent } from '@arco-design/w
|
|
|
const productExampleVisible = ref(false)
|
|
const productExampleVisible = ref(false)
|
|
|
const caseExampleVisible = 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 = () => {
|
|
const toggleProductExample = () => {
|
|
|
productExampleVisible.value = !productExampleVisible.value
|
|
productExampleVisible.value = !productExampleVisible.value
|
|
@@ -1220,6 +1213,9 @@ const showProductImage = ref(false)
|
|
|
// 存储生成的多个新图
|
|
// 存储生成的多个新图
|
|
|
const newImages = ref([])
|
|
const newImages = ref([])
|
|
|
|
|
|
|
|
|
|
+// 加载状态控制
|
|
|
|
|
+const loadingStatus = ref(false)
|
|
|
|
|
+
|
|
|
const formatImageUrl = (path) => {
|
|
const formatImageUrl = (path) => {
|
|
|
if (!path) return ''
|
|
if (!path) return ''
|
|
|
// 检查path是否已经是完整的URL
|
|
// 检查path是否已经是完整的URL
|
|
@@ -1352,8 +1348,52 @@ const setActive = async (type) => {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
+// 处理模板分类树数据
|
|
|
|
|
+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) => {
|
|
const onRowDblClick = async (row) => {
|
|
|
- try {
|
|
|
|
|
// 设置编辑表单ID
|
|
// 设置编辑表单ID
|
|
|
editFormData.id = row.id
|
|
editFormData.id = row.id
|
|
|
editDialogVisible.value = true
|
|
editDialogVisible.value = true
|
|
@@ -1382,7 +1422,9 @@ const onRowDblClick = async (row) => {
|
|
|
if (item.product_new_img) {
|
|
if (item.product_new_img) {
|
|
|
newImages.value.push({
|
|
newImages.value.push({
|
|
|
url: item.product_new_img,
|
|
url: item.product_new_img,
|
|
|
- product_content: item.product_content || ''
|
|
|
|
|
|
|
+ product_content: item.product_content || '',
|
|
|
|
|
+ template_id: item.template_id,
|
|
|
|
|
+ createTime: item.createTime
|
|
|
})
|
|
})
|
|
|
}
|
|
}
|
|
|
})
|
|
})
|
|
@@ -1391,25 +1433,22 @@ const onRowDblClick = async (row) => {
|
|
|
if (newImages.value.length > 0 && newImages.value[0].product_content) {
|
|
if (newImages.value.length > 0 && newImages.value[0].product_content) {
|
|
|
editFormData.chinese_description = newImages.value[0].product_content
|
|
editFormData.chinese_description = newImages.value[0].product_content
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+ // 处理模板分类树数据
|
|
|
|
|
+ processTemplateTreeData(detailResponse.image)
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// 2. 获取所有模板数据
|
|
// 2. 获取所有模板数据
|
|
|
await fetchTemplates()
|
|
await fetchTemplates()
|
|
|
|
|
|
|
|
- } catch (error) {
|
|
|
|
|
- console.error('打开编辑弹窗失败:', error)
|
|
|
|
|
- ElMessage.error('获取数据失败')
|
|
|
|
|
- }
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// 存储所有模板数据
|
|
// 存储所有模板数据
|
|
|
const templateList = ref([])
|
|
const templateList = ref([])
|
|
|
-const currentTemplateId = ref(null) // 当前选中的模板ID
|
|
|
|
|
|
|
|
|
|
// 获取所有模板
|
|
// 获取所有模板
|
|
|
const fetchTemplates = async () => {
|
|
const fetchTemplates = async () => {
|
|
|
- try {
|
|
|
|
|
const response = await product_template()
|
|
const response = await product_template()
|
|
|
if (response.code === 0 && response.data) {
|
|
if (response.code === 0 && response.data) {
|
|
|
templateList.value = response.data.map(item => ({
|
|
templateList.value = response.data.map(item => ({
|
|
@@ -1425,10 +1464,6 @@ const fetchTemplates = async () => {
|
|
|
// }
|
|
// }
|
|
|
updateProductImage(newImages.value[0].url)
|
|
updateProductImage(newImages.value[0].url)
|
|
|
}
|
|
}
|
|
|
- } catch (error) {
|
|
|
|
|
- console.error('获取模板失败:', error)
|
|
|
|
|
- templateList.value = []
|
|
|
|
|
- }
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// 选择模板
|
|
// 选择模板
|
|
@@ -1509,13 +1544,16 @@ const optimizeContent = async () => {
|
|
|
return
|
|
return
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ // 设置加载状态
|
|
|
|
|
+ loadingStatus.value = true
|
|
|
|
|
+
|
|
|
// 重置状态
|
|
// 重置状态
|
|
|
pollStatus.value = 'optimizing'
|
|
pollStatus.value = 'optimizing'
|
|
|
pollCount.value = 0
|
|
pollCount.value = 0
|
|
|
|
|
|
|
|
// 第一步:调用生成接口触发生成任务
|
|
// 第一步:调用生成接口触发生成任务
|
|
|
const generateResponse = await GetTxtToTxt({
|
|
const generateResponse = await GetTxtToTxt({
|
|
|
- status_val: '图生文',
|
|
|
|
|
|
|
+ status_val: '文生文',
|
|
|
prompt: editFormData.chinese_description,
|
|
prompt: editFormData.chinese_description,
|
|
|
model: 'gemini-3-pro-preview',
|
|
model: 'gemini-3-pro-preview',
|
|
|
id: editFormData.id,
|
|
id: editFormData.id,
|
|
@@ -1545,6 +1583,7 @@ const optimizeContent = async () => {
|
|
|
clearInterval(pollInterval.value)
|
|
clearInterval(pollInterval.value)
|
|
|
pollInterval.value = null
|
|
pollInterval.value = null
|
|
|
pollStatus.value = 'success'
|
|
pollStatus.value = 'success'
|
|
|
|
|
+ loadingStatus.value = false
|
|
|
|
|
|
|
|
// 更新内容到输入框
|
|
// 更新内容到输入框
|
|
|
editFormData.chinese_description = checkResponse.data.content
|
|
editFormData.chinese_description = checkResponse.data.content
|
|
@@ -1558,6 +1597,7 @@ const optimizeContent = async () => {
|
|
|
clearInterval(pollInterval.value)
|
|
clearInterval(pollInterval.value)
|
|
|
pollInterval.value = null
|
|
pollInterval.value = null
|
|
|
pollStatus.value = 'error'
|
|
pollStatus.value = 'error'
|
|
|
|
|
+ loadingStatus.value = false
|
|
|
ElMessage.warning('优化超时,请稍后手动检查结果')
|
|
ElMessage.warning('优化超时,请稍后手动检查结果')
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -1569,11 +1609,13 @@ const optimizeContent = async () => {
|
|
|
|
|
|
|
|
} else {
|
|
} else {
|
|
|
pollStatus.value = 'error'
|
|
pollStatus.value = 'error'
|
|
|
|
|
+ loadingStatus.value = false
|
|
|
ElMessage.error('优化任务启动失败: ' + (generateResponse.msg || '未知错误'))
|
|
ElMessage.error('优化任务启动失败: ' + (generateResponse.msg || '未知错误'))
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
} catch (generateError) {
|
|
} catch (generateError) {
|
|
|
pollStatus.value = 'error'
|
|
pollStatus.value = 'error'
|
|
|
|
|
+ loadingStatus.value = false
|
|
|
console.error('内容优化失败:', generateError)
|
|
console.error('内容优化失败:', generateError)
|
|
|
ElMessage.error('内容优化失败: ' + (generateError.message || '未知错误'))
|
|
ElMessage.error('内容优化失败: ' + (generateError.message || '未知错误'))
|
|
|
}
|
|
}
|
|
@@ -1583,19 +1625,27 @@ const optimizeContent = async () => {
|
|
|
const pollStatus = ref(null) // 轮询状态:'polling', 'success', 'error'
|
|
const pollStatus = ref(null) // 轮询状态:'polling', 'success', 'error'
|
|
|
const pollCount = ref(0) // 轮询次数
|
|
const pollCount = ref(0) // 轮询次数
|
|
|
const pollInterval = ref(null) // 轮询定时器
|
|
const pollInterval = ref(null) // 轮询定时器
|
|
|
-
|
|
|
|
|
|
|
+const task_id = ref('')
|
|
|
// 生成图片(简化版,只做轮询)
|
|
// 生成图片(简化版,只做轮询)
|
|
|
const generateImage = async () => {
|
|
const generateImage = async () => {
|
|
|
try {
|
|
try {
|
|
|
|
|
+ if (!editFormData.template_id) {
|
|
|
|
|
+ ElMessage.warning('请先选择模版')
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
if (!editFormData.chinese_description) {
|
|
if (!editFormData.chinese_description) {
|
|
|
ElMessage.warning('请输入描述内容')
|
|
ElMessage.warning('请输入描述内容')
|
|
|
return
|
|
return
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+ // 设置加载状态
|
|
|
|
|
+ loadingStatus.value = true
|
|
|
|
|
|
|
|
// 重置状态
|
|
// 重置状态
|
|
|
pollStatus.value = 'polling'
|
|
pollStatus.value = 'polling'
|
|
|
pollCount.value = 0
|
|
pollCount.value = 0
|
|
|
-
|
|
|
|
|
|
|
+ console.log(editFormData.template_id)
|
|
|
// 第一步:调用生成接口触发生成任务
|
|
// 第一步:调用生成接口触发生成任务
|
|
|
const generateResponse = await GetTxtToTxt({
|
|
const generateResponse = await GetTxtToTxt({
|
|
|
status_val: '文生图',
|
|
status_val: '文生图',
|
|
@@ -1603,10 +1653,15 @@ const generateImage = async () => {
|
|
|
model: 'gemini-3-pro-image-preview',
|
|
model: 'gemini-3-pro-image-preview',
|
|
|
id: editFormData.id,
|
|
id: editFormData.id,
|
|
|
size: selectedSize.value,
|
|
size: selectedSize.value,
|
|
|
|
|
+ template_id:editFormData.template_id,
|
|
|
})
|
|
})
|
|
|
|
|
|
|
|
if (generateResponse.code === 0) {
|
|
if (generateResponse.code === 0) {
|
|
|
ElMessage.success('图片生成任务已开始,请稍候...')
|
|
ElMessage.success('图片生成任务已开始,请稍候...')
|
|
|
|
|
+ task_id.value = generateResponse.data.task_id
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+ // 稍后在轮询中使用GetImageStatus接口
|
|
|
|
|
|
|
|
// 清除之前的定时器
|
|
// 清除之前的定时器
|
|
|
if (pollInterval.value) {
|
|
if (pollInterval.value) {
|
|
@@ -1618,35 +1673,61 @@ const generateImage = async () => {
|
|
|
pollCount.value++
|
|
pollCount.value++
|
|
|
|
|
|
|
|
try {
|
|
try {
|
|
|
- // 调用查询接口
|
|
|
|
|
- const checkResponse = await GetProductFind({ id: editFormData.id })
|
|
|
|
|
|
|
+ // 调用GetImageStatus接口查询生成状态
|
|
|
|
|
+ const statusResponse = await GetImageStatus({ task_id: task_id.value })
|
|
|
|
|
|
|
|
- if (checkResponse.code === 0 && checkResponse.data) {
|
|
|
|
|
- // 如果获取到数据且有product_new_img字段
|
|
|
|
|
- if (checkResponse.data.product_new_img) {
|
|
|
|
|
|
|
+ if (statusResponse.code === 0 && statusResponse.data) {
|
|
|
|
|
+ // 如果获取到数据且有图片URL
|
|
|
|
|
+ if (statusResponse.data.image_url) {
|
|
|
// 停止轮询
|
|
// 停止轮询
|
|
|
clearInterval(pollInterval.value)
|
|
clearInterval(pollInterval.value)
|
|
|
|
|
+ pollInterval.value = null
|
|
|
pollStatus.value = 'success'
|
|
pollStatus.value = 'success'
|
|
|
|
|
+ loadingStatus.value = false
|
|
|
|
|
|
|
|
// 更新新图URL
|
|
// 更新新图URL
|
|
|
- editFormData.new_image_url = checkResponse.data.product_new_img
|
|
|
|
|
|
|
+ const imageUrl = statusResponse.data.image_url
|
|
|
|
|
+ editFormData.new_image_url = imageUrl
|
|
|
editFormData.img_name = `生成图片_${new Date().getTime()}.jpg`
|
|
editFormData.img_name = `生成图片_${new Date().getTime()}.jpg`
|
|
|
- editFormData.product_name = checkResponse.data.product_name
|
|
|
|
|
- editFormData.product_code = checkResponse.data.product_code
|
|
|
|
|
|
|
|
|
|
- // 如果有原图字段,也更新一下
|
|
|
|
|
- if (checkResponse.data.product_img) {
|
|
|
|
|
- editFormData.original_image_url = checkResponse.data.product_img
|
|
|
|
|
|
|
+ // 更新历史记录
|
|
|
|
|
+ const newImageItem = {
|
|
|
|
|
+ url: imageUrl,
|
|
|
|
|
+ product_content: editFormData.chinese_description || '',
|
|
|
|
|
+ template_id: editFormData.template_id,
|
|
|
|
|
+ createTime: statusResponse.data.completed_at || new Date().toISOString()
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- ElMessage.success(`图片生成成功!耗时约${pollCount.value * 10}秒`)
|
|
|
|
|
|
|
+ // 添加到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次(5分钟),停止轮询
|
|
|
|
|
|
|
+ // 如果轮询超过30次(2.5分钟),停止轮询
|
|
|
if (pollCount.value >= 30) {
|
|
if (pollCount.value >= 30) {
|
|
|
clearInterval(pollInterval.value)
|
|
clearInterval(pollInterval.value)
|
|
|
|
|
+ pollInterval.value = null
|
|
|
pollStatus.value = 'error'
|
|
pollStatus.value = 'error'
|
|
|
|
|
+ loadingStatus.value = false
|
|
|
ElMessage.warning('生成超时,请稍后手动检查结果')
|
|
ElMessage.warning('生成超时,请稍后手动检查结果')
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -1654,15 +1735,17 @@ const generateImage = async () => {
|
|
|
console.error('轮询查询失败:', pollError)
|
|
console.error('轮询查询失败:', pollError)
|
|
|
// 轮询失败继续尝试
|
|
// 轮询失败继续尝试
|
|
|
}
|
|
}
|
|
|
- }, 5000) // 每10秒轮询一次
|
|
|
|
|
|
|
+ }, 5000) // 每5秒轮询一次
|
|
|
|
|
|
|
|
} else {
|
|
} else {
|
|
|
pollStatus.value = 'error'
|
|
pollStatus.value = 'error'
|
|
|
|
|
+ loadingStatus.value = false
|
|
|
ElMessage.error('生成任务启动失败: ' + (generateResponse.msg || '未知错误'))
|
|
ElMessage.error('生成任务启动失败: ' + (generateResponse.msg || '未知错误'))
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
} catch (generateError) {
|
|
} catch (generateError) {
|
|
|
pollStatus.value = 'error'
|
|
pollStatus.value = 'error'
|
|
|
|
|
+ loadingStatus.value = false
|
|
|
console.error('生成图片失败:', generateError)
|
|
console.error('生成图片失败:', generateError)
|
|
|
ElMessage.error('生成图片失败: ' + (generateError.message || '未知错误'))
|
|
ElMessage.error('生成图片失败: ' + (generateError.message || '未知错误'))
|
|
|
}
|
|
}
|
|
@@ -2181,7 +2264,7 @@ defineExpose({
|
|
|
|
|
|
|
|
.image-comparison-section {
|
|
.image-comparison-section {
|
|
|
flex: none; /* 改为不伸缩 */
|
|
flex: none; /* 改为不伸缩 */
|
|
|
- height: 400px; /* 固定高度,和原来一样 */
|
|
|
|
|
|
|
+ height: 300px; /* 固定高度,和原来一样 */
|
|
|
display: flex;
|
|
display: flex;
|
|
|
flex-direction: column;
|
|
flex-direction: column;
|
|
|
gap: 15px;
|
|
gap: 15px;
|