|
|
@@ -6,7 +6,7 @@
|
|
|
<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" icon="search" @click="onSubmit" title="搜索查询">查询</el-button>
|
|
|
<el-button type="primary" @click="onADD" >新增产品</el-button>
|
|
|
</el-form-item>
|
|
|
</el-form>
|
|
|
@@ -43,7 +43,7 @@
|
|
|
@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="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">
|
|
|
@@ -94,182 +94,137 @@
|
|
|
</layout>
|
|
|
</layout>
|
|
|
|
|
|
-<el-dialog
|
|
|
- v-model="editDialogVisible"
|
|
|
- title="图片对比与编辑"
|
|
|
- fullscreen
|
|
|
- :modal="true"
|
|
|
- @close="handleDialogClose">
|
|
|
-
|
|
|
- <div class="image-edit-container" style="display: flex; gap: 20px; height: calc(100vh - 140px);">
|
|
|
+<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 class="left-column" style="flex: 2; display: flex; flex-direction: column; gap: 20px;">
|
|
|
-
|
|
|
- <!-- 图片对比区域 -->
|
|
|
- <div class="image-comparison-section" style="flex: 1; display: flex; flex-direction: column; gap: 15px;">
|
|
|
- <div class="image-item">
|
|
|
- <div style="display: flex; justify-content: space-between; width: 100%;">
|
|
|
- <div style="display: flex; gap: 12px;">
|
|
|
- <el-button type="danger" size="large" @click="editDialogVisible = false">
|
|
|
- <el-icon><Close /></el-icon>关闭
|
|
|
- </el-button>
|
|
|
- <el-button type="primary" size="large" @click="downloadImage('original')">
|
|
|
- <el-icon><Download /></el-icon>下载原图
|
|
|
- </el-button>
|
|
|
- <el-button type="primary" size="large" @click="downloadImage('new')">
|
|
|
- <el-icon><Download /></el-icon>下载新图
|
|
|
- </el-button>
|
|
|
- </div>
|
|
|
-
|
|
|
- <div style="display: flex; gap: 12px;">
|
|
|
- <el-button type="success" size="large">
|
|
|
- <el-icon><Download /></el-icon>内容审核
|
|
|
- </el-button>
|
|
|
- <el-button type="primary" size="large">
|
|
|
- <el-icon><Download /></el-icon>确认广告图
|
|
|
- </el-button>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
-
|
|
|
- <!-- 原图区域 -->
|
|
|
- <div class="image-preview" style="position: relative;">
|
|
|
- <el-image
|
|
|
- v-if="editFormData.original_image_url"
|
|
|
- :src="formatImageUrl(editFormData.original_image_url)"
|
|
|
- :preview-src-list="[formatImageUrl(editFormData.original_image_url)]"
|
|
|
- style="width: 100%; height: 200px;"
|
|
|
- fit="contain"
|
|
|
- preview-teleported
|
|
|
- />
|
|
|
- <el-button
|
|
|
- v-if="editFormData.original_image_url"
|
|
|
- type="primary"
|
|
|
- circle
|
|
|
- size="medium"
|
|
|
- style="position: absolute; top: 10px; right: 10px; opacity: 0; transition: opacity 0.3s; z-index: 10;"
|
|
|
- @click.stop="downloadImage('original')"
|
|
|
- class="image-download-btn"
|
|
|
- >
|
|
|
- <el-icon><Download /></el-icon>
|
|
|
- </el-button>
|
|
|
- <div v-else class="image-placeholder">
|
|
|
- <el-icon :size="40"><Picture /></el-icon>
|
|
|
- <span>暂无原图</span>
|
|
|
- </div>
|
|
|
- <div class="image-info">
|
|
|
- <span>文件名: {{ editFormData.original_name || '未命名' }}</span>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
+ <div class="left-column" style="flex: 1; display: flex; flex-direction: column; gap: 15px; padding: 15px; overflow-y: hidden;">
|
|
|
+ <!-- 图片对比区域 -->
|
|
|
+ <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 v-if="editFormData.original_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.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" style="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;">
|
|
|
+ <el-icon :size="30"><Picture /></el-icon>
|
|
|
+ <span style="margin-top: 5px; font-size: 10px;">暂无原图</span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
|
|
|
- <!-- 新图区域 -->
|
|
|
- <div class="image-preview" style="position: relative;">
|
|
|
- <el-image
|
|
|
- v-if="editFormData.new_image_url"
|
|
|
- :src="formatImageUrl(editFormData.new_image_url)"
|
|
|
- style="width: 100%; height: 200px; cursor: pointer;"
|
|
|
- fit="contain"
|
|
|
- @click="updateProductImage(editFormData.new_image_url)"
|
|
|
- />
|
|
|
- <el-button
|
|
|
- v-if="editFormData.new_image_url"
|
|
|
- type="primary"
|
|
|
- circle
|
|
|
- size="medium"
|
|
|
- style="position: absolute; top: 10px; right: 10px; opacity: 0; transition: opacity 0.3s; z-index: 10;"
|
|
|
- @click.stop="downloadImage('new')"
|
|
|
- class="image-download-btn"
|
|
|
- >
|
|
|
- <el-icon><Download /></el-icon>
|
|
|
- </el-button>
|
|
|
- <div v-else class="image-placeholder">
|
|
|
- <el-icon :size="40"><Picture /></el-icon>
|
|
|
- <span>暂无新图</span>
|
|
|
- </div>
|
|
|
- <div class="image-info">
|
|
|
- <span>文件名: {{ editFormData.img_name || '未命名' }}</span>
|
|
|
+ <!-- 新图区域 -->
|
|
|
+ <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>
|
|
|
+
|
|
|
+ <!-- 输入框区域 -->
|
|
|
+ <div class="edit-section" style="border: 1px solid #e4e7ed; border-radius: 4px; display: flex; flex-direction: column;">
|
|
|
+ <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="12"
|
|
|
+ placeholder="点击右侧模板图片可自动填充描述内容"
|
|
|
+ show-word-limit
|
|
|
+ maxlength="500"
|
|
|
+ style="width: 100%; resize: none;"
|
|
|
+ />
|
|
|
+ </el-form>
|
|
|
|
|
|
+ <!-- 按钮放在表单下方 -->
|
|
|
+ <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 class="edit-section" style="flex: 1; border-top: 1px solid #e4e7ed; padding-top: 20px; display: flex; flex-direction: column;">
|
|
|
- <el-form :model="editFormData" label-width="80px" style="flex: 1; display: flex; flex-direction: column;">
|
|
|
- <el-input
|
|
|
- type="textarea"
|
|
|
- v-model="editFormData.chinese_description"
|
|
|
- :rows="12"
|
|
|
- placeholder="点击右侧模板图片可自动填充描述内容"
|
|
|
- show-word-limit
|
|
|
- maxlength="500"
|
|
|
- style="width: 100%;"
|
|
|
- />
|
|
|
- </el-form>
|
|
|
-
|
|
|
-<!-- 按钮放在表单下方 -->
|
|
|
-<div style="display: flex; justify-content: space-between; align-items: center; margin-top: 15px; padding-top: 15px; border-top: 1px solid #e4e7ed;">
|
|
|
- <!-- 左侧:尺寸选择区域 -->
|
|
|
- <div style="display: flex; align-items: center; gap: 10px;">
|
|
|
- <span style="font-size: 14px; color: #606266;">尺寸比例:</span>
|
|
|
- <el-select v-model="selectedSize" size="small" style="width: 120px;" @change="handleSizeChange">
|
|
|
- <el-option label="1:1" value="1:1" />
|
|
|
- <el-option label="4:3" value="4:3" />
|
|
|
- <el-option label="3:2" value="3:2" />
|
|
|
- <el-option label="2:3" value="2:3" />
|
|
|
- <el-option label="9:16" value="9:16" />
|
|
|
- <el-option label="16:9" value="16:9" />
|
|
|
- <el-option label="自由尺寸" value="custom" />
|
|
|
- </el-select>
|
|
|
-
|
|
|
- <!-- 自由尺寸的像素输入 -->
|
|
|
- <div v-if="selectedSize === 'custom'" style="display: flex; align-items: center; gap: 5px;">
|
|
|
- <el-input
|
|
|
- v-model="customWidth"
|
|
|
- size="small"
|
|
|
- style="width: 80px;"
|
|
|
- placeholder="宽"
|
|
|
- @input="validateCustomSize"
|
|
|
- >
|
|
|
- <template #append>px</template>
|
|
|
- </el-input>
|
|
|
- <span style="color: #909399;">×</span>
|
|
|
- <el-input
|
|
|
- v-model="customHeight"
|
|
|
- size="small"
|
|
|
- style="width: 80px;"
|
|
|
- placeholder="高"
|
|
|
- @input="validateCustomSize"
|
|
|
- >
|
|
|
- <template #append>px</template>
|
|
|
- </el-input>
|
|
|
+ <!-- 操作按钮 -->
|
|
|
+ <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">
|
|
|
+ 扩写提示词 <span style="margin-left: 8px;">⚡ 25 <span style="font-size: 12px;"></span></span>
|
|
|
+ </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>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
</div>
|
|
|
-
|
|
|
- <!-- 显示当前尺寸信息 -->
|
|
|
- <div v-if="selectedSize !== 'custom'" style="font-size: 12px; color: #909399;">
|
|
|
- {{ getSizeInfo(selectedSize) }}
|
|
|
- </div>
|
|
|
- </div>
|
|
|
-
|
|
|
- <!-- 右侧:操作按钮 -->
|
|
|
- <div style="display: flex; gap: 10px;">
|
|
|
- <el-button @click="clearInput">清空</el-button>
|
|
|
- <el-button type="primary" @click="optimizeContent">内容优化</el-button>
|
|
|
- <el-button type="success" @click="generateImage">生成图片</el-button>
|
|
|
- </div>
|
|
|
-</div>
|
|
|
- </div>
|
|
|
-</div>
|
|
|
-
|
|
|
</div>
|
|
|
|
|
|
<!-- 中间:产品信息 -->
|
|
|
<div class="middle-column" style="width: 430px; border-left: 1px solid #e4e7ed; border-right: 1px solid #e4e7ed; padding: 0 20px;">
|
|
|
<div style="height: 100%; display: flex; flex-direction: column;">
|
|
|
-
|
|
|
<!-- 上:留出的空白区域 -->
|
|
|
- <div style="height: 90px; background-image: url('/public/src/assets/top-bg.png'); background-size: cover; background-position: center; border-top-left-radius: 8px; border-top-right-radius: 8px;"></div>
|
|
|
-
|
|
|
+ <div style="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="width: 430px; height: 290px; display: flex; justify-content: center; align-items: center; background-color: white; border-radius: 4px;">
|
|
|
@@ -287,7 +242,6 @@
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
-
|
|
|
<!-- 中:商品信息表单 -->
|
|
|
<div class="product-info-container" style="height: 320px;border: 12px solid #f6E0dd; border-radius: 4px; padding: 15px;">
|
|
|
<div class="product-info-item">
|
|
|
@@ -315,111 +269,101 @@
|
|
|
<span class="product-info-value">{{ editFormData.unit || '-' }}</span>
|
|
|
</div>
|
|
|
</div>
|
|
|
-
|
|
|
<!-- 下:空出来的部分 -->
|
|
|
<div style="width: 430px; height: 61px;">
|
|
|
-
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
<!-- 右侧:模板列表 -->
|
|
|
- <div class="right-column" style="flex: 2; padding-left: 20px;">
|
|
|
- <div class="right-template" style="height: 100%; display: flex; flex-direction: column;">
|
|
|
- <div class="template-header" style="margin-bottom: 15px;">
|
|
|
- </div>
|
|
|
-
|
|
|
- <!-- 搜索框 -->
|
|
|
- <div class="template-search" style="margin-bottom: 15px;">
|
|
|
- <el-input
|
|
|
- v-model="searchKeyword"
|
|
|
- placeholder="输入关键词搜索模板..."
|
|
|
- clearable
|
|
|
- @keyup.enter="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>参考模板 ({{ 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="cover"
|
|
|
- >
|
|
|
- <template #error>
|
|
|
- <div class="thumbnail-error">
|
|
|
- <el-icon><Picture /></el-icon>
|
|
|
+ <div class="right-column" style="flex: 1;">
|
|
|
+ <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 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="cover"
|
|
|
+ >
|
|
|
+ <template #error>
|
|
|
+ <div class="thumbnail-error">
|
|
|
+ <el-icon><Picture /></el-icon>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ </el-image>
|
|
|
+ <div class="zoom-icon" @click.stop="handleImageZoom(template.template_image_url)">
|
|
|
+ <el-icon :size="20"><ZoomIn /></el-icon>
|
|
|
</div>
|
|
|
- </template>
|
|
|
- </el-image>
|
|
|
- <div class="zoom-icon" @click.stop="handleImageZoom(template.template_image_url)">
|
|
|
- <el-icon :size="20"><ZoomIn /></el-icon>
|
|
|
+ </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 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 v-if="!searchKeyword && !searchLoading && templateList.length === 0" class="empty-templates">
|
|
|
+ <el-icon :size="40"><Picture /></el-icon>
|
|
|
+ <p>暂无模板数据</p>
|
|
|
+ </div>
|
|
|
</div>
|
|
|
- </div>
|
|
|
-
|
|
|
- <!-- 初始无数据提示 -->
|
|
|
- <div v-if="!searchKeyword && !searchLoading && templateList.length === 0" class="empty-templates">
|
|
|
- <el-icon :size="40"><Picture /></el-icon>
|
|
|
- <p>暂无模板数据</p>
|
|
|
- </div>
|
|
|
+ </el-scrollbar>
|
|
|
+ <!-- 图片预览组件 -->
|
|
|
+ <el-image-viewer
|
|
|
+ v-if="previewVisible"
|
|
|
+ :url-list="[previewImageUrl]"
|
|
|
+ @close="previewVisible = false"
|
|
|
+ />
|
|
|
</div>
|
|
|
- </el-scrollbar>
|
|
|
-
|
|
|
- <!-- 图片预览组件 -->
|
|
|
- <el-image-viewer
|
|
|
- v-if="previewVisible"
|
|
|
- :url-list="[previewImageUrl]"
|
|
|
- @close="previewVisible = false"
|
|
|
- />
|
|
|
+ </div>
|
|
|
</div>
|
|
|
</div>
|
|
|
-</div>
|
|
|
- </div>
|
|
|
-
|
|
|
-
|
|
|
</el-dialog>
|
|
|
|
|
|
<!-- 图片预览 -->
|
|
|
@@ -539,7 +483,7 @@ import { ElMessage, ElLoading} from 'element-plus'
|
|
|
import { getTable, imageToText, Template_ids,txttoimg_moxing,GetHttpUrl,txttoimg_update, getSide,merchantGetab,productList,productDetail,
|
|
|
product_template,GetTxtToTxt,GetProductFind,productAdd,getMerchantId } from '@/api/mes/job'
|
|
|
import { useUserStore } from '@/pinia/modules/user'
|
|
|
-import { ArrowDown, ZoomIn } from '@element-plus/icons-vue'
|
|
|
+import { ArrowDown, ZoomIn, Camera } from '@element-plus/icons-vue'
|
|
|
import { Layout, LayoutHeader, LayoutSider, LayoutContent } from '@arco-design/web-vue'
|
|
|
const props = defineProps({
|
|
|
editFormData: {
|
|
|
@@ -629,8 +573,10 @@ const editFormData = reactive({
|
|
|
chinese_description: '',
|
|
|
english_description: '',
|
|
|
new_image_url: '',
|
|
|
+ new_video_url: '',
|
|
|
imgtoimg_url: '',
|
|
|
- img_name: ''
|
|
|
+ img_name: '',
|
|
|
+ video_name: ''
|
|
|
})
|
|
|
|
|
|
// 定义文生图表单对象
|
|
|
@@ -641,16 +587,29 @@ const form = reactive({
|
|
|
// 控制产品信息部分图片是否显示
|
|
|
const showProductImage = ref(false)
|
|
|
|
|
|
+// 存储生成的多个新图
|
|
|
+const newImages = ref([])
|
|
|
+
|
|
|
const formatImageUrl = (path) => {
|
|
|
if (!path) return ''
|
|
|
- return `${full_url.value}/${path.replace(/^public\//, '')}`
|
|
|
+ // 检查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
|
|
|
}
|
|
|
|
|
|
// 点击图片时更新产品信息部分的图片
|
|
|
const updateProductImage = (imageUrl) => {
|
|
|
editFormData.new_image_url = imageUrl
|
|
|
showProductImage.value = true
|
|
|
- ElMessage.success('图片已更新到产品信息区域')
|
|
|
+ // ElMessage.success('图片已更新到产品信息区域')
|
|
|
}
|
|
|
|
|
|
const txttoimg_modelList = ref([]); // 存储所有模型数据
|
|
|
@@ -772,6 +731,11 @@ const onRowDblClick = async (row) => {
|
|
|
editFormData.original_name = detailResponse.data['产品名称']
|
|
|
editFormData.product_name = detailResponse.data['产品名称']
|
|
|
editFormData.product_code = detailResponse.data['产品编码']
|
|
|
+
|
|
|
+ // 如果有新图片,自动显示到产品信息区域
|
|
|
+ if (detailResponse.data['产品效果图']) {
|
|
|
+ showProductImage.value = true
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
// 2. 获取所有模板数据
|
|
|
@@ -1057,7 +1021,9 @@ const sizePresets = {
|
|
|
'3:2': { width: 1024, height: 683 },
|
|
|
'2:3': { width: 683, height: 1024 },
|
|
|
'9:16': { width: 675, height: 1200 },
|
|
|
- '16:9': { width: 1200, height: 675 }
|
|
|
+ '16:9': { width: 1200, height: 675 },
|
|
|
+ '21:9': { width: 1200, height: 514 },
|
|
|
+ '3:4': { width: 768, height: 1024 }
|
|
|
}
|
|
|
|
|
|
// 获取尺寸信息
|
|
|
@@ -1069,9 +1035,10 @@ const getSizeInfo = (size) => {
|
|
|
|
|
|
// 尺寸变化处理
|
|
|
const handleSizeChange = (value) => {
|
|
|
- if (value !== 'custom') {
|
|
|
+ const selectedValue = value || selectedSize.value
|
|
|
+ if (selectedValue !== 'custom') {
|
|
|
// 如果是预设尺寸,可以在这里执行相关操作
|
|
|
- console.log('选择了尺寸:', value, sizePresets[value])
|
|
|
+ console.log('选择了尺寸:', selectedValue, sizePresets[selectedValue])
|
|
|
// 可以更新生成图片的参数
|
|
|
}
|
|
|
}
|
|
|
@@ -1159,6 +1126,10 @@ const downloadImage = async (type) => {
|
|
|
ElMessage.warning('新图不存在')
|
|
|
return
|
|
|
}
|
|
|
+ } else {
|
|
|
+ console.error('未知的下载类型:', type)
|
|
|
+ ElMessage.error('未知的下载类型')
|
|
|
+ return
|
|
|
}
|
|
|
|
|
|
console.log(`下载${type}图信息:`, { imagePath, originalFileName })
|
|
|
@@ -1171,8 +1142,14 @@ const downloadImage = async (type) => {
|
|
|
const safeFileName = generateSafeFilename(originalFileName, imagePath, type)
|
|
|
console.log('安全文件名:', safeFileName)
|
|
|
|
|
|
- // 调用下载
|
|
|
- await downloadWithBlob(fullUrl, safeFileName)
|
|
|
+ try {
|
|
|
+ // 调用下载
|
|
|
+ await downloadWithBlob(fullUrl, safeFileName)
|
|
|
+ console.log('下载函数调用成功')
|
|
|
+ } catch (error) {
|
|
|
+ console.error('下载函数调用失败:', error)
|
|
|
+ ElMessage.error('下载过程中发生错误')
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
// 生成安全的文件名(处理中文和特殊字符)
|
|
|
@@ -1209,6 +1186,30 @@ const getFileExtension = (filepath) => {
|
|
|
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 {
|
|
|
@@ -1268,13 +1269,19 @@ const downloadWithBlob = async (url, filename) => {
|
|
|
} catch (directError) {
|
|
|
console.error('直接下载失败:', directError)
|
|
|
|
|
|
- // 备用方案2:直接打开
|
|
|
+ // 备用方案2:使用更简单的下载方法
|
|
|
try {
|
|
|
- console.log('尝试直接打开...')
|
|
|
- window.open(url, '_blank')
|
|
|
- ElMessage.info('已在新的标签页打开图片')
|
|
|
- } catch (openError) {
|
|
|
- console.error('所有方法都失败:', openError)
|
|
|
+ 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('下载失败,请检查网络或联系管理员')
|
|
|
}
|
|
|
}
|
|
|
@@ -1597,6 +1604,10 @@ defineExpose({
|
|
|
resize: none;
|
|
|
}
|
|
|
|
|
|
+ :deep(.el-textarea__inner) {
|
|
|
+ resize: none !important;
|
|
|
+ }
|
|
|
+
|
|
|
.right-column {
|
|
|
display: flex;
|
|
|
flex-direction: column;
|
|
|
@@ -1743,8 +1754,27 @@ defineExpose({
|
|
|
font-weight: bold;
|
|
|
}
|
|
|
|
|
|
- .image-preview:hover .image-download-btn {
|
|
|
- opacity: 1;
|
|
|
+ .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 {
|
|
|
@@ -1771,4 +1801,25 @@ defineExpose({
|
|
|
.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>
|