|
|
@@ -34,36 +34,36 @@
|
|
|
</el-descriptions>
|
|
|
|
|
|
<el-descriptions
|
|
|
- title=""
|
|
|
- column="7"
|
|
|
- border
|
|
|
- class="queue-status-box"
|
|
|
- >
|
|
|
- <el-descriptions-item label="总任务数">
|
|
|
- <el-tag type="info">{{ stats['总任务数'] }}</el-tag>
|
|
|
- </el-descriptions-item>
|
|
|
-
|
|
|
- <el-descriptions-item label="待处理">
|
|
|
- <el-tag type="warning">{{ stats['待处理'] }}</el-tag>
|
|
|
- </el-descriptions-item>
|
|
|
-
|
|
|
- <el-descriptions-item label="处理中">
|
|
|
- <el-tag type="primary">{{ stats['处理中'] }}</el-tag>
|
|
|
- </el-descriptions-item>
|
|
|
-
|
|
|
- <el-descriptions-item label="成功">
|
|
|
- <el-tag type="success">{{ stats['成功'] }}</el-tag>
|
|
|
- </el-descriptions-item>
|
|
|
-
|
|
|
- <el-descriptions-item label="失败">
|
|
|
- <el-tag type="danger">{{ stats['失败'] }}</el-tag>
|
|
|
- </el-descriptions-item>
|
|
|
+ title=""
|
|
|
+ column="7"
|
|
|
+ border
|
|
|
+ class="queue-status-box">
|
|
|
|
|
|
- <el-descriptions-item label="操作">
|
|
|
- <el-button type="danger" size="small" @click="stopQueueclick" :loading="isLoading" :disabled="isLoading">全部停止处理</el-button>
|
|
|
+ <el-descriptions-item label="总任务数">
|
|
|
+ <el-tag type="info">{{ queuestats['总任务数'] }}</el-tag>
|
|
|
+ </el-descriptions-item>
|
|
|
+
|
|
|
+ <el-descriptions-item label="待处理">
|
|
|
+ <el-tag type="warning">{{ queuestats['待处理'] }}</el-tag>
|
|
|
+ </el-descriptions-item>
|
|
|
+
|
|
|
+ <el-descriptions-item label="处理中">
|
|
|
+ <el-tag type="primary">{{ queuestats['处理中'] }}</el-tag>
|
|
|
+ </el-descriptions-item>
|
|
|
+
|
|
|
+ <el-descriptions-item label="成功">
|
|
|
+ <el-tag type="success">{{ queuestats['成功'] }}</el-tag>
|
|
|
+ </el-descriptions-item>
|
|
|
+
|
|
|
+ <el-descriptions-item label="失败">
|
|
|
+ <el-tag type="danger">{{ queuestats['失败'] }}</el-tag>
|
|
|
+ </el-descriptions-item>
|
|
|
+
|
|
|
+ <el-descriptions-item label="操作">
|
|
|
+ <el-button type="danger" size="small" @click="stopQueueclick" :loading="isLoading" :disabled="isLoading">全部停止处理</el-button>
|
|
|
<el-button type="primary" size="small" @click="handleViewQueue" :loading="isLoading">任务列表</el-button>
|
|
|
- </el-descriptions-item>
|
|
|
- </el-descriptions>
|
|
|
+ </el-descriptions-item>
|
|
|
+ </el-descriptions>
|
|
|
|
|
|
<el-dialog
|
|
|
v-model="queueDialogVisible"
|
|
|
@@ -112,10 +112,11 @@
|
|
|
<br>
|
|
|
<el-table :data="tableData" border height="450" v-loading="loading">
|
|
|
<el-table-column prop="id" label="ID" width="50" />
|
|
|
- <el-table-column prop="old_image_url" label="原图目录" width="320" />
|
|
|
- <el-table-column prop="new_image_url" label="出图目录" width="320" />
|
|
|
- <el-table-column prop="image_count" label="图片数量" width="90" />
|
|
|
- <el-table-column prop="count" label="总数量" width="90" />
|
|
|
+ <el-table-column prop="old_image_url" label="原图目录" width="360" />
|
|
|
+ <el-table-column prop="new_image_url" label="出图目录" width="360" />
|
|
|
+ <el-table-column prop="old_img_count" label="图片数量" width="90" />
|
|
|
+ <el-table-column prop="new_image_count" label="总数量" width="90" />
|
|
|
+ <el-table-column prop="queueLog_model_name" label="任务执行状态" width="110" />
|
|
|
<el-table-column align="center" label="操作" width="230">
|
|
|
<template #default="{ row, $index }" >
|
|
|
<el-button @click="record_deleteRow(row,$index)" type="primary" size="small"
|
|
|
@@ -124,32 +125,30 @@
|
|
|
</el-button>
|
|
|
<el-button @click="packRow(row,$index)" type="primary" size="small"
|
|
|
style="font-size: 16px;padding: 0px;width: 100px;">
|
|
|
- 打包文件zip
|
|
|
+ 打包压缩zip
|
|
|
</el-button>
|
|
|
</template>
|
|
|
</el-table-column>
|
|
|
</el-table>
|
|
|
|
|
|
- <el-dialog v-model="showDescDialog" title="" width="890px" top="2%">
|
|
|
- <div style="display: flex; gap: 10px; max-height: 80vh; overflow: hidden;">
|
|
|
+ <el-dialog v-model="showDescDialog" title="" width="890px" top="0%">
|
|
|
+ <div style="display: flex; gap: 10px; max-height: 70vh; overflow: hidden;">
|
|
|
<!-- 左侧图片区域,自适应图片尺寸,可滚动查看完整图片 -->
|
|
|
- <div
|
|
|
- style="flex: 1; display: flex; align-items: start; justify-content: center; border: 1px solid #eee; overflow: auto; max-height: 80vh;"
|
|
|
- >
|
|
|
+ <div style="flex: 1; display: flex; align-items: start; justify-content: center; border: 1px solid #eee; overflow: auto; max-height: 80vh;">
|
|
|
<el-image
|
|
|
- :src="formatImageUrl(new_image_url)"
|
|
|
+ :src="formatImageUrl(path_image_url)"
|
|
|
fit="contain"
|
|
|
style="max-width: 100%; height: auto;"
|
|
|
- :preview-src-list="[formatImageUrl(new_image_url)]"
|
|
|
+ :preview-src-list="[formatImageUrl(path_image_url)]"
|
|
|
:initial-index="0"
|
|
|
/>
|
|
|
</div>
|
|
|
|
|
|
- <!-- 右侧描述信息,固定高度,可滚动 -->
|
|
|
- <div style="width: 350px; white-space: pre-wrap; overflow-y: auto; max-height: 63vh; border: 1px solid #f0f0f0; padding: 10px;">
|
|
|
- <span style="color: red;">文生图提示词</span>
|
|
|
- {{ activeDescription }}
|
|
|
- </div>
|
|
|
+ <!-- 图像描述弹窗内容区域 -->
|
|
|
+ <div style="width: 350px; white-space: pre-wrap; overflow-y: auto; max-height: 63vh; border: 1px solid #f0f0f0; padding: 10px;">
|
|
|
+ <div v-html="activeDescription"></div>
|
|
|
+ </div>
|
|
|
+
|
|
|
</div>
|
|
|
|
|
|
<el-descriptions title="" :column="1" border>
|
|
|
@@ -165,13 +164,6 @@
|
|
|
<span>{{ path_image_url }}</span>
|
|
|
</el-descriptions-item>
|
|
|
</el-descriptions>
|
|
|
-
|
|
|
-<!-- <br />
|
|
|
- <span>{{ img_id }}</span>
|
|
|
- <br />
|
|
|
- <span>{{ model }}</span>
|
|
|
- <br />
|
|
|
- <span>{{ path_image_url }}</span> -->
|
|
|
</el-dialog>
|
|
|
|
|
|
<el-dialog
|
|
|
@@ -182,36 +174,6 @@
|
|
|
top="4vh"
|
|
|
destroy-on-close
|
|
|
>
|
|
|
-
|
|
|
-
|
|
|
- <!-- <el-descriptions
|
|
|
- title=""
|
|
|
- column="7"
|
|
|
- border
|
|
|
- class="queue-status-box"
|
|
|
- >
|
|
|
- <el-descriptions-item label="总任务数">
|
|
|
- <el-tag type="info">{{ queuestats['总任务数'] }}</el-tag>
|
|
|
- </el-descriptions-item>
|
|
|
-
|
|
|
- <el-descriptions-item label="待处理">
|
|
|
- <el-tag type="warning">{{ queuestats['待处理'] }}</el-tag>
|
|
|
- </el-descriptions-item>
|
|
|
-
|
|
|
- <el-descriptions-item label="处理中">
|
|
|
- <el-tag type="primary">{{ queuestats['处理中'] }}</el-tag>
|
|
|
- </el-descriptions-item>
|
|
|
-
|
|
|
- <el-descriptions-item label="成功">
|
|
|
- <el-tag type="success">{{ queuestats['成功'] }}</el-tag>
|
|
|
- </el-descriptions-item>
|
|
|
-
|
|
|
- <el-descriptions-item label="失败">
|
|
|
- <el-tag type="danger">{{ queuestats['失败'] }}</el-tag>
|
|
|
- </el-descriptions-item>
|
|
|
- </el-descriptions> -->
|
|
|
-
|
|
|
-
|
|
|
<el-table
|
|
|
:data="table_Taskqueue"
|
|
|
row-key="id"
|
|
|
@@ -239,8 +201,9 @@
|
|
|
v-model="mlinventoryVisible"
|
|
|
:before-close="mlcloseDialog"
|
|
|
title=""
|
|
|
- width="95%"
|
|
|
- top="4vh"
|
|
|
+ width="100%"
|
|
|
+ style="height: 97%;margin: 0px;"
|
|
|
+ top="2vh"
|
|
|
destroy-on-close
|
|
|
>
|
|
|
<div class="dialog-body">
|
|
|
@@ -248,6 +211,8 @@
|
|
|
<div class="dialog-left">
|
|
|
<el-form ref="elSearchFormRef" class="demo-form-inline">
|
|
|
<el-form-item>
|
|
|
+ <el-button type="primary" title="" @click="Refresh_Status" :loading="isLoading">刷新执行状态</el-button>
|
|
|
+
|
|
|
<span>选择状态:</span>
|
|
|
<el-select
|
|
|
v-model="filterStatus"
|
|
|
@@ -256,8 +221,12 @@
|
|
|
style="width: 120px;"
|
|
|
>
|
|
|
<el-option label="全部" value="全部" />
|
|
|
- <el-option label="已出图" value="已出图" />
|
|
|
+ <el-option label="已出图" value="已出图" />
|
|
|
<el-option label="未出图" value="未出图" />
|
|
|
+ <el-option label="图生文" value="图生文" />
|
|
|
+ <el-option label="文生文" value="文生文" />
|
|
|
+ <el-option label="文生图" value="文生图" />
|
|
|
+ <el-option label="图生图" value="图生图" />
|
|
|
</el-select>
|
|
|
</el-form-item>
|
|
|
</el-form>
|
|
|
@@ -266,43 +235,45 @@
|
|
|
:data="tableData_lsit"
|
|
|
row-key="id"
|
|
|
border
|
|
|
- style="width: 100%; height: 60vh;"
|
|
|
+ style="width: 100%; height: 80vh;"
|
|
|
v-loading="loading"
|
|
|
highlight-current-row
|
|
|
tooltip-effect="dark"
|
|
|
- :row-style="{ height: '40px' }"
|
|
|
- :cell-style="{ padding: '4px' }"
|
|
|
- :header-cell-style="{ padding: '4px' }"
|
|
|
- :header-row-style="{ height: '40px' }"
|
|
|
+ :row-style="{ height: '0px' }"
|
|
|
+ :cell-style="{ padding: '0px' }"
|
|
|
+ :header-cell-style="{ padding: '0px' }"
|
|
|
+ :header-row-style="{ height: '0px' }"
|
|
|
@selection-change="SelectionChange"
|
|
|
:show-overflow-tooltip="true"
|
|
|
@row-click="handleRowClick"
|
|
|
>
|
|
|
<el-table-column type="selection" width="50" align="center" />
|
|
|
- <el-table-column prop="id" label="序号" width="70" align="center" />
|
|
|
- <el-table-column label="原图尺寸" width="120" align="center">
|
|
|
- <template #default="{ row }">
|
|
|
- {{ row.width }} x {{ row.height }}
|
|
|
- </template>
|
|
|
- </el-table-column>
|
|
|
-
|
|
|
- <el-table-column label="状态" width="120" align="center">
|
|
|
+ <el-table-column prop="id" label="序号" width="60" align="center" />
|
|
|
+
|
|
|
+ <el-table-column label="状态" width="86" align="center">
|
|
|
<template #default="{ row }">
|
|
|
<el-tag v-if="row.status === 1" type="success">已出图</el-tag>
|
|
|
- <el-tag v-else type="info">未出图</el-tag>
|
|
|
+ <el-tag v-else type="danger">未出图</el-tag>
|
|
|
</template>
|
|
|
</el-table-column>
|
|
|
-
|
|
|
+ <el-table-column prop="status_name" label="操作模型" width="90" align="center" />
|
|
|
+ <el-table-column prop="queue_status" label="状态说明" width="140" align="center" />
|
|
|
<el-table-column prop="same_count" label="出图数量" width="90" align="center" />
|
|
|
- <el-table-column label="原图预览" width="150">
|
|
|
+ <el-table-column label="原图预览" width="120">
|
|
|
<template #default="{ row }">
|
|
|
<img
|
|
|
:src="formatImageUrl(row.path)"
|
|
|
- style="width: 100px; height: 100px; object-fit: contain; cursor: pointer;"
|
|
|
+ style="width: 90px; height: 70px; object-fit: contain; cursor: pointer;"
|
|
|
@click="showDescription(row, 'old')"
|
|
|
/>
|
|
|
</template>
|
|
|
</el-table-column>
|
|
|
+
|
|
|
+ <el-table-column label="原图尺寸" width="120" align="center">
|
|
|
+ <template #default="{ row }">
|
|
|
+ {{ row.width }} x {{ row.height }}
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
</el-table>
|
|
|
|
|
|
<div class="gva-pagination">
|
|
|
@@ -310,7 +281,7 @@
|
|
|
@size-change="handleSizeChange"
|
|
|
@current-change="handleCurrentChange"
|
|
|
:current-page="page"
|
|
|
- :page-sizes="[10, 30, 50, 100, 500]"
|
|
|
+ :page-sizes="[10, 30, 50, 100, 500,1000]"
|
|
|
:page-size="pageSize"
|
|
|
layout="total, sizes, prev, pager, next"
|
|
|
:total="total"
|
|
|
@@ -325,25 +296,84 @@
|
|
|
<el-form :model="mlformdata" label-position="top">
|
|
|
<el-descriptions column="1" border>
|
|
|
|
|
|
- <el-descriptions-item label="图生文提示词">
|
|
|
- <el-input
|
|
|
- v-model="textareaContent"
|
|
|
- disabled
|
|
|
- rows="6"
|
|
|
- class="custom-textarea"
|
|
|
- type="textarea"
|
|
|
- />
|
|
|
- </el-descriptions-item>
|
|
|
-
|
|
|
- <el-descriptions-item label="文生文提示词">
|
|
|
- <el-input
|
|
|
- v-model="english_content"
|
|
|
- disabled
|
|
|
- rows="5"
|
|
|
- class="custom-textarea"
|
|
|
- type="textarea"
|
|
|
- />
|
|
|
- </el-descriptions-item>
|
|
|
+ <el-descriptions-item label="操作">
|
|
|
+ <el-button type="primary" title="执行选择中图片到队列中,图生文" @click="imgtotext" :loading="isLoading">执行图生文</el-button>
|
|
|
+ <el-button type="primary" title="执行选择中图片到队列中,文生文" @click="texttotxt" :loading="isLoading">执行文生文</el-button>
|
|
|
+ <el-button type="primary" title="执行选择中图片到队列中,文生图" @click="texttoimg" :loading="isLoading">执行文生图</el-button>
|
|
|
+ <el-button type="primary" title="执行选中图片到队列中,执行顺序:图生文->文生文->文生图->图生图" @click="handleSelected" :loading="isLoading" :disabled="isLoading">执行选择任务</el-button>
|
|
|
+ <el-button type="primary" title="执行当前所有图片到队列中,执行顺序:图生文->文生文->文生图->图生图" @click="handleAll" :loading="isLoading">执行全部任务</el-button>
|
|
|
+ <el-button type="primary" title="执行选择中图片到队列中,图生图" @click="imgtoimg" :loading="isLoading">SD图生图</el-button>
|
|
|
+ </el-descriptions-item>
|
|
|
+
|
|
|
+ <el-descriptions-item label="文生文模型">
|
|
|
+ <el-radio-group v-model="txttotxt_selectedOption">
|
|
|
+ <el-radio label="gemini-2.0-flash">gemini-2.0-flash</el-radio>
|
|
|
+ <el-radio label="gtp-4">gtp-4</el-radio>
|
|
|
+ </el-radio-group>
|
|
|
+ </el-descriptions-item>
|
|
|
+
|
|
|
+ <el-descriptions-item label="文生图模型">
|
|
|
+ <el-radio-group v-model="selectedOption">
|
|
|
+ <el-radio label="dall-e-3">dall-e-3</el-radio>
|
|
|
+ <el-radio label="gpt-image-1">gpt-image-1</el-radio>
|
|
|
+ </el-radio-group>
|
|
|
+ </el-descriptions-item>
|
|
|
+
|
|
|
+ <el-descriptions-item label="出图预览">
|
|
|
+ <div style="display: flex; gap: 20px; align-items: flex-start;">
|
|
|
+ <!-- 左侧:图片列表区域 -->
|
|
|
+ <div style="flex: 1;">
|
|
|
+ <div class="image-preview-wrap" style="height: 140px;">
|
|
|
+ <div
|
|
|
+ v-for="(img, index) in imageList"
|
|
|
+ :key="'fixed-' + index"
|
|
|
+ class="image-item"
|
|
|
+ @click="showDescription(img, 'new')"
|
|
|
+ >
|
|
|
+ <img :src="formatImageUrl(img.new_image_url)" />
|
|
|
+ 1024x1024
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="image-preview-wrap" style="margin-top: 16px; height: 145px;">
|
|
|
+ <div
|
|
|
+ v-for="(img, index) in imageList"
|
|
|
+ :key="'custom-' + index"
|
|
|
+ class="image-items"
|
|
|
+ @click="showDescription(img, 'custom')"
|
|
|
+ >
|
|
|
+ <img :src="formatImageUrl(img.custom_image_url)" />
|
|
|
+ {{ img.size }}
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="image-preview-wrap" style="margin-top: 16px; height: 145px;">
|
|
|
+ <div
|
|
|
+ v-for="(img, index) in imageList"
|
|
|
+ :key="'imgtoimg-' + index"
|
|
|
+ class="image-itemsimg"
|
|
|
+ @click="showDescription(img, 'san')"
|
|
|
+ >
|
|
|
+ <img :src="formatImageUrl(img.imgtoimg_url)" />
|
|
|
+ 图生图 679x862
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 右侧:文字描述区域 -->
|
|
|
+ <div
|
|
|
+ style="
|
|
|
+ width: 500px;
|
|
|
+ white-space: pre-wrap;
|
|
|
+ overflow-y: auto;
|
|
|
+ max-height: 50vh;
|
|
|
+ border: 1px solid #f0f0f0;
|
|
|
+ padding: 10px;
|
|
|
+ "
|
|
|
+ >
|
|
|
+ <div v-html="activeDescription"></div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </el-descriptions-item>
|
|
|
+
|
|
|
|
|
|
<el-descriptions-item label="出图尺寸">
|
|
|
<div style="display: flex; align-items: center; flex-wrap: wrap; gap: 12px;">
|
|
|
@@ -357,66 +387,37 @@
|
|
|
<el-input-number v-model="num" :step="1" />
|
|
|
</el-descriptions-item>
|
|
|
|
|
|
- <el-descriptions-item label="出图模型">
|
|
|
- <el-radio-group v-model="selectedOption">
|
|
|
- <el-radio label="dall-e-3">dall-e-3</el-radio>
|
|
|
- <el-radio label="gpt-image-1">gpt-image-1</el-radio>
|
|
|
- </el-radio-group>
|
|
|
- </el-descriptions-item>
|
|
|
-
|
|
|
- <el-descriptions-item label="操作">
|
|
|
- <div class="button-group">
|
|
|
- <el-button type="primary" title="执行选择中图片到队列中" @click="imgtotext" :loading="isLoading">执行图生文</el-button>
|
|
|
- <el-button type="primary" title="执行选择中图片到队列中" @click="texttoimg" :loading="isLoading">执行文生图</el-button>
|
|
|
- <el-button type="primary" title="执行选择中图片到队列中" @click="texttotxt" :loading="isLoading">执行文生文</el-button>
|
|
|
- <el-button type="primary" title="执行选择中图片到队列中" @click="handleSelected" :loading="isLoading" :disabled="isLoading">执行选择任务</el-button>
|
|
|
- <el-button type="primary" title="执行当前页面所有图片到队列中" @click="handleAll" :loading="isLoading">执行全部任务</el-button>
|
|
|
- </div>
|
|
|
- </el-descriptions-item>
|
|
|
-
|
|
|
<el-descriptions-item label="任务队列">
|
|
|
- <el-table :data="table_queue" border
|
|
|
- style="width: 100%; height: 30vh;"
|
|
|
+ <el-table
|
|
|
+ :data="table_queue" border
|
|
|
+ :show-overflow-tooltip="true"
|
|
|
+ v-loading="loading"
|
|
|
+ tooltip-effect="dark"
|
|
|
+ :row-style="{ height: '30px' }"
|
|
|
+ :cell-style="{ padding: '2px' }"
|
|
|
+ :header-cell-style="{ padding: '0px' }"
|
|
|
+ :header-row-style="{ height: '30px' }"
|
|
|
+ style="width: 100%; height: 21vh;"
|
|
|
>
|
|
|
- <el-table-column prop="id" label="任务ID" width="80" />
|
|
|
+ <el-table-column prop="id" label="ID" width="50" />
|
|
|
<el-table-column prop="status" label="状态" width="100" />
|
|
|
- <el-table-column prop="model" label="队列模型" width="180" />
|
|
|
- <el-table-column prop="image_count" label="执行数量" width="95" />
|
|
|
- <el-table-column prop="排队中的数量" label="队列中" width="95" />
|
|
|
- <el-table-column prop="处理中数量" label="处理中" width="95" />
|
|
|
- <el-table-column prop="已完成数量" label="成功" width="95" />
|
|
|
- <!-- <el-table-column align="center" label="操作" width="130">
|
|
|
- <template #default="{ row, $index }" >
|
|
|
- <el-button @click="record_queueRow(row,$index)" type="primary" size="small"
|
|
|
- style="font-size: 16px;padding: 0px;width: 80px;">
|
|
|
- 任务列表
|
|
|
- </el-button>
|
|
|
-
|
|
|
- </template>
|
|
|
- </el-table-column> -->
|
|
|
+ <el-table-column prop="model" label="队列模型" width="170" />
|
|
|
+ <el-table-column prop="model_name" label="队列模型" width="90" />
|
|
|
+ <el-table-column prop="image_count" label="执行数量" width="90" />
|
|
|
+ <el-table-column prop="排队中的数量" label="队列中" width="70" />
|
|
|
+ <el-table-column prop="处理中数量" label="处理中" width="70" />
|
|
|
+ <el-table-column prop="已完成数量" label="成功" width="70" />
|
|
|
+ <el-table-column prop="失败数量" label="失败" width="70" />
|
|
|
</el-table>
|
|
|
</el-descriptions-item>
|
|
|
-
|
|
|
- <el-descriptions-item label="出图预览">
|
|
|
- <div class="image-preview-wrap">
|
|
|
- <div v-for="(img, index) in imageList" :key="'fixed-' + index" class="image-item" @click="showDescription(img, 'new')">
|
|
|
- <img :src="formatImageUrl(img.new_image_url)" />
|
|
|
- <div>1024x1024</div>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
-
|
|
|
- <div class="image-preview-wrap" style="margin-top: 16px;">
|
|
|
- <div v-for="(img, index) in imageList" :key="'custom-' + index" class="image-item" @click="showDescription(img, 'custom')">
|
|
|
- <img :src="formatImageUrl(img.custom_image_url)" />
|
|
|
- <div>{{ img.size }}</div>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- </el-descriptions-item>
|
|
|
+
|
|
|
</el-descriptions>
|
|
|
</el-form>
|
|
|
</el-card>
|
|
|
</div>
|
|
|
</div>
|
|
|
+
|
|
|
+
|
|
|
</div>
|
|
|
</el-dialog>
|
|
|
|
|
|
@@ -461,7 +462,7 @@ const uploadsPort = import.meta.env.VITE_UPLOADS_PORT || '9093'
|
|
|
const uploadUrl = ref(`${basePath}:${uploadsPort}/api/Facility/ImgUpload`)
|
|
|
const uploadHeaders = {
|
|
|
'Content-Type': 'multipart/form-data',
|
|
|
- 'Authorization': 'Bearer ' + localStorage.getItem('token') // 添加认证头
|
|
|
+ 'Authorization': 'Bearer ' + localStorage.getItem('token')
|
|
|
}
|
|
|
|
|
|
// 文件列表
|
|
|
@@ -559,7 +560,7 @@ const handleExceed = (files, fileList) => {
|
|
|
|
|
|
|
|
|
// --------------------- 查看队列任务 ---------------------
|
|
|
-const stats = ref({
|
|
|
+const queuestats = ref({
|
|
|
总任务数: 0,
|
|
|
待处理: 0,
|
|
|
处理中: 0,
|
|
|
@@ -569,8 +570,9 @@ const stats = ref({
|
|
|
//队列状态
|
|
|
const queueStats_list = async () => {
|
|
|
const res = await queueStats()
|
|
|
+ console.log(res)
|
|
|
if (res.code === 0) {
|
|
|
- stats.value = res.data
|
|
|
+ queuestats.value = res.data
|
|
|
}
|
|
|
}
|
|
|
queueStats_list()
|
|
|
@@ -634,26 +636,7 @@ const queueDialog = async () => {
|
|
|
queueDialogVisible.value = false
|
|
|
}
|
|
|
|
|
|
-// --------------------- 更新图片列表方法 ---------------------
|
|
|
-// const updateImageList = async () => {
|
|
|
-// const res = await getlsit({ path: _oldrow.value['path'] })
|
|
|
-// if (res.data === null) {
|
|
|
-// imageList.value = []
|
|
|
-// } else {
|
|
|
-// imageList.value = res.data.map(item => ({
|
|
|
-// chinese_description: item.chinese_description,
|
|
|
-// new_image_url: item.new_image_url,
|
|
|
-// custom_image_url: item.custom_image_url,
|
|
|
-// size: item.size
|
|
|
-// }))
|
|
|
-// }
|
|
|
-// }
|
|
|
-
|
|
|
// --------------------- 查看详情 ---------------------
|
|
|
-// 分页
|
|
|
-const page = ref(1)
|
|
|
-const total = ref(0)
|
|
|
-const pageSize = ref(50)
|
|
|
const fetchPreviewImages = async () => {
|
|
|
loading.value = true;
|
|
|
const params = {
|
|
|
@@ -666,6 +649,14 @@ const fetchPreviewImages = async () => {
|
|
|
params.status = 1
|
|
|
} else if (filterStatus.value === '未出图') {
|
|
|
params.status = 0
|
|
|
+ }else if(filterStatus.value === '图生文') {
|
|
|
+ params.status_name = "图生文"
|
|
|
+ }else if(filterStatus.value === '文生文') {
|
|
|
+ params.status_name = "文生文"
|
|
|
+ }else if(filterStatus.value === '文生图') {
|
|
|
+ params.status_name = "文生图"
|
|
|
+ }else if(filterStatus.value === '图生图') {
|
|
|
+ params.status_name = "图生图"
|
|
|
}
|
|
|
|
|
|
// 获取分页数据
|
|
|
@@ -675,27 +666,13 @@ const fetchPreviewImages = async () => {
|
|
|
tableData_lsit.value = res.data;
|
|
|
total.value = res.total;
|
|
|
}
|
|
|
-
|
|
|
- // 再发起全量请求(不分页)
|
|
|
- const allParams = {
|
|
|
- path: _resrow.value.old_image_url,
|
|
|
- limit: 10000 // 给一个极大的值相当于全量
|
|
|
- };
|
|
|
-
|
|
|
- if (filterStatus.value === '已出图') {
|
|
|
- allParams.status = 1
|
|
|
- } else if (filterStatus.value === '未出图') {
|
|
|
- allParams.status = 0
|
|
|
- }
|
|
|
-
|
|
|
- const allRes = await getPreviewimg(allParams);
|
|
|
- if (allRes.code === 0) {
|
|
|
- allTableData.value = allRes.data;
|
|
|
- }
|
|
|
-
|
|
|
loading.value = false;
|
|
|
};
|
|
|
|
|
|
+// 分页
|
|
|
+const page = ref(1)
|
|
|
+const total = ref(0)
|
|
|
+const pageSize = ref(50)
|
|
|
// 页码变化
|
|
|
const handleCurrentChange = (val) => {
|
|
|
page.value = val;
|
|
|
@@ -705,7 +682,7 @@ const handleCurrentChange = (val) => {
|
|
|
// 每页数量变化
|
|
|
const handleSizeChange = (val) => {
|
|
|
pageSize.value = val;
|
|
|
- page.value = 1; // 切换每页数量时,重置为第一页
|
|
|
+ page.value = 1;
|
|
|
fetchPreviewImages();
|
|
|
};
|
|
|
|
|
|
@@ -724,26 +701,34 @@ const height = ref('')
|
|
|
const mlformdata = ref({})
|
|
|
const tableData_lsit = ref([])
|
|
|
const _resrow = ref('')
|
|
|
-const textareaContent = ref('');
|
|
|
-const english_content = ref('');
|
|
|
|
|
|
const TaskqueueVisible = ref(false)
|
|
|
const table_queue = ref([])
|
|
|
const table_Taskqueue = ref([])
|
|
|
//查看详情按钮
|
|
|
-const record_deleteRow = async (row) => {
|
|
|
- getPreviewSubDirslist()
|
|
|
+const record_deleteRow = async (row) => {
|
|
|
+ // getPreviewSubDirslist()
|
|
|
_resrow.value = row;
|
|
|
- page.value = 1;
|
|
|
+ // page.value = 1;
|
|
|
+
|
|
|
+ //打开弹窗
|
|
|
mlinventoryVisible.value = true;
|
|
|
|
|
|
- console.log(row['old_image_url'])
|
|
|
+ //清空信息保持数据最新
|
|
|
+ imageList.value = []
|
|
|
+ img_id.value = '';
|
|
|
+ model.value = '';
|
|
|
+ new_image_url.value = '';
|
|
|
+ imgtoimg_url.value = '';
|
|
|
+ path_image_url.value = '';
|
|
|
+ activeDescription.value = '';
|
|
|
+
|
|
|
+ // 任务队列
|
|
|
const queue_logs = await get_queue_logs({ old_image_file: row['old_image_url'] });
|
|
|
table_queue.value = queue_logs.data;
|
|
|
|
|
|
+ // 出图尺寸
|
|
|
const res = await Template();
|
|
|
- textareaContent.value = res.data.content
|
|
|
- english_content.value = res.data.english_content
|
|
|
height.value = res.data.height
|
|
|
width.value = res.data.width
|
|
|
|
|
|
@@ -767,27 +752,39 @@ const imageList = ref([]);
|
|
|
const _oldrow = ref('');
|
|
|
//点击当前行
|
|
|
const handleRowClick = async (row) => {
|
|
|
+ // fetchPreviewImages();
|
|
|
+
|
|
|
console.log("当前行信息",row)
|
|
|
- _oldrow.value = row
|
|
|
|
|
|
- const queue_logs = await get_queue_logs({ old_image_file: _resrow.value['old_image_url'] });
|
|
|
- table_queue.value = queue_logs.data;
|
|
|
+ // 文本内容高亮处理
|
|
|
+ const zh = highlightKeywords(row['chinese_description'] || '');
|
|
|
+ const en = highlightKeywords(row['english_description'] || '');
|
|
|
+ const name = highlightKeywords(row['img_name'] || '');
|
|
|
|
|
|
- const res = await getlsit({ path: row['path'] });
|
|
|
- if (res.data === null) {
|
|
|
- imageList.value = [];
|
|
|
- } else {
|
|
|
- imageList.value = res.data.map(item => ({
|
|
|
- id: item.id,
|
|
|
- model: item.model,
|
|
|
- chinese_description: item.chinese_description,
|
|
|
- english_description: item.english_description,
|
|
|
- img_name: item.img_name,
|
|
|
- new_image_url: item.new_image_url,
|
|
|
- custom_image_url: item.custom_image_url,
|
|
|
- size: item.size
|
|
|
- }));
|
|
|
- }
|
|
|
+ activeDescription.value = `第一段:\n${zh}\n\n第二段:\n${en}\n\n第三段:\n${name}`;
|
|
|
+
|
|
|
+ _oldrow.value = row
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ const res = await getlsit({ path: row['path'] });
|
|
|
+ if (res.data === null) {
|
|
|
+ imageList.value = [];
|
|
|
+ } else {
|
|
|
+ imageList.value = res.data.map(item => ({
|
|
|
+ id: item.id,
|
|
|
+ model: item.model,
|
|
|
+ chinese_description: item.chinese_description,
|
|
|
+ english_description: item.english_description,
|
|
|
+ img_name: item.img_name,
|
|
|
+ new_image_url: item.new_image_url,
|
|
|
+ imgtoimg_url:item.imgtoimg_url,
|
|
|
+ custom_image_url: item.custom_image_url,
|
|
|
+ size: item.size
|
|
|
+ }));
|
|
|
+ const queue_logs = await get_queue_logs({ old_image_file: _resrow.value['old_image_url'] });
|
|
|
+ table_queue.value = queue_logs.data;
|
|
|
+ }
|
|
|
};
|
|
|
|
|
|
//关闭按钮
|
|
|
@@ -803,32 +800,64 @@ const path_image_url = ref('');
|
|
|
const img_id = ref('');
|
|
|
const model = ref('');
|
|
|
const new_image_url = ref('');
|
|
|
+const imgtoimg_url = ref('');
|
|
|
const showDescDialog = ref(false);
|
|
|
-const showDescription = (img, type) => {
|
|
|
- showDescDialog.value = true;
|
|
|
- new_image_url.value = ''
|
|
|
- path_image_url.value = ''
|
|
|
- if (type === 'new') {
|
|
|
- img_id.value = img.id;
|
|
|
- model.value = img.model;
|
|
|
- new_image_url.value = img.new_image_url || '';
|
|
|
- path_image_url.value = img.new_image_url || '图片未生成';
|
|
|
- activeDescription.value = "\n" + "\n" + img.chinese_description + "\n" + "\n" + img.english_description + "\n" + "\n" + img.img_name || '暂无说明';
|
|
|
- }else if (type === 'custom'){
|
|
|
- img_id.value = img.id;
|
|
|
- model.value = img.model;
|
|
|
- new_image_url.value = img.custom_image_url || '';
|
|
|
- path_image_url.value = img.custom_image_url || '图片未生成';
|
|
|
- activeDescription.value = "\n" + "\n" + img.chinese_description + "\n" + "\n" + img.english_description + "\n" + "\n" + img.img_name || '暂无说明';
|
|
|
- } else if (type === 'old') {
|
|
|
- img_id.value = "";
|
|
|
- model.value = "";
|
|
|
- new_image_url.value = img.path || '';
|
|
|
- path_image_url.value = img.path || '暂无说明';
|
|
|
- activeDescription.value = '';
|
|
|
- }else{
|
|
|
- console.log('无')
|
|
|
- }
|
|
|
+// 高亮关键词为红色
|
|
|
+const highlightKeywords = (text) => {
|
|
|
+ const keywords = ['几何', 'geometry', 'geometric'];
|
|
|
+ keywords.forEach(word => {
|
|
|
+ const reg = new RegExp(word, 'gi');
|
|
|
+ text = text.replace(reg, match => `<span style="color:red">${match}</span>`);
|
|
|
+ });
|
|
|
+ return text;
|
|
|
+};
|
|
|
+
|
|
|
+// 显示图像描述
|
|
|
+const showDescription = async (img, type) => {
|
|
|
+ showDescDialog.value = true;
|
|
|
+
|
|
|
+ Refresh_Status()
|
|
|
+ // 任务队列
|
|
|
+ const queue_logs = await get_queue_logs({ old_image_file: _resrow.value['old_image_url'] });
|
|
|
+ table_queue.value = queue_logs.data;
|
|
|
+
|
|
|
+ // 公共字段初始化
|
|
|
+ img_id.value = img.id || '';
|
|
|
+ model.value = img.model || '';
|
|
|
+ path_image_url.value = '';
|
|
|
+
|
|
|
+ // 文本内容高亮处理
|
|
|
+ const zh = highlightKeywords(img.chinese_description || '');
|
|
|
+ const en = highlightKeywords(img.english_description || '');
|
|
|
+ const name = highlightKeywords(img.img_name || '');
|
|
|
+
|
|
|
+ if (type === 'new') {
|
|
|
+
|
|
|
+ path_image_url.value = img.new_image_url || '图片未生成';
|
|
|
+ activeDescription.value = `第一段:\n${zh}\n\n第二段:\n${en}\n\n第三段:\n${name}`;
|
|
|
+ imgtoimg_url.value = img.imgtoimg_url || '图片未生成';
|
|
|
+
|
|
|
+ } else if (type === 'custom') {
|
|
|
+
|
|
|
+ path_image_url.value = img.custom_image_url || '图片未生成';
|
|
|
+ activeDescription.value = `第一段:\n${zh}\n\n第二段:\n${en}\n\n第三段:\n${name}`;
|
|
|
+ imgtoimg_url.value = img.imgtoimg_url || '图片未生成';
|
|
|
+
|
|
|
+ }else if (type === 'san') {
|
|
|
+
|
|
|
+ path_image_url.value = img.imgtoimg_url || '图片未生成';
|
|
|
+ imgtoimg_url.value = img.imgtoimg_url || '图片未生成';
|
|
|
+ activeDescription.value = '';
|
|
|
+ model.value = '';
|
|
|
+ }else if (type === 'old') {
|
|
|
+
|
|
|
+ path_image_url.value = img.path || '暂无说明';
|
|
|
+ imgtoimg_url.value = '';
|
|
|
+ activeDescription.value = '';
|
|
|
+
|
|
|
+ } else {
|
|
|
+ console.log('无效的类型');
|
|
|
+ }
|
|
|
};
|
|
|
|
|
|
|
|
|
@@ -840,41 +869,121 @@ const SelectionChange = (rows) => {
|
|
|
|
|
|
//查看详情右侧区域
|
|
|
const isLoading = ref(false)
|
|
|
+//执行次数默认值
|
|
|
const num = ref(1)
|
|
|
+
|
|
|
+//文生文模型下拉(默认值)
|
|
|
+const txttotxt_selectedOption = ref('gemini-2.0-flash')
|
|
|
+//文生图模型下拉(默认值)
|
|
|
const selectedOption = ref('dall-e-3')
|
|
|
|
|
|
|
|
|
+//刷新表格任务状态
|
|
|
+const Refresh_Status = async () => {
|
|
|
+ // 开始 loading
|
|
|
+ loading.value = true;
|
|
|
+
|
|
|
+ fetchPreviewImages();
|
|
|
+ // 任务队列
|
|
|
+ const queue_logs = await get_queue_logs({ old_image_file: _resrow.value['old_image_url'] });
|
|
|
+ table_queue.value = queue_logs.data;
|
|
|
+
|
|
|
+ // 延迟2秒再关闭loading
|
|
|
+ await new Promise(resolve => setTimeout(resolve, 3000));
|
|
|
+ isLoading.value = false;
|
|
|
+}
|
|
|
+
|
|
|
//执行图生文、选择执行选择图片,没有选择执行当前页图片处理
|
|
|
const imgtotext = () => {
|
|
|
processImages(toRaw(_parh.value),'图生文');
|
|
|
};
|
|
|
-
|
|
|
//执行文生文、选择执行选择图片,没有选择执行当前页图片处理
|
|
|
const texttotxt = () => {
|
|
|
processImages(toRaw(_parh.value),'文生文');
|
|
|
};
|
|
|
-
|
|
|
//执行文生图、选择执行选择图片
|
|
|
const texttoimg = () => {
|
|
|
processImages(toRaw(_parh.value),'文生图');
|
|
|
};
|
|
|
-
|
|
|
-
|
|
|
+//执行图生图、选择执行选择图片
|
|
|
+const imgtoimg = () => {
|
|
|
+ processImages(toRaw(_parh.value),'图生图');
|
|
|
+};
|
|
|
|
|
|
//执行选择任务
|
|
|
const handleSelected = () => {
|
|
|
- processImages(toRaw(_parh.value));
|
|
|
+ processImages(toRaw(_parh.value),'');
|
|
|
};
|
|
|
|
|
|
//执行全部任务
|
|
|
const allTableData = ref([]); // 全部数据缓存
|
|
|
-const handleAll = () => {
|
|
|
- const allPaths = toRaw(allTableData.value).map(item => item.path);
|
|
|
- processImages(allPaths);
|
|
|
+
|
|
|
+const handleAll = async () => {
|
|
|
+ try {
|
|
|
+ await ElMessageBox.confirm(
|
|
|
+ '确定要执行全部任务吗?',
|
|
|
+ '确认操作',
|
|
|
+ {
|
|
|
+ confirmButtonText: '确定',
|
|
|
+ cancelButtonText: '取消',
|
|
|
+ type: 'warning'
|
|
|
+ }
|
|
|
+ );
|
|
|
+
|
|
|
+ // 开始 loading
|
|
|
+ loading.value = true;
|
|
|
+
|
|
|
+ // 发起全量请求
|
|
|
+ const allParams = {
|
|
|
+ path: _resrow.value.old_image_url,
|
|
|
+ page: 1,
|
|
|
+ limit: 10000
|
|
|
+ };
|
|
|
+
|
|
|
+
|
|
|
+ // const allRes = await getPreviewimg(allParams);
|
|
|
+ // console.log(allRes);
|
|
|
+
|
|
|
+ // if (allRes.code === 0) {
|
|
|
+ // allTableData.value = allRes.data;
|
|
|
+ // const allPaths = toRaw(allTableData.value).map(item => item.path);
|
|
|
+ // processImages(toRaw(allPaths),'');
|
|
|
+ // } else {
|
|
|
+ // ElMessage.error(allRes.msg || '获取全部图片失败');
|
|
|
+ // }
|
|
|
+
|
|
|
+ const allRes = await getPreviewimg(allParams);
|
|
|
+ console.log(allRes);
|
|
|
+
|
|
|
+ if (allRes.code === 0) {
|
|
|
+ // 全部原始数据
|
|
|
+ allTableData.value = allRes.data;
|
|
|
+
|
|
|
+ // 只保留 status 为 0 且 status_name 为空的项
|
|
|
+ const filteredPaths = toRaw(allTableData.value)
|
|
|
+ .filter(item => item.status === 0 && !item.status_name)
|
|
|
+ .map(item => item.path);
|
|
|
+
|
|
|
+ processImages(filteredPaths, '');
|
|
|
+ } else {
|
|
|
+ ElMessage.error(allRes.msg || '获取全部图片失败');
|
|
|
+ }
|
|
|
+
|
|
|
+ } catch (err) {
|
|
|
+ // 用户点击取消时,不做任何操作
|
|
|
+ if (err !== 'cancel') {
|
|
|
+ ElMessage.error('操作取消');
|
|
|
+ }
|
|
|
+ } finally {
|
|
|
+ // 无论成功/失败/异常,最后关闭 loading
|
|
|
+ loading.value = false;
|
|
|
+ }
|
|
|
};
|
|
|
|
|
|
+
|
|
|
//队列操作 统一执行操作按钮处理方法
|
|
|
const processImages = async (files,type) => {
|
|
|
+
|
|
|
if (!Array.isArray(files) || files.length === 0) {
|
|
|
ElMessage.warning('请选择要处理的图片')
|
|
|
return
|
|
|
@@ -885,17 +994,6 @@ const processImages = async (files,type) => {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
- let prompt = '';
|
|
|
- if (type === '图生文') {
|
|
|
- prompt = textareaContent.value;
|
|
|
- } else if (type === '文生文') {
|
|
|
- prompt = english_content.value;
|
|
|
- }else if (type === '文生图') {
|
|
|
- prompt = '';
|
|
|
- }else{
|
|
|
- prompt = '';
|
|
|
- }
|
|
|
-
|
|
|
isLoading.value = true
|
|
|
let successCount = 0
|
|
|
const failList = []
|
|
|
@@ -903,7 +1001,7 @@ const processImages = async (files,type) => {
|
|
|
old_image_file:_resrow.value['old_image_url'],
|
|
|
type:type,
|
|
|
selectedOption:selectedOption.value,
|
|
|
- prompt: prompt,
|
|
|
+ txttotxt_selectedOption:txttotxt_selectedOption.value,
|
|
|
batch:files,
|
|
|
num:num.value,
|
|
|
width: width.value,
|
|
|
@@ -912,7 +1010,6 @@ const processImages = async (files,type) => {
|
|
|
|
|
|
//打印调试区域
|
|
|
// console.log(payload);
|
|
|
- // console.log(selectedOption.value)
|
|
|
// await new Promise(resolve => setTimeout(resolve, 2000));
|
|
|
// isLoading.value = false;
|
|
|
// return;
|
|
|
@@ -927,13 +1024,14 @@ const processImages = async (files,type) => {
|
|
|
console.warn('失败列表:', failList)
|
|
|
}
|
|
|
|
|
|
- const queue_logs = await get_queue_logs({ old_image_file: _resrow.value['old_image_url'] });
|
|
|
- table_queue.value = queue_logs.data;
|
|
|
-
|
|
|
-
|
|
|
// 延迟2秒再关闭loading
|
|
|
- await new Promise(resolve => setTimeout(resolve, 2000));
|
|
|
+ await new Promise(resolve => setTimeout(resolve, 3000));
|
|
|
isLoading.value = false;
|
|
|
+
|
|
|
+ const queue_logs = await get_queue_logs({ old_image_file: _resrow.value['old_image_url'] });
|
|
|
+ table_queue.value = queue_logs.data;
|
|
|
+
|
|
|
+
|
|
|
}
|
|
|
|
|
|
// --------------------- 打包zip ---------------------
|
|
|
@@ -944,7 +1042,7 @@ const packRow = async (row) => {
|
|
|
const res = await getPreviewimg({
|
|
|
path: row.old_image_url,
|
|
|
page: 1,
|
|
|
- limit: 9999
|
|
|
+ limit: 10000
|
|
|
});
|
|
|
if (res.code !== 0 || !res.data || res.data.length === 0) {
|
|
|
ElMessage.warning('未找到出图记录');
|
|
|
@@ -1186,7 +1284,7 @@ const packRow = async (row) => {
|
|
|
}
|
|
|
|
|
|
.dialog-body {
|
|
|
- height: 78vh;
|
|
|
+ height: 93vh;
|
|
|
display: flex;
|
|
|
gap: 20px;
|
|
|
overflow: hidden;
|
|
|
@@ -1211,7 +1309,7 @@ const packRow = async (row) => {
|
|
|
.dialog-right-scroll {
|
|
|
flex: 1;
|
|
|
overflow-y: auto;
|
|
|
- padding-right: 10px;
|
|
|
+ padding-right: 5px;
|
|
|
}
|
|
|
|
|
|
/* 按钮区域自动换行不拥挤 */
|
|
|
@@ -1219,7 +1317,7 @@ const packRow = async (row) => {
|
|
|
display: flex;
|
|
|
flex-wrap: wrap;
|
|
|
gap: 10px;
|
|
|
- margin-top: 10px;
|
|
|
+ margin-top: 5px;
|
|
|
}
|
|
|
|
|
|
/* 图片容器 */
|
|
|
@@ -1244,4 +1342,38 @@ const packRow = async (row) => {
|
|
|
font-size: 12px;
|
|
|
color: #666;
|
|
|
}
|
|
|
+
|
|
|
+.image-items {
|
|
|
+ position: relative;
|
|
|
+ text-align: center;
|
|
|
+ width: 107px;
|
|
|
+}
|
|
|
+.image-items img {
|
|
|
+ width: 95px;
|
|
|
+ height: 120px;
|
|
|
+ border: 1px solid #ccc;
|
|
|
+ object-fit: contain;
|
|
|
+}
|
|
|
+.image-items div {
|
|
|
+ margin-top: 4px;
|
|
|
+ font-size: 12px;
|
|
|
+ color: #666;
|
|
|
+}
|
|
|
+
|
|
|
+.image-itemsimg {
|
|
|
+ position: relative;
|
|
|
+ text-align: center;
|
|
|
+ width: 110px;
|
|
|
+}
|
|
|
+.image-itemsimg img {
|
|
|
+ width: 95px;
|
|
|
+ height: 120px;
|
|
|
+ border: 1px solid #ccc;
|
|
|
+ object-fit: contain;
|
|
|
+}
|
|
|
+.image-itemsimg div {
|
|
|
+ margin-top: 4px;
|
|
|
+ font-size: 12px;
|
|
|
+ color: #666;
|
|
|
+}
|
|
|
</style>
|