|
|
@@ -1,201 +1,2036 @@
|
|
|
<template>
|
|
|
- <div>
|
|
|
- <layout>
|
|
|
- <layout-header>
|
|
|
- <div class="">
|
|
|
- <!-- 按钮部分-->
|
|
|
- <el-form ref="elSearchFormRef" class="demo-form-inline" :rules="searchRule" >
|
|
|
- <!-- <el-form-item>
|
|
|
- <el-input v-model="searchInfo" placeholder="搜索工单编号" clearable style="width: 200px;margin: 5px"></el-input>
|
|
|
- <el-button type="primary" class="bt" icon="download" @click="hzToExcel" >导出到Excel(汇总)</el-button>
|
|
|
- <el-button type="primary" class="bt" icon="download" @click="mxToExcel" >导出到Excel(明细)</el-button>
|
|
|
- </el-form-item> -->
|
|
|
- <h3>页面正在建设中</h3>
|
|
|
- </el-form>
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- </div>
|
|
|
- </layout-header>
|
|
|
-
|
|
|
- <layout>
|
|
|
- <!-- 左侧树侧形结构-->
|
|
|
- <!-- <layout-sider :resize-directions="['right']" :width="190" style="margin-right: 10px;">
|
|
|
- <div class="JKWTree-tree" style="height: 200px">
|
|
|
- <h3>生产进程查询</h3>
|
|
|
- <el-tree :data="treeData" :props="defaultProps" @node-click="handleNodeClick" @node-expand="handleNodeExpand">
|
|
|
- </el-tree>
|
|
|
- </div>
|
|
|
- </layout-sider>
|
|
|
- -->
|
|
|
- <!-- 右侧区域 -->
|
|
|
- <layout-content >
|
|
|
- <!-- <el-main>
|
|
|
- <div class="gva-table-box">
|
|
|
- <el-table ref="multipleTable" style="width: 100%;height: 33vh" tooltip-effect="dark"
|
|
|
- :row-style="{ height: '25px' }" :header-cell-style="{ padding: '0px' }"
|
|
|
- :cell-style="{ padding: '0px' }" :header-row-style="{ height: '20px' }"
|
|
|
- :data="hztableData" border row-key="ID"
|
|
|
- size="small"
|
|
|
- :cell-class-name="gxbgCellClass"
|
|
|
- highlight-current-row="true" @row-dblclick="updateCompanyFunc"
|
|
|
- @row-click="tableRowClick" :show-overflow-tooltip="true"
|
|
|
- @selection-change="handleSelectionChange">
|
|
|
- <el-table-column sortable align="center" label="设备编号" prop="工单编号" width="120" />
|
|
|
- <el-table-column sortable align="center" label="设备名称" prop="印件代号" width="120" />
|
|
|
- <el-table-column align="center" label="上月末主电表读数" prop="印件名称" width="200" />
|
|
|
- <el-table-column align="center" label="本月末主电表读数" prop="联数" width="200" />
|
|
|
- <el-table-column align="center" label="主电表耗电量" prop="投料大箱" width="110" />
|
|
|
- <el-table-column align="center" label="上月末辅电表读数" prop="计划投料" width="200" />
|
|
|
- <el-table-column align="center" label="本月末本电表读数" prop="工序1" width="200" />
|
|
|
- <el-table-column align="center" label="辅电表耗电量" prop="工序2" width="110" />
|
|
|
- </el-table>
|
|
|
-
|
|
|
- <div class="gva-pagination">
|
|
|
- <el-pagination layout="total" :current-page="page" :page-size="pageSize"
|
|
|
- :total="total" @current-change="handleCurrentChange" @size-change="handleSizeChange" />
|
|
|
- </div>
|
|
|
- </div>
|
|
|
-
|
|
|
-
|
|
|
- <div class="gva-table-box">
|
|
|
- <el-table ref="multipleTable" style="width: 100%;height: 45vh" tooltip-effect="dark"
|
|
|
- :row-style="{ height: '25px' }" :header-cell-style="{ padding: '0px' }"
|
|
|
- :cell-style="{ padding: '0px' }" :header-row-style="{ height: '20px' }"
|
|
|
- :data="mxtableData" border row-key="ID"
|
|
|
- size="small"
|
|
|
- :cell-class-name="gxbgCellClass"
|
|
|
- highlight-current-row="true" @row-dblclick="updateCompanyFunc"
|
|
|
- @row-click="tableRowClick" :show-overflow-tooltip="true"
|
|
|
- @selection-change="handleSelectionChange">
|
|
|
- <el-table-column sortable align="center" label="机台编号" prop="机台编号" width="120" />
|
|
|
- <el-table-column sortable align="center" label="开工时间" prop="开工时间" width="120" />
|
|
|
- <el-table-column sortable align="center" label="主电表" prop="主电表" width="200" />
|
|
|
- <el-table-column sortable align="center" label="辅电表" prop="辅电表" width="100" />
|
|
|
- </el-table>
|
|
|
-
|
|
|
- <div class="gva-pagination">
|
|
|
- <el-pagination layout="total" :current-page="page" :page-size="pageSize"
|
|
|
- :total="total" @current-change="handleCurrentChange" @size-change="handleSizeChange" />
|
|
|
- </div>
|
|
|
- </div>
|
|
|
-
|
|
|
- </el-main> -->
|
|
|
- </layout-content>
|
|
|
- </layout>
|
|
|
- </layout>
|
|
|
- </div>
|
|
|
- </template>
|
|
|
- <script setup>
|
|
|
- // 全量引入格式化工具 请按需保留
|
|
|
- import { Layout, LayoutSider, LayoutContent } from '@arco-design/web-vue';
|
|
|
-
|
|
|
- import {ref, reactive} from 'vue'
|
|
|
- import { exportExcelFile } from '@/utils/excel'
|
|
|
- import {ElMessage} from "element-plus";
|
|
|
- defineOptions({name: 'Company'})
|
|
|
- // =========== 获取左侧树侧形结构 ===========
|
|
|
-
|
|
|
+ <div class="page-container">
|
|
|
+ <el-descriptions title="" :column="1" border>
|
|
|
+ <el-descriptions-item label="图片上传">
|
|
|
+ <div class="upload-container">
|
|
|
+ <el-upload
|
|
|
+ ref="uploadRef"
|
|
|
+ class="upload-list"
|
|
|
+ :action="uploadUrl"
|
|
|
+ :http-request="customUpload"
|
|
|
+ :headers="uploadHeaders"
|
|
|
+ list-type="picture-card"
|
|
|
+ :on-preview="handlePreview"
|
|
|
+ :on-remove="handleRemove"
|
|
|
+ :on-change="handleChange"
|
|
|
+ :before-upload="beforeUpload"
|
|
|
+ :on-success="handleSuccess"
|
|
|
+ :on-error="handleError"
|
|
|
+ :on-exceed="handleExceed"
|
|
|
+ :limit="30"
|
|
|
+ :multiple="true"
|
|
|
+ accept="image/jpeg,image/png">
|
|
|
+ <el-icon><Plus /></el-icon>
|
|
|
+ <template #tip>
|
|
|
+ <div class="el-upload__tip">
|
|
|
+ 只能上传 <b>jpg/png</b> 文件,且 <b>不超过30张</b>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ <template #file="{ file }">
|
|
|
+ </template>
|
|
|
+ </el-upload>
|
|
|
+ </div>
|
|
|
+ </el-descriptions-item>
|
|
|
+ </el-descriptions>
|
|
|
+
|
|
|
+ <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-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-dialog
|
|
|
+ v-model="queueDialogVisible"
|
|
|
+ :before-close="queueDialog"
|
|
|
+ title="队列任务详情"
|
|
|
+ width="700px"
|
|
|
+ destroy-on-close
|
|
|
+ >
|
|
|
+ <div class="dialog-scroll-wrapper">
|
|
|
+ <template v-if="queueData.tasks_preview && queueData.tasks_preview.length">
|
|
|
+ <el-card
|
|
|
+ v-for="(task, index) in queueData.tasks_preview"
|
|
|
+ :key="task.id"
|
|
|
+ class="task-card"
|
|
|
+ >
|
|
|
+ <div class="task-grid">
|
|
|
+ <div><strong>任务 ID:</strong>{{ task.id }}</div>
|
|
|
+ <div><strong>尝试次数:</strong>{{ task.attempts }}</div>
|
|
|
+
|
|
|
+ <div>
|
|
|
+ <strong>状态:</strong>
|
|
|
+ <el-tag :type="index === 0 ? 'success' : 'warning'">
|
|
|
+ {{ index === 0 ? '处理中' : '待处理' }}
|
|
|
+ </el-tag>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="task-image">
|
|
|
+ <el-image
|
|
|
+ style="width: 120px; height: 120px; border: 1px solid #ccc"
|
|
|
+ :src="formatImageUrl(task.data.sourceDir + '/' + task.data.file_name)"
|
|
|
+ fit="cover"
|
|
|
+ :preview-src-list="[formatImageUrl(task.data.sourceDir + '/' + task.data.file_name)]"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </el-card>
|
|
|
+ </template>
|
|
|
+
|
|
|
+ <template v-else>
|
|
|
+ <div class="empty-queue">当前无任务在队列中。</div>
|
|
|
+ </template>
|
|
|
+ </div>
|
|
|
+ </el-dialog>
|
|
|
+
|
|
|
+
|
|
|
+ <br>
|
|
|
+ <el-table :data="tableData" border height="450" highlight-current-row="true" v-loading="loading">
|
|
|
+ <el-table-column prop="id" label="ID" width="50" />
|
|
|
+ <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="80" />
|
|
|
+ <el-table-column prop="queueLog_model_name" label="执行状态" width="100" />
|
|
|
+ <el-table-column align="center" label="操作" width="230">
|
|
|
+ <template #default="{ row, $index }" >
|
|
|
+ <el-button @click="record_deleteRow(row,$index)" type="primary" size="small"
|
|
|
+ style="font-size: 16px;padding: 0px;width: 80px;">
|
|
|
+ 查看详情
|
|
|
+ </el-button>
|
|
|
+ <el-button @click="packRow(row,$index)" type="primary" size="small"
|
|
|
+ style="font-size: 16px;padding: 0px;width: 100px;">
|
|
|
+ 打包压缩zip
|
|
|
+ </el-button>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ </el-table>
|
|
|
+
|
|
|
+
|
|
|
+ <el-dialog v-model="zipview" title="请选择打包尺寸" width="500px" top="20%">
|
|
|
+ <el-radio-group v-model="zipselectedOption" size="medium">
|
|
|
+ <el-radio label="1024x1024">1024 x 1024</el-radio>
|
|
|
+ <!-- <el-radio label="1024x1303">1024 x 1303</el-radio> -->
|
|
|
+ <el-radio label="图生图">图生图</el-radio>
|
|
|
+ <el-radio label="高清放大">高清放大</el-radio>
|
|
|
+ </el-radio-group>
|
|
|
+ <template #footer>
|
|
|
+ <div style="text-align: right">
|
|
|
+ <el-button @click="zipview = false">取消</el-button>
|
|
|
+ <el-button type="primary" @click="confirmPack">确认打包</el-button>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ </el-dialog>
|
|
|
+
|
|
|
+
|
|
|
+ <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;">
|
|
|
+ <template v-if="path_image_url">
|
|
|
+ <el-image
|
|
|
+ :src="formatImageUrl(path_image_url)"
|
|
|
+ fit="contain"
|
|
|
+ style="max-width: 100%; height: auto;"
|
|
|
+ :preview-src-list="[formatImageUrl(path_image_url)]"
|
|
|
+ :initial-index="0"
|
|
|
+ />
|
|
|
+
|
|
|
+ </template>
|
|
|
+ <template v-else>
|
|
|
+ <el-image
|
|
|
+ :src="`https://chatapi.onechats.ai/mj/image/${taskId_ids}`"
|
|
|
+ fit="contain"
|
|
|
+ style="max-width: 100%; height: auto;"
|
|
|
+ :preview-src-list="[`https://chatapi.onechats.ai/mj/image/${taskId_ids}`]"
|
|
|
+ :initial-index="0"
|
|
|
+ />
|
|
|
+ </template>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- <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(path_image_url)"
|
|
|
+ fit="contain"
|
|
|
+ style="max-width: 100%; height: auto;"
|
|
|
+ :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;">
|
|
|
+ <div v-html="activeDescription"></div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <el-descriptions title="" :column="1" border>
|
|
|
+ <el-descriptions-item v-if="img_id" label="ID">
|
|
|
+ <span>{{ img_id }}</span>
|
|
|
+ </el-descriptions-item>
|
|
|
+
|
|
|
+ <el-descriptions-item v-if="img_id" label="模型">
|
|
|
+ <span>{{ model }}</span>
|
|
|
+ </el-descriptions-item>
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ <template v-if="path_image_url">
|
|
|
+ <el-descriptions-item label="图片路径" width="50">
|
|
|
+ <span>{{ path_image_url }}</span>
|
|
|
+ </el-descriptions-item>
|
|
|
+ </template>
|
|
|
+ <template v-else>
|
|
|
+ <el-descriptions-item label="图片路径" width="50">
|
|
|
+ <span>https://chatapi.onechats.ai/mj/image/{{taskId_ids}}</span>
|
|
|
+ </el-descriptions-item>
|
|
|
+ </template>
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ <template v-if="path_image_url">
|
|
|
+
|
|
|
+ </template>
|
|
|
+ <template v-else>
|
|
|
+ <el-descriptions-item label="模型主图ID" width="50">
|
|
|
+ <span>{{ taskId_ids }}</span>
|
|
|
+ <!-- <el-button type="primary" @click="image_seed('1')" style="margin-left: 60px;">获取图一</el-button>
|
|
|
+ <el-button type="primary" @click="image_seed('2')" style="margin-left: 10px;">获取图二</el-button>
|
|
|
+ <el-button type="primary" @click="image_seed('3')" style="margin-left: 10px;">获取图三</el-button>
|
|
|
+ <el-button type="primary" @click="image_seed('4')" style="margin-left: 10px;">获取图四</el-button> -->
|
|
|
+ </el-descriptions-item>
|
|
|
+ </template>
|
|
|
+
|
|
|
+ </el-descriptions>
|
|
|
+ </el-dialog>
|
|
|
+
|
|
|
+ <el-dialog
|
|
|
+ v-model="TaskqueueVisible"
|
|
|
+ :before-close="TaskqueueDialog"
|
|
|
+ title=""
|
|
|
+ width="95%"
|
|
|
+ top="4vh"
|
|
|
+ destroy-on-close
|
|
|
+ >
|
|
|
+ <el-table
|
|
|
+ :data="table_Taskqueue"
|
|
|
+ row-key="id"
|
|
|
+ border
|
|
|
+ style="width: 100%; height: 60vh;"
|
|
|
+ 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' }"
|
|
|
+ @selection-change="SelectionChange"
|
|
|
+ :show-overflow-tooltip="true"
|
|
|
+ >
|
|
|
+ <el-table-column type="selection" width="60" align="center" />
|
|
|
+ <el-table-column prop="id" label="任务ID" width="100" align="center" />
|
|
|
+ <el-table-column prop="task_id" label="子任务ID" width="100" align="center" />
|
|
|
+ <el-table-column prop="log" label="状态" width="160" align="center" />
|
|
|
+ </el-table>
|
|
|
+ </el-dialog>
|
|
|
+
|
|
|
+ <!-- 模版页面 -->
|
|
|
+ <el-dialog v-model="ListTemplate_Visible"
|
|
|
+ :before-close="ListTemplateDialog"
|
|
|
+ title="" width="90%"
|
|
|
+ style="height: 90%;margin: 2%;padding: 0px;"
|
|
|
+ top="2vh" destroy-on-close>
|
|
|
+ <div class="page-container">
|
|
|
+ <el-descriptions :column="2" border class="queue-status-box">
|
|
|
+ <!-- 模版选择器 -->
|
|
|
+ <el-descriptions-item label="选择" :span="2">
|
|
|
+ <el-row :gutter="10" align="middle">
|
|
|
+
|
|
|
+ <el-col :span="6">
|
|
|
+ <el-select v-model="selectedId" placeholder="请选择模版" @change="loadTemplateDetail">
|
|
|
+ <el-option
|
|
|
+ v-for="tpl in templateList"
|
|
|
+ :key="tpl.id"
|
|
|
+ :label="'模版 ' + tpl.id + (tpl.ids === 1 ? '(使用中)' : '')"
|
|
|
+ :value="tpl.id"
|
|
|
+ />
|
|
|
+ </el-select>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="3">
|
|
|
+ <el-button type="primary" @click="createNewTemplate">新增模版</el-button>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="4">
|
|
|
+ <el-button type="success" @click="onsetActive" :disabled="selectedId === usedId">设为当前使用模版</el-button>
|
|
|
+ </el-col>
|
|
|
+ </el-row>
|
|
|
+ </el-descriptions-item>
|
|
|
+
|
|
|
+ <!-- 图生文模版输入区域 -->
|
|
|
+ <el-descriptions-item label="图生文模版" :span="2">
|
|
|
+ <textarea
|
|
|
+ v-model="textareaContent"
|
|
|
+ placeholder="请输入提示词"
|
|
|
+ rows="10"
|
|
|
+ class="custom-textarea"
|
|
|
+ @keydown.tab.prevent="insertTab"
|
|
|
+ ></textarea>
|
|
|
+ </el-descriptions-item>
|
|
|
+
|
|
|
+ <!-- 文生文模版输入区域 -->
|
|
|
+ <el-descriptions-item label="文生文模版" :span="2">
|
|
|
+ <textarea
|
|
|
+ v-model="english_content"
|
|
|
+ placeholder="请输入提示词"
|
|
|
+ rows="10"
|
|
|
+ class="custom-textarea"
|
|
|
+ @keydown.tab.prevent="insertTab"
|
|
|
+ ></textarea>
|
|
|
+ </el-descriptions-item>
|
|
|
+
|
|
|
+ <!-- 出图尺寸输入区域 -->
|
|
|
+ <el-descriptions-item label="出图尺寸" :span="2">
|
|
|
+ <el-row :gutter="10" align="middle">
|
|
|
+ <el-col :span="4">
|
|
|
+ <el-input
|
|
|
+ v-model="width"
|
|
|
+ placeholder="宽度"
|
|
|
+ size="small"
|
|
|
+ type="number"
|
|
|
+ min="1"
|
|
|
+ />
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="1" style="text-align: center;">×</el-col>
|
|
|
+ <el-col :span="4">
|
|
|
+ <el-input
|
|
|
+ v-model="height"
|
|
|
+ placeholder="高度"
|
|
|
+ size="small"
|
|
|
+ type="number"
|
|
|
+ min="1"
|
|
|
+ />
|
|
|
+ </el-col>
|
|
|
+ </el-row>
|
|
|
+ </el-descriptions-item>
|
|
|
+
|
|
|
+ <!-- 操作按钮 -->
|
|
|
+ <el-descriptions-item label="操作" :span="2">
|
|
|
+ <el-button type="primary" @click="saveTemplate" :loading="mb_isLoading">
|
|
|
+ 保存模版
|
|
|
+ </el-button>
|
|
|
+ <el-button type="danger" title="" @click="ListTemplateDialog">关 闭</el-button>
|
|
|
+ </el-descriptions-item>
|
|
|
+ </el-descriptions>
|
|
|
+ </div>
|
|
|
+ </el-dialog>
|
|
|
+
|
|
|
+ <!-- 查看详情页面 -->
|
|
|
+ <el-dialog v-model="mlinventoryVisible"
|
|
|
+ :before-close="mlcloseDialog"
|
|
|
+ title="" width="100%"
|
|
|
+ style="height: 100%;margin: 0px;"
|
|
|
+ top="2vh" destroy-on-close>
|
|
|
+ <div class="dialog-body">
|
|
|
+
|
|
|
+ <!-- 左侧-->
|
|
|
+ <div class="dialog-left">
|
|
|
+ <el-form ref="elSearchFormRef" class="demo-form-inline">
|
|
|
+ <el-form-item>
|
|
|
+ <el-button type="danger" title="" @click="details_close">关 闭</el-button>
|
|
|
+ <el-button type="primary" title="" @click="Refresh_Status" :loading="isLoading">刷新执行状态</el-button>
|
|
|
+
|
|
|
+ <el-button type="primary" title="" @click="ListTemplate_model" :loading="isLoading">查看模版</el-button>
|
|
|
+
|
|
|
+ <span>选择状态:</span>
|
|
|
+ <el-select
|
|
|
+ v-model="filterStatus"
|
|
|
+ placeholder="全部"
|
|
|
+ @change="handleFilterChange"
|
|
|
+ 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-option label="未图生文" value="未图生文" />
|
|
|
+ <el-option label="未文生文" value="未文生文" />
|
|
|
+ <el-option label="未文生图" value="未文生图" />
|
|
|
+ <el-option label="未图生图" value="未图生图" />
|
|
|
+ </el-select>
|
|
|
+ </el-form-item>
|
|
|
+ </el-form>
|
|
|
+
|
|
|
+ <el-table
|
|
|
+ :data="tableData_lsit"
|
|
|
+ row-key="id"
|
|
|
+ border
|
|
|
+ style="width: 97%; height: 77vh;"
|
|
|
+ v-loading="loading"
|
|
|
+ highlight-current-row
|
|
|
+ tooltip-effect="dark"
|
|
|
+ :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="59" align="center" />
|
|
|
+ <el-table-column prop="ids" label="ID" width="70" align="center" />
|
|
|
+ <el-table-column label="状态" width="83" align="center">
|
|
|
+ <template #default="{ row }">
|
|
|
+ <el-tag v-if="row.status === 1" type="success">已出图</el-tag>
|
|
|
+ <el-tag v-else type="danger">未出图</el-tag>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column prop="status_name" label="操作" width="69" 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="120">
|
|
|
+ <template #default="{ row }">
|
|
|
+ <img
|
|
|
+ :src="formatImageUrl(row.path)"
|
|
|
+ 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">
|
|
|
+ <el-pagination
|
|
|
+ style="margin-right: 40px;"
|
|
|
+ @size-change="handleSizeChange"
|
|
|
+ @current-change="handleCurrentChange"
|
|
|
+ :current-page="page"
|
|
|
+ :page-sizes="[10, 30, 50, 100, 500,1000]"
|
|
|
+ :page-size="pageSize"
|
|
|
+ layout="total, sizes, prev, pager, next"
|
|
|
+ :total="total"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 右侧 -->
|
|
|
+ <div class="dialog-right">
|
|
|
+ <div class="dialog-right-scroll">
|
|
|
+ <el-card shadow="hover" body-style="padding: 0px;">
|
|
|
+ <el-form :model="mlformdata" label-position="top">
|
|
|
+ <el-descriptions column="1" border>
|
|
|
+
|
|
|
+ <el-descriptions-item label="操作">
|
|
|
+ <el-button type="primary" :loading="isLoading" title="选择图片,执行图生文" @click="imgtotext" >图生文</el-button>
|
|
|
+ <el-button type="primary" :loading="isLoading" title="选择图片,执行文生文" @click="texttotxt" >文生文</el-button>
|
|
|
+ <el-button type="primary" :loading="isLoading" title="选择图片,执行执行文生图" @click="texttoimg" >文生图</el-button>
|
|
|
+ <el-button type="primary" :loading="isLoading" title="选择图片,执行图生图" @click="imgtoimg" >图生图</el-button>
|
|
|
+ <el-button type="primary" :loading="isLoading" title="选择图片,执行图像高清放大处理" @click="singleimg" >图像高清放大处理</el-button>
|
|
|
+ <el-button type="primary" :loading="isLoading" title="选中图片,执行顺序:图生文->文生文->文生图->图生图->高清放大" @click="handleSelected" :disabled="isLoading">执选择任务</el-button>
|
|
|
+ <el-button type="primary" :loading="isLoading" title="执行当前所有图片,执行顺序:图生文->文生文->文生图->图生图->高清放大" @click="handleAll" >执行全部任务</el-button>
|
|
|
+ </el-descriptions-item>
|
|
|
+
|
|
|
+ <el-descriptions-item label="图生文模型">
|
|
|
+ <div style="display: flex; align-items: center; gap: 20px;">
|
|
|
+ <el-radio-group v-model="imgtotxtselectedModel" @change="handleModelChange">
|
|
|
+ <el-radio
|
|
|
+ v-for="item in imgtotxt_modelList"
|
|
|
+ :key="item.id"
|
|
|
+ :label="item.imgtotxt">
|
|
|
+ {{ item.imgtotxt }}
|
|
|
+ <span v-if="item.id === usedIds.tushengwen" style="color: #67C23A; margin-left: 5px;">(默认使用)</span>
|
|
|
+ </el-radio>
|
|
|
+ </el-radio-group>
|
|
|
+ </div>
|
|
|
+ <el-button type="success" @click="setActive('tushengwen')" :disabled="!selectedIds.tushengwen || selectedIds.tushengwen === usedIds.tushengwen">
|
|
|
+ 设为默认使用模型
|
|
|
+ </el-button>
|
|
|
+ </el-descriptions-item>
|
|
|
+
|
|
|
+ <el-descriptions-item label="文生文模型">
|
|
|
+ <div style="display: flex; align-items: center; gap: 20px;">
|
|
|
+ <el-radio-group v-model="txttotxtselectedModel" @change="handleModelChange">
|
|
|
+ <el-radio
|
|
|
+ v-for="item in txttotxt_modelList"
|
|
|
+ :key="item.id"
|
|
|
+ :label="item.txttotxt">
|
|
|
+ {{ item.txttotxt }}
|
|
|
+ <span v-if="item.id === usedIds.wenshengwen" style="color: #67C23A; margin-left: 5px;">(默认使用)</span>
|
|
|
+ </el-radio>
|
|
|
+ </el-radio-group>
|
|
|
+ </div>
|
|
|
+ <el-button type="success" @click="setActive('wenshengwen')" :disabled="!selectedIds.wenshengwen || selectedIds.wenshengwen === usedIds.wenshengwen">
|
|
|
+ 设为默认使用模型
|
|
|
+ </el-button>
|
|
|
+ </el-descriptions-item>
|
|
|
+
|
|
|
+ <el-descriptions-item label="文生图模型">
|
|
|
+ <div style="display: flex; align-items: center; gap: 20px;">
|
|
|
+ <el-radio-group v-model="txtimgselectedModel" @change="handleModelChange">
|
|
|
+ <el-radio
|
|
|
+ v-for="item in txttoimg_modelList"
|
|
|
+ :key="item.id"
|
|
|
+ :label="item.txttoimg">
|
|
|
+ {{ item.txttoimg }}
|
|
|
+ <span v-if="item.id === usedIds.wenshengtu" style="color: #67C23A; margin-left: 5px;">(默认使用)</span>
|
|
|
+ </el-radio>
|
|
|
+ </el-radio-group>
|
|
|
+ </div>
|
|
|
+ <el-button type="success" @click="setActive('wenshengtu')" :disabled="!selectedIds.wenshengtu || selectedIds.wenshengtu === usedIds.wenshengtu">
|
|
|
+ 设为默认使用模型
|
|
|
+ </el-button>
|
|
|
+ </el-descriptions-item>
|
|
|
+
|
|
|
+
|
|
|
+ <el-descriptions-item label="是否执行">
|
|
|
+ <el-checkbox v-model="executeKeywords">
|
|
|
+ 执行几何图
|
|
|
+ </el-checkbox>
|
|
|
+ </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;">
|
|
|
+ <template v-if="taskId_ids">
|
|
|
+ <div
|
|
|
+ class="image-item"
|
|
|
+ @click="showDescription('new',`https://chatapi.onechats.ai/mj/image/${taskId_ids}`)"
|
|
|
+ >
|
|
|
+ <el-image
|
|
|
+ :src="`https://chatapi.onechats.ai/mj/image/${taskId_ids}`"
|
|
|
+ fit="contain"
|
|
|
+ style="max-width: 100%; height: auto;"
|
|
|
+ :initial-index="0"
|
|
|
+ />
|
|
|
+ <span class="image-dimension">2048x2048</span>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ <template v-else>
|
|
|
+ <div class="image-grid">
|
|
|
+ <div
|
|
|
+ v-for="(img, index) in imageList"
|
|
|
+ :key="`image-item-${index}`"
|
|
|
+ class="image-item"
|
|
|
+ @click="showDescription(img, 'new')"
|
|
|
+ >
|
|
|
+ <img :src="formatImageUrl(img.new_image_url)"/>
|
|
|
+ <span class="image-dimension">1024x1024</span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="image-preview-wrap" style="margin-top: 16px; height: 167px;">
|
|
|
+ <div
|
|
|
+ v-for="(img, index) in imageList"
|
|
|
+ :key="'imgtoimg-' + index"
|
|
|
+ class="image-itemsimg"
|
|
|
+ @click="showDescription(img, 'san')"
|
|
|
+ >
|
|
|
+ <img :src="formatImageUrl(img.imgtoimg_url)" />图生图</div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="image-preview-wrap" style="margin-top: 16px; height: 140px;">
|
|
|
+ <div
|
|
|
+ v-for="(img, index) in imageList"
|
|
|
+ :key="'custom-' + index"
|
|
|
+ class="image-items"
|
|
|
+ @click="showDescription(img, 'custom')"
|
|
|
+ >
|
|
|
+ <img :src="formatImageUrl(img.custom_image_url)" />
|
|
|
+ 高清放大
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 右侧:文字描述区域 -->
|
|
|
+ <div
|
|
|
+ style="
|
|
|
+ width: 700px;
|
|
|
+ white-space: pre-wrap;
|
|
|
+ overflow-y: auto;
|
|
|
+ max-height: 60vh;
|
|
|
+ border: 1px solid #f0f0f0;
|
|
|
+ padding: 10px 80px 10px 10px;
|
|
|
+ "
|
|
|
+ >
|
|
|
+ <p>第一段(文生图 文字修改区)</p>
|
|
|
+ <el-input
|
|
|
+ type="textarea"
|
|
|
+ v-model="yi_activeDescription"
|
|
|
+ :rows="6"
|
|
|
+ />
|
|
|
+ <p>第二段(文生图 风格修改区)</p>
|
|
|
+ <el-input
|
|
|
+ type="textarea"
|
|
|
+ v-model="er_activeDescription"
|
|
|
+ :rows="6"
|
|
|
+ />
|
|
|
+ <p>图片名称</p>
|
|
|
+ <el-input
|
|
|
+ type="textarea"
|
|
|
+ v-model="name_activeDescription"
|
|
|
+ :rows="2"
|
|
|
+ />
|
|
|
+ <el-button type="primary" @click="submitEdit" style="margin-top: 20px;">修改</el-button>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </el-descriptions-item>
|
|
|
+
|
|
|
+
|
|
|
+ <el-descriptions-item label="出图尺寸">
|
|
|
+ <div style="display: flex; align-items: center; flex-wrap: wrap; gap: 12px;">
|
|
|
+ <el-input v-model="width" placeholder="宽度" size="small" style="width: 80px;" type="number" min="1" />
|
|
|
+ <span style="font-weight: bold;">×</span>
|
|
|
+ <el-input v-model="height" placeholder="高度" size="small" style="width: 80px;" type="number" min="1" />
|
|
|
+ </div>
|
|
|
+ </el-descriptions-item>
|
|
|
+
|
|
|
+ <!-- <el-descriptions-item label="执行次数">
|
|
|
+ <el-input-number v-model="num" :step="1" />
|
|
|
+ </el-descriptions-item> -->
|
|
|
+
|
|
|
+ <el-descriptions-item label="任务队列">
|
|
|
+ <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="50" />
|
|
|
+ <el-table-column prop="status" label="状态" width="100" />
|
|
|
+ <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>
|
|
|
+ </el-form>
|
|
|
+ </el-card>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+
|
|
|
+ </div>
|
|
|
+ </el-dialog>
|
|
|
+
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script setup>
|
|
|
+import {ref,reactive,toRaw} from 'vue'
|
|
|
+import {ElMessage, ElMessageBox,ElLoading } from 'element-plus'
|
|
|
+import axios from 'axios'
|
|
|
+import {Plus,Delete,CircleCheck,CircleClose} from '@element-plus/icons-vue'
|
|
|
+import {getPreviewSubDirs,queueStats,stopQueueProcesses, viewQueueStatus,ImgUpload,getPreviewimg,getlsit,
|
|
|
+imageToText,txttoimg_moxing,txttoimg_update,
|
|
|
+textToImage,Template_ids,sd_models,getSide,
|
|
|
+TemplateList,
|
|
|
+Template,
|
|
|
+updatetemplate,getPreviewFolders,
|
|
|
+setActiveTemplate,
|
|
|
+packImagess,getUploadPath,get_queue_logs,getTaskProgress
|
|
|
+} from '@/api/ai/aiimg'
|
|
|
+import { useUserStore } from '@/pinia/modules/user';
|
|
|
+
|
|
|
+//获取登录用户信息
|
|
|
+const userStore = useUserStore()
|
|
|
+const _username = ref('')
|
|
|
+_username.value = userStore.userInfo.userName + '/' + userStore.userInfo.nickName
|
|
|
+
|
|
|
+//获取服务器地址
|
|
|
+const formatImageUrl = (path) => {
|
|
|
+ if (!path) return ''
|
|
|
+ const base = 'http://20.0.16.53:9093'
|
|
|
+ return `${base}/${path.replace(/^public\//, '')}`
|
|
|
+}
|
|
|
+
|
|
|
+// --------------------- 图片上传 ---------------------
|
|
|
+const tableData = ref([])
|
|
|
+const getPreviewSubDirslist = async () => {
|
|
|
+ const res = await getPreviewSubDirs()
|
|
|
+ console.log('getPreviewSubDirs',res.data.data)
|
|
|
+ const processedData = res.data.data.map(item => {
|
|
|
+ return {
|
|
|
+ ...item,
|
|
|
+ new_image_url: `${item.new_image_url}${item.name}/`
|
|
|
+ };
|
|
|
+ });
|
|
|
+ tableData.value = processedData;
|
|
|
+ console.log(tableData.value)
|
|
|
+}
|
|
|
+getPreviewSubDirslist()
|
|
|
+
|
|
|
+// 环境配置
|
|
|
+const basePath = import.meta.env.VITE_BASE_PATH || 'http://20.0.16.53'
|
|
|
+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')
|
|
|
+}
|
|
|
+
|
|
|
+// 文件列表
|
|
|
+const fileList = ref([])
|
|
|
+const uploadRef = ref(null)
|
|
|
+
|
|
|
+// 获取本地文件URL
|
|
|
+const getObjectUrl = (file) => {
|
|
|
+ return URL.createObjectURL(file)
|
|
|
+}
|
|
|
+
|
|
|
+// 上传前校验
|
|
|
+const beforeUpload = (file) => {
|
|
|
+ const isImage = file.type === 'image/jpeg' || file.type === 'image/png'
|
|
|
+ const isLt5M = file.size / 1024 / 1024 < 5 // 限制5MB
|
|
|
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- </script>
|
|
|
-
|
|
|
- <style scoped>
|
|
|
- .form-container {
|
|
|
- display: flex;
|
|
|
- flex-wrap: wrap;
|
|
|
+ if (!isImage) {
|
|
|
+ ElMessage.error('只能上传 JPG/PNG 格式的图片!')
|
|
|
+ return false
|
|
|
}
|
|
|
|
|
|
- .form-column {
|
|
|
- /*flex: 1;*/
|
|
|
- margin-right: 15px; /* 调整列之间的间距 */
|
|
|
+ if (!isLt5M) {
|
|
|
+ ElMessage.error('图片大小不能超过 5MB!')
|
|
|
+ return false
|
|
|
}
|
|
|
|
|
|
- /* 左侧输入框宽度调整 */
|
|
|
- .form-column .el-form-item .el-input {
|
|
|
- width: 150px; /* 调整左侧输入框的宽度 */
|
|
|
- }
|
|
|
+ // 显示加载中
|
|
|
+ const loading = ElLoading.service({
|
|
|
+ lock: true,
|
|
|
+ text: '正在上传图片...',
|
|
|
+ background: 'rgba(0, 0, 0, 0.7)'
|
|
|
+ })
|
|
|
|
|
|
- :deep(.hui-plan-usage-lows div) {
|
|
|
- color: #8c939d !important;
|
|
|
- }
|
|
|
- :deep(.lan-plan-usage-lows div) {
|
|
|
- color: blue !important;
|
|
|
- font-weight: bold;
|
|
|
- }
|
|
|
+ // 将loading实例附加到file对象上,以便后续关闭
|
|
|
+ file.loadingInstance = loading
|
|
|
|
|
|
+ return true
|
|
|
+}
|
|
|
+
|
|
|
+// 自定义上传逻辑
|
|
|
+const customUpload = async (options) => {
|
|
|
+ const { file, onProgress, onSuccess, onError } = options
|
|
|
+ try {
|
|
|
+ const formData = new FormData()
|
|
|
+ formData.append('image', file)
|
|
|
+ const response = await axios.post(uploadUrl.value, formData, {
|
|
|
+ headers: uploadHeaders,
|
|
|
+ onUploadProgress: (progressEvent) => {
|
|
|
+ const percent = Math.round(
|
|
|
+ (progressEvent.loaded * 100) / progressEvent.total
|
|
|
+ )
|
|
|
+ onProgress({ percent }, file)
|
|
|
+ },
|
|
|
+ timeout: 60000 // 60秒超时
|
|
|
+ })
|
|
|
|
|
|
- /* 媒体查询,根据需要调整断点 */
|
|
|
- @media screen and (max-width: 768px) {
|
|
|
- .form-column {
|
|
|
- flex: 1 0 100%; /* 在小屏幕下变成单列布局 */
|
|
|
- margin-right: 0;
|
|
|
+ } catch (error) {
|
|
|
+
|
|
|
+ } finally {
|
|
|
+ // 关闭加载中
|
|
|
+ if (file.loadingInstance) {
|
|
|
+ file.loadingInstance.close()
|
|
|
}
|
|
|
}
|
|
|
- /*:deep(.el-table td .cell) {*/
|
|
|
- /* line-height: 30px !important;*/
|
|
|
- /*}*/
|
|
|
- .JKWTree-container {
|
|
|
- display: flex;
|
|
|
+}
|
|
|
+
|
|
|
+// 预览图片
|
|
|
+const handlePreview = (file) => {
|
|
|
+ if (file.url) {
|
|
|
+ window.open(file.url, '_blank')
|
|
|
+ } else if (file.raw) {
|
|
|
+ const url = getObjectUrl(file.raw)
|
|
|
+ window.open(url, '_blank')
|
|
|
+ URL.revokeObjectURL(url) // 释放内存
|
|
|
}
|
|
|
- .JKWTree-tree {
|
|
|
- /*width: 300px;*/
|
|
|
- background-color: #fff;
|
|
|
- padding: 10px;
|
|
|
- margin-right: 20px;
|
|
|
+}
|
|
|
+
|
|
|
+// 上传成功
|
|
|
+const handleSuccess = (response, file, fileList) => {
|
|
|
+ getPreviewSubDirslist()
|
|
|
+ file.loadingInstance?.close()
|
|
|
+}
|
|
|
+
|
|
|
+// 上传失败
|
|
|
+const handleError = (error, file, fileList) => {
|
|
|
+ console.error('上传错误:', error)
|
|
|
+ ElMessage.error(`${file.name} 上传失败`)
|
|
|
+ file.loadingInstance?.close()
|
|
|
+}
|
|
|
+
|
|
|
+// 超出限制
|
|
|
+const handleExceed = (files, fileList) => {
|
|
|
+ ElMessage.warning(`最多只能上传 30 张图片,您已选择 ${files.length} 张,共 ${files.length + fileList.length} 张`)
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+// --------------------- 查看队列任务 ---------------------
|
|
|
+const queuestats = ref({
|
|
|
+ 总任务数: 0,
|
|
|
+ 待处理: 0,
|
|
|
+ 处理中: 0,
|
|
|
+ 成功: 0,
|
|
|
+ 失败: 0
|
|
|
+})
|
|
|
+//队列状态
|
|
|
+const queueStats_list = async () => {
|
|
|
+ const res = await queueStats()
|
|
|
+ console.log(res)
|
|
|
+ if (res.code === 0) {
|
|
|
+ queuestats.value = res.data
|
|
|
+ }
|
|
|
+}
|
|
|
+queueStats_list()
|
|
|
+
|
|
|
+//停止处理
|
|
|
+const stopQueueLoading = ref(false)
|
|
|
+const stopQueueclick = async () => {
|
|
|
+ if (stopQueueLoading.value) return
|
|
|
+ try {
|
|
|
+ await ElMessageBox.confirm(
|
|
|
+ '确定要停止所有队列任务吗?',
|
|
|
+ '确认操作',
|
|
|
+ {
|
|
|
+ confirmButtonText: '清空队列',
|
|
|
+ cancelButtonText: '取消',
|
|
|
+ type: 'warning',
|
|
|
+ }
|
|
|
+ )
|
|
|
+ stopQueueLoading.value = true
|
|
|
+ const res = await stopQueueProcesses()
|
|
|
+ if (res.code === 0) {
|
|
|
+ ElMessage.success(res.msg || '已成功停止队列任务')
|
|
|
+ }
|
|
|
+ } catch (err) {
|
|
|
+ if (err !== 'cancel') {
|
|
|
+ ElMessage.error('操作失败,请稍后重试')
|
|
|
+ }
|
|
|
+ } finally {
|
|
|
+ stopQueueLoading.value = false
|
|
|
}
|
|
|
- .JKWTree-tree h3 {
|
|
|
- font-size: 15px;
|
|
|
- font-weight: 700;
|
|
|
- margin: 10px 0;
|
|
|
+}
|
|
|
+
|
|
|
+//任务列表
|
|
|
+const queueDialogVisible = ref(false)
|
|
|
+// 队列数据
|
|
|
+const queueData = ref({
|
|
|
+ tasks_preview: [],
|
|
|
+ count: 0
|
|
|
+})
|
|
|
+const QueueStatusisLoading = ref(false)
|
|
|
+// 任务列表按钮
|
|
|
+const handleViewQueue = async () => {
|
|
|
+ queueStats_list()
|
|
|
+ getPreviewSubDirslist()
|
|
|
+ QueueStatusisLoading.value = true
|
|
|
+ try {
|
|
|
+ const res = await viewQueueStatus()
|
|
|
+ if (res.code === 0) {
|
|
|
+ queueData.value = res
|
|
|
+ queueDialogVisible.value = true
|
|
|
+ } else {
|
|
|
+ ElMessage.error(res.msg || '查询失败')
|
|
|
+ }
|
|
|
+ } catch (err) {
|
|
|
+ ElMessage.error('请求异常')
|
|
|
+ } finally {
|
|
|
+ QueueStatusisLoading.value = false
|
|
|
}
|
|
|
- .JKWTree-content {
|
|
|
- flex: 1;
|
|
|
+}
|
|
|
+const queueDialog = async () => {
|
|
|
+ queueDialogVisible.value = false
|
|
|
+}
|
|
|
+
|
|
|
+// --------------------- 查看详情 ---------------------
|
|
|
+const fetchPreviewImages = async () => {
|
|
|
+ loading.value = true;
|
|
|
+ const params = {
|
|
|
+ sys_id:userStore.userInfo.nickName,
|
|
|
+ path: _resrow.value.old_image_url,
|
|
|
+ page: page.value,
|
|
|
+ limit: pageSize.value
|
|
|
+ };
|
|
|
+
|
|
|
+ if (filterStatus.value === '已出图') {
|
|
|
+ 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 = "未文生文"
|
|
|
+ }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 = "未图生图"
|
|
|
+ }else if(filterStatus.value === '高清放大') {
|
|
|
+ params.status_name = "高清放大"
|
|
|
}
|
|
|
+console.log("params",params)
|
|
|
+ // 获取分页数据
|
|
|
+ const res = await getPreviewimg(params);
|
|
|
+console.log("getPreviewimg",res.data.data)
|
|
|
+ if (res.data.code === 0) {
|
|
|
+ tableData_lsit.value = res.data.data;
|
|
|
+ total.value = res.data.total;
|
|
|
+ }
|
|
|
+ loading.value = false;
|
|
|
+};
|
|
|
+
|
|
|
+// 分页
|
|
|
+const page = ref(1)
|
|
|
+const total = ref(0)
|
|
|
+const pageSize = ref(50)
|
|
|
+// 页码变化
|
|
|
+const handleCurrentChange = (val) => {
|
|
|
+ page.value = val;
|
|
|
+ fetchPreviewImages();
|
|
|
+};
|
|
|
+
|
|
|
+// 每页数量变化
|
|
|
+const handleSizeChange = (val) => {
|
|
|
+ pageSize.value = val;
|
|
|
+ page.value = 1;
|
|
|
+ fetchPreviewImages();
|
|
|
+};
|
|
|
+
|
|
|
+//---------------选择框----------------
|
|
|
+const filterStatus = ref('全部')
|
|
|
+const handleFilterChange = () => {
|
|
|
+ // console.log('当前选择状态:', filterStatus.value);
|
|
|
+ page.value = 1;
|
|
|
+ fetchPreviewImages();
|
|
|
+};
|
|
|
+
|
|
|
+const mlinventoryVisible = ref(false)
|
|
|
+//关闭查看详情页面
|
|
|
+const details_close = async () => {
|
|
|
+ mlinventoryVisible.value = false;
|
|
|
+}
|
|
|
+
|
|
|
+const loading = ref(false)
|
|
|
+const width = ref('')
|
|
|
+const height = ref('')
|
|
|
+const mlformdata = ref({})
|
|
|
+const tableData_lsit = ref([])
|
|
|
+const _resrow = ref('')
|
|
|
+
|
|
|
+const TaskqueueVisible = ref(false)
|
|
|
+const table_queue = ref([])
|
|
|
+const table_Taskqueue = ref([])
|
|
|
+
|
|
|
+//SD模型
|
|
|
+const selectedModel = ref('Realistic_Vision_V5.0-inpainting.safetensors [cf5d9eb09b]')
|
|
|
+const modelList = ref([])
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+// 模型列表
|
|
|
+const txttoimg_modelList = ref([]);
|
|
|
+const txtimgselectedModel = ref('');
|
|
|
+const imgtotxt_modelList = ref([]);
|
|
|
+const imgtotxtselectedModel = ref('');
|
|
|
+const txttotxt_modelList = ref([]);
|
|
|
+const txttotxtselectedModel = ref('');
|
|
|
+
|
|
|
+// 当前使用和选择的ID
|
|
|
+const usedIds = ref({
|
|
|
+ wenshengwen: null,
|
|
|
+ tushengwen: null,
|
|
|
+ wenshengtu: null
|
|
|
+});
|
|
|
+
|
|
|
+const selectedIds = ref({
|
|
|
+ wenshengwen: null,
|
|
|
+ tushengwen: null,
|
|
|
+ wenshengtu: null
|
|
|
+});
|
|
|
+
|
|
|
+
|
|
|
+//查看详情按钮
|
|
|
+const record_deleteRow = async (row) => {
|
|
|
+ //打开弹窗
|
|
|
+ mlinventoryVisible.value = true;
|
|
|
+
|
|
|
+ //获取当前文件夹行信息
|
|
|
+ _resrow.value = row;
|
|
|
+
|
|
|
+ //清空信息保持数据最新
|
|
|
+ imageList.value = []
|
|
|
+ img_id.value = '';
|
|
|
+ model.value = '';
|
|
|
+ new_image_url.value = '';
|
|
|
+ imgtoimg_url.value = '';
|
|
|
+ path_image_url.value = '';
|
|
|
+ activeDescription.value = '';
|
|
|
+ yi_activeDescription.value = '';
|
|
|
+ er_activeDescription.value = '';
|
|
|
+ name_activeDescription.value = '';
|
|
|
+ taskId_ids.value = '';
|
|
|
+
|
|
|
+ // 获取 SD 模型列表
|
|
|
+ // const sd_models_list = await sd_models();
|
|
|
+ // modelList.value = sd_models_list.data
|
|
|
+
|
|
|
+ // 任务队列
|
|
|
+ const queue_logs = await get_queue_logs({ old_image_file: row['old_image_url'] });
|
|
|
+ table_queue.value = queue_logs.data.data;
|
|
|
+
|
|
|
+ //获取图出图自定义尺寸
|
|
|
+ const TemplateList_res = await TemplateList({path:row['old_image_url']})
|
|
|
+
|
|
|
+
|
|
|
+ const res = await Template_ids({path:row['old_image_url']});
|
|
|
+ height.value = res.data.data.height
|
|
|
+ width.value = res.data.data.width
|
|
|
+
|
|
|
+ // 获取模型列表
|
|
|
+ const response = await txttoimg_moxing();
|
|
|
+ // 设置模型列表
|
|
|
+ imgtotxt_modelList.value = response.data.data.models.tushengwen;
|
|
|
+ txttotxt_modelList.value = response.data.data.models.wenshengwen;
|
|
|
+ txttoimg_modelList.value = response.data.data.models.wenshengtu;
|
|
|
+
|
|
|
+ // 设置当前使用的ID
|
|
|
+ usedIds.value = response.data.data.used_ids;
|
|
|
|
|
|
+ // 设置默认选中的模型
|
|
|
+ if (txttoimg_modelList.value.length > 0) {
|
|
|
+ const defaultModel = txttoimg_modelList.value.find(item => item.id === usedIds.value.wenshengtu);
|
|
|
+ if (defaultModel) {
|
|
|
+ txtimgselectedModel.value = defaultModel.txttoimg;
|
|
|
+ selectedIds.value.wenshengtu = defaultModel.id;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (imgtotxt_modelList.value.length > 0) {
|
|
|
+ const defaultModel = imgtotxt_modelList.value.find(item => item.id === usedIds.value.tushengwen);
|
|
|
+ if (defaultModel) {
|
|
|
+ imgtotxtselectedModel.value = defaultModel.imgtotxt;
|
|
|
+ selectedIds.value.tushengwen = defaultModel.id;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (txttotxt_modelList.value.length > 0) {
|
|
|
+ const defaultModel = txttotxt_modelList.value.find(item => item.id === usedIds.value.wenshengwen);
|
|
|
+ if (defaultModel) {
|
|
|
+ txttotxtselectedModel.value = defaultModel.txttotxt;
|
|
|
+ selectedIds.value.wenshengwen = defaultModel.id;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ await fetchPreviewImages();
|
|
|
+}
|
|
|
+
|
|
|
+// 当选择模型变化时
|
|
|
+const handleModelChange = (modelName) => {
|
|
|
+ // 更新文生图模型选择
|
|
|
+ const txttoimg_model = txttoimg_modelList.value.find(item => item.txttoimg === modelName);
|
|
|
+ if (txttoimg_model) {
|
|
|
+ selectedIds.value.wenshengtu = txttoimg_model.id;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 更新图生文模型选择
|
|
|
+ const imgtotxt_model = imgtotxt_modelList.value.find(item => item.imgtotxt === modelName);
|
|
|
+ if (imgtotxt_model) {
|
|
|
+ selectedIds.value.tushengwen = imgtotxt_model.id;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 更新文生文模型选择
|
|
|
+ const txttotxt_model = txttotxt_modelList.value.find(item => item.txttotxt === modelName);
|
|
|
+ if (txttotxt_model) {
|
|
|
+ selectedIds.value.wenshengwen = txttotxt_model.id;
|
|
|
+ }
|
|
|
|
|
|
- /* 选中某行时的背景色 */
|
|
|
- :deep(.el-table__body tr.current-row) > td {
|
|
|
- background: #ff80ff !important;
|
|
|
- }
|
|
|
- </style>
|
|
|
- <style scoped>
|
|
|
- :deep(.el-table td .cell) {
|
|
|
- line-height: 20px !important;
|
|
|
+}
|
|
|
+//设置模型
|
|
|
+const setActive = async (type) => {
|
|
|
+ const id = selectedIds.value[type];
|
|
|
+ if (id) {
|
|
|
+ const result = await txttoimg_update({type:type,id: id});
|
|
|
+ if (result.code === 0) {
|
|
|
+ usedIds.value[type] = id;
|
|
|
+ ElMessage.success('设置成功');
|
|
|
+
|
|
|
+ // 重新加载模型列表以更新状态
|
|
|
+ const response = await txttoimg_moxing();
|
|
|
+ usedIds.value = response.data.used_ids;
|
|
|
+ } else {
|
|
|
+ ElMessage.error('设置失败');
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+const record_queueRow = async (row) => {
|
|
|
+ TaskqueueVisible.value = true;
|
|
|
+
|
|
|
+ console.log(row['id'])
|
|
|
+ const getTaskProgress_data = await getTaskProgress({ id: row['id'] });
|
|
|
+ table_Taskqueue.value = getTaskProgress_data.data.data;
|
|
|
+}
|
|
|
+
|
|
|
+const TaskqueueDialog = async (row) => {
|
|
|
+ TaskqueueVisible.value = false;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+const imageList = ref([]);
|
|
|
+const _oldrow = ref('');
|
|
|
+const old_path = ref('');
|
|
|
+const ids = ref('');
|
|
|
+//点击当前行
|
|
|
+const handleRowClick = async (row) => {
|
|
|
+ imgtoimg_url.value = ''
|
|
|
+ activeDescription.value = ''
|
|
|
+ yi_activeDescription.value = '';
|
|
|
+ er_activeDescription.value = '';
|
|
|
+ name_activeDescription.value = '';
|
|
|
+ // fetchPreviewImages();
|
|
|
+
|
|
|
+ console.log("当前行信息",row)
|
|
|
+
|
|
|
+ // 文本内容高亮处理
|
|
|
+ const zh = highlightKeywords(row['chinese_description'] || '');
|
|
|
+ const en = highlightKeywords(row['english_description'] || '');
|
|
|
+ const name = highlightKeywords(row['img_name'] || '');
|
|
|
+
|
|
|
+ activeDescription.value = `第一段:\n${zh}\n\n第二段:\n${en}\n\n第三段:\n${name}`;
|
|
|
+ yi_activeDescription.value = zh;
|
|
|
+ er_activeDescription.value = en;
|
|
|
+ name_activeDescription.value = name;
|
|
|
+
|
|
|
+ _oldrow.value = row
|
|
|
+ taskId_ids.value = row['taskId']
|
|
|
+ old_path.value = row['path']
|
|
|
+ ids.value = row['ids']
|
|
|
+
|
|
|
+ const res = await getlsit({sys_id:userStore.userInfo.nickName, path: row['path'] });
|
|
|
+ if (res.data === null) {
|
|
|
+ imageList.value = [];
|
|
|
+ } else {
|
|
|
+ imageList.value = res.data.map(item => ({
|
|
|
+ id: item.id,
|
|
|
+ taskId: item.taskId,
|
|
|
+ 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;
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+//关闭按钮
|
|
|
+const mlcloseDialog = () => {
|
|
|
+ mlinventoryVisible.value = false
|
|
|
+}
|
|
|
+
|
|
|
+const submitEdit = async () => {
|
|
|
+ const payload = {
|
|
|
+ id:ids.value,
|
|
|
+ chinese_description:yi_activeDescription.value,
|
|
|
+ english_description:er_activeDescription.value,
|
|
|
+ img_name:name_activeDescription.value
|
|
|
+ };
|
|
|
+ await getSide(payload);
|
|
|
+ ElMessage.success('修改成功');
|
|
|
+ Refresh_Status()
|
|
|
+};
|
|
|
+
|
|
|
+
|
|
|
+const ListTemplate_Visible = ref(false)
|
|
|
+// 模版状态数据
|
|
|
+const templateList = ref([])
|
|
|
+const selectedId = ref(null)
|
|
|
+const usedId = ref(null)
|
|
|
+
|
|
|
+const path_templateList = ref([])
|
|
|
+const path_selectedId = ref(null)
|
|
|
+
|
|
|
+// 模版内容
|
|
|
+const textareaContent = ref('')
|
|
|
+const english_content = ref('')
|
|
|
+// const height = ref('')
|
|
|
+// const width = ref('')
|
|
|
+const mb_isLoading = ref(false)
|
|
|
+
|
|
|
+const ListTemplate_model = async () => {
|
|
|
+ ListTemplate_Visible.value = true
|
|
|
+ console.log(_resrow.value['old_image_url'])
|
|
|
+ const res = await TemplateList({path:_resrow.value['old_image_url']})
|
|
|
+ console.log("TemplateList",res.data.data.list)
|
|
|
+ console.log("TemplateList",res.data.data.usedId)
|
|
|
+ templateList.value = res.data.data.list
|
|
|
+ usedId.value = res.data.data.usedId
|
|
|
+ selectedId.value = usedId.value
|
|
|
+ await loadTemplateDetail(selectedId.value)
|
|
|
+}
|
|
|
+//获取模版列表后将默认模版显示
|
|
|
+const loadTemplateDetail = async (id) => {
|
|
|
+ if(id){
|
|
|
+ const res = await Template({ id })
|
|
|
+ textareaContent.value = res.data.data.content
|
|
|
+ english_content.value = res.data.data.english_content
|
|
|
+ width.value = res.data.data.width
|
|
|
+ height.value = res.data.data.height
|
|
|
+ }
|
|
|
+}
|
|
|
+// 新增模版按钮
|
|
|
+const createNewTemplate = () => {
|
|
|
+ selectedId.value = null
|
|
|
+ textareaContent.value = '请输入新增模版内容'
|
|
|
+ english_content.value = '请输入新增模版内容'
|
|
|
+ width.value = '1303'
|
|
|
+ height.value = '1024'
|
|
|
+}
|
|
|
+
|
|
|
+// 保存模版(新增或更新)
|
|
|
+const saveTemplate = async () => {
|
|
|
+
|
|
|
+ if (!textareaContent.value || !width.value || !height.value) {
|
|
|
+ ElMessage.warning('请填写完整模版内容和尺寸')
|
|
|
+ return
|
|
|
}
|
|
|
- :deep(.el-tabs__header){
|
|
|
- margin-bottom: 0;
|
|
|
+
|
|
|
+ mb_isLoading.value = true
|
|
|
+ const res = await updatetemplate({
|
|
|
+ id: selectedId.value,
|
|
|
+ path:_resrow.value['old_image_url'],
|
|
|
+ textareaContent: textareaContent.value,
|
|
|
+ english_content: english_content.value,
|
|
|
+ width: width.value,
|
|
|
+ height: height.value
|
|
|
+ })
|
|
|
+ mb_isLoading.value = false
|
|
|
+
|
|
|
+ if (res.data.code === 0) {
|
|
|
+ ElMessage.success('模版保存成功')
|
|
|
+ loadTemplateList()
|
|
|
+ } else {
|
|
|
+ ElMessage.error('保存失败')
|
|
|
}
|
|
|
- .search{
|
|
|
- margin-left: 0px !important;
|
|
|
- margin-right: 10px !important;
|
|
|
+}
|
|
|
+
|
|
|
+// 设为当前模版
|
|
|
+const onsetActive = async () => {
|
|
|
+ const res = await setActiveTemplate({ id: selectedId.value,path:path_selectedId.value })
|
|
|
+ if (res.code === 0) {
|
|
|
+ ElMessage.success('已设为当前使用模版')
|
|
|
+ await loadTemplateList()
|
|
|
+ } else {
|
|
|
+ ElMessage.error('设置失败')
|
|
|
}
|
|
|
- .bt{
|
|
|
- margin-left: 2px !important;
|
|
|
- padding: 3px !important;
|
|
|
- font-size: 12px;
|
|
|
+}
|
|
|
+
|
|
|
+// tab 缩进逻辑
|
|
|
+const insertTab = (event) => {
|
|
|
+ const textarea = event.target
|
|
|
+ const start = textarea.selectionStart
|
|
|
+ const end = textarea.selectionEnd
|
|
|
+ const isShift = event.shiftKey
|
|
|
+ const value = textareaContent.value
|
|
|
+ const before = value.substring(0, start)
|
|
|
+ const selected = value.substring(start, end)
|
|
|
+ const after = value.substring(end)
|
|
|
+
|
|
|
+ if (selected.includes('\n')) {
|
|
|
+ const lines = selected.split('\n')
|
|
|
+ const newText = lines
|
|
|
+ .map(line => (isShift
|
|
|
+ ? (line.startsWith('\t') ? line.substring(1) : line.startsWith(' ') ? line.substring(4) : line)
|
|
|
+ : '\t' + line))
|
|
|
+ .join('\n')
|
|
|
+ textareaContent.value = before + newText + after
|
|
|
+ const offset = newText.length - selected.length
|
|
|
+ nextTick(() => {
|
|
|
+ textarea.selectionStart = start
|
|
|
+ textarea.selectionEnd = end + offset
|
|
|
+ })
|
|
|
+ } else {
|
|
|
+ if (isShift && value.substring(start - 1, start) === '\t') {
|
|
|
+ textareaContent.value = before.slice(0, -1) + selected + after
|
|
|
+ nextTick(() => {
|
|
|
+ textarea.selectionStart = textarea.selectionEnd = start - 1
|
|
|
+ })
|
|
|
+ } else {
|
|
|
+ textareaContent.value = before + '\t' + selected + after
|
|
|
+ nextTick(() => {
|
|
|
+ textarea.selectionStart = textarea.selectionEnd = start + 1
|
|
|
+ })
|
|
|
+ }
|
|
|
}
|
|
|
- .el-tabs__header{
|
|
|
- margin: 0px !important;
|
|
|
+
|
|
|
+ event.preventDefault()
|
|
|
+}
|
|
|
+//关闭按钮
|
|
|
+const ListTemplateDialog = () => {
|
|
|
+ ListTemplate_Visible.value = false
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+/**
|
|
|
+ * 点击图片查看显示
|
|
|
+*/
|
|
|
+const yi_activeDescription = ref('');
|
|
|
+const er_activeDescription = ref('');
|
|
|
+const name_activeDescription = ref('');
|
|
|
+const activeDescription = ref('');
|
|
|
+const path_image_url = ref('');
|
|
|
+const taskId_ids = ref('');
|
|
|
+const img_id = ref('');
|
|
|
+const model = ref('');
|
|
|
+const new_image_url = ref('');
|
|
|
+const imgtoimg_url = ref('');
|
|
|
+const showDescDialog = ref(false);
|
|
|
+// 高亮关键词为红色
|
|
|
+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,url) => {
|
|
|
+ showDescDialog.value = true;
|
|
|
+ console.log(img)
|
|
|
+ //刷新任务队列-保持实时查看
|
|
|
+ Refresh_Status()
|
|
|
+
|
|
|
+ // 公共字段初始化
|
|
|
+ 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 || '图片未生成';
|
|
|
+ taskId_ids.value = taskId_ids.value || '';
|
|
|
+
|
|
|
+ } 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 || '图片未生成';
|
|
|
+ // taskId_ids.value = '';
|
|
|
+
|
|
|
+ }else if (type === 'san') {
|
|
|
+
|
|
|
+ path_image_url.value = img.imgtoimg_url || '图片未生成';
|
|
|
+ imgtoimg_url.value = img.imgtoimg_url || '图片未生成';
|
|
|
+ activeDescription.value = '';
|
|
|
+ model.value = '';
|
|
|
+ // taskId_ids.value = '';
|
|
|
+
|
|
|
+ }else if (type === 'old') {
|
|
|
+
|
|
|
+ path_image_url.value = img.path || '暂无说明';
|
|
|
+ imgtoimg_url.value = '';
|
|
|
+ activeDescription.value = '';
|
|
|
+ // taskId_ids.value = '';
|
|
|
+
|
|
|
+ } else {
|
|
|
+ // console.log('无效的类型');
|
|
|
}
|
|
|
- .gva-table-box{
|
|
|
- padding: 0px !important;
|
|
|
+};
|
|
|
+
|
|
|
+const image_seed = async (label) => {
|
|
|
+ console.log(label);
|
|
|
+ console.log(ids.value);
|
|
|
+ console.log(taskId_ids.value);
|
|
|
+ console.log(old_path.value)
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+//复选框
|
|
|
+const _parh = ref('')
|
|
|
+const _queue_status = ref('')
|
|
|
+const SelectionChange = (rows) => {
|
|
|
+ _parh.value = rows.map(item => item.path);
|
|
|
+ _queue_status.value = rows.map(item => item.queue_status);
|
|
|
+};
|
|
|
+
|
|
|
+//查看详情右侧区域
|
|
|
+const isLoading = ref(false)
|
|
|
+//执行次数默认值
|
|
|
+const num = ref(1)
|
|
|
+
|
|
|
+//图生文模型(默认值)
|
|
|
+const imgtotxt_selectedOption = ref('gemini-2.5-flash-lite-preview-06-17')
|
|
|
+//文生文模型(默认值)
|
|
|
+const txttotxt_selectedOption = ref('gemini-2.0-flash')
|
|
|
+//文生图模型(默认值)
|
|
|
+const selectedOption = ref('')
|
|
|
+
|
|
|
+const executeKeywords = ref(false) // 默认未选择
|
|
|
+
|
|
|
+//刷新表格任务状态
|
|
|
+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 = async() => {
|
|
|
+ const isProcessing = _queue_status.value.some(
|
|
|
+ status => status.includes("处理中") || status.includes("队列中")
|
|
|
+ );
|
|
|
+
|
|
|
+ if (isProcessing) {
|
|
|
+ await ElMessageBox.confirm(
|
|
|
+ '部分数据正在处理中,请稍后再操作!?',
|
|
|
+ '文生图',
|
|
|
+ {
|
|
|
+ confirmButtonText: '确定',
|
|
|
+ cancelButtonText: '取消',
|
|
|
+ type: 'warning'
|
|
|
+ }
|
|
|
+ );
|
|
|
+ return; // 阻止继续执行
|
|
|
+ }
|
|
|
+
|
|
|
+ // 如果没有任务在执行,才允许调用
|
|
|
+ processImages(toRaw(_parh.value), '文生图');
|
|
|
+};
|
|
|
+//执行图生图
|
|
|
+const imgtoimg = () => {
|
|
|
+ processImages(toRaw(_parh.value),'图生图');
|
|
|
+};
|
|
|
+//执行高清放大
|
|
|
+const singleimg = () => {
|
|
|
+ processImages(toRaw(_parh.value),'高清放大');
|
|
|
+};
|
|
|
+//执行选择任务
|
|
|
+const handleSelected = () => {
|
|
|
+ processImages(toRaw(_parh.value),'');
|
|
|
+};
|
|
|
+//执行全部任务
|
|
|
+const allTableData = ref([]); // 全部数据缓存
|
|
|
+const handleAll = async () => {
|
|
|
+ try {
|
|
|
+ await ElMessageBox.confirm(
|
|
|
+ '确定要执行全部任务吗?',
|
|
|
+ '确认操作',
|
|
|
+ {
|
|
|
+ confirmButtonText: '确定',
|
|
|
+ cancelButtonText: '取消',
|
|
|
+ type: 'warning'
|
|
|
+ }
|
|
|
+ );
|
|
|
+
|
|
|
+ // 开始 loading
|
|
|
+ loading.value = true;
|
|
|
+
|
|
|
+ // 发起全量请求
|
|
|
+ const allParams = {
|
|
|
+ sys_id:userStore.userInfo.nickName,
|
|
|
+ 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;
|
|
|
+
|
|
|
+ // 只保留 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;
|
|
|
}
|
|
|
- .mab{
|
|
|
- margin-bottom: 5px;
|
|
|
+};
|
|
|
+
|
|
|
+
|
|
|
+//操作 统一执行操作按钮处理方法
|
|
|
+const processImages = async (files,type) => {
|
|
|
+ if (!Array.isArray(files) || files.length === 0) {
|
|
|
+ ElMessage.warning('请选择要处理的图片')
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ // console.log(imgtotxtselectedModel.value)
|
|
|
+ // console.log(txttotxtselectedModel.value)
|
|
|
+ // console.log(txtimgselectedModel.value)
|
|
|
+
|
|
|
+ //加载开启
|
|
|
+ isLoading.value = true
|
|
|
+
|
|
|
+ const failList = []
|
|
|
+ const payload = {
|
|
|
+ old_image_file:_resrow.value['old_image_url'],
|
|
|
+ type:type,
|
|
|
+ imgtotxt_selectedOption:imgtotxtselectedModel.value,
|
|
|
+ txttotxt_selectedOption:txttotxtselectedModel.value,
|
|
|
+ selectedOption:txtimgselectedModel.value,
|
|
|
+ batch:files,
|
|
|
+ num:num.value,
|
|
|
+ width: width.value,
|
|
|
+ height: height.value,
|
|
|
+ executeKeywords:executeKeywords.value,
|
|
|
+ sys_id:userStore.userInfo.nickName
|
|
|
+ }
|
|
|
+
|
|
|
+ // 打印调试区域
|
|
|
+ // console.log(payload);
|
|
|
+ // await new Promise(resolve => setTimeout(resolve, 2000));
|
|
|
+ // isLoading.value = false;
|
|
|
+ // return;
|
|
|
+
|
|
|
+ //提交
|
|
|
+ try {
|
|
|
+ const res = await imageToText(payload)
|
|
|
+ } catch (e) {
|
|
|
+ failList.push(`第 ${batchStart + i + 1} 张 第 ${j + 1} 次`)
|
|
|
+ }
|
|
|
+ ElMessage.success(`共处理 ${files.length} 张 * ${num.value} 次,共 ${files.length * num.value} 次`)
|
|
|
+ if (failList.length > 0) {
|
|
|
+ console.warn('失败列表:', failList)
|
|
|
+ }
|
|
|
+
|
|
|
+ // 延迟2秒再关闭loading
|
|
|
+ await new Promise(resolve => setTimeout(resolve, 3000));
|
|
|
+ isLoading.value = false;
|
|
|
+
|
|
|
+ //刷新执行状态
|
|
|
+ Refresh_Status()
|
|
|
+
|
|
|
+ //任务队列刷新
|
|
|
+ const queue_logs = await get_queue_logs({ old_image_file: _resrow.value['old_image_url'] });
|
|
|
+ table_queue.value = queue_logs.data;
|
|
|
+
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+// --------------------- 打包zip ---------------------
|
|
|
+const zipview = ref(false)
|
|
|
+const ziprow = ref('')
|
|
|
+const zipselectedOption = ref('图生图') // 默认选中
|
|
|
+//点击打包按钮
|
|
|
+const packRow = async (row) => {
|
|
|
+ zipview.value = true;
|
|
|
+
|
|
|
+ ziprow.value = row
|
|
|
+}
|
|
|
+
|
|
|
+//确定按钮
|
|
|
+const confirmPack = async () => {
|
|
|
+ isLoading.value = true;
|
|
|
+ // console.log(zipselectedOption.value)
|
|
|
+ // return;
|
|
|
+ try {
|
|
|
+ const res = await getPreviewimg({
|
|
|
+ sys_id:userStore.userInfo.nickName,
|
|
|
+ path: ziprow.value.old_image_url,
|
|
|
+ page: 1,
|
|
|
+ limit: 10000
|
|
|
+ });
|
|
|
+
|
|
|
+ if (res.code !== 0 || !res.data || res.data.length === 0) {
|
|
|
+ ElMessage.warning('未找到出图记录');
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 根据选择的选项筛选对应的图片路径
|
|
|
+ const imagePaths = res.data.flatMap(item => {
|
|
|
+ const paths = [];
|
|
|
+
|
|
|
+ switch(zipselectedOption.value) {
|
|
|
+ case '1024x1024':
|
|
|
+ if (item.new_image_url?.trim()) {
|
|
|
+ paths.push({ type: 'new_image_url', path: item.new_image_url });
|
|
|
+ }
|
|
|
+ break;
|
|
|
+
|
|
|
+ // case '1024x1303':
|
|
|
+ // if (item.imgtoimg_url?.trim()) {
|
|
|
+ // paths.push({ type: 'imgtoimg_url', path: item.imgtoimg_url });
|
|
|
+ // }
|
|
|
+ // break;
|
|
|
+
|
|
|
+ case '高清放大':
|
|
|
+ if (item.custom_image_url?.trim()) {
|
|
|
+ paths.push({ type: 'custom_image_url', path: item.custom_image_url });
|
|
|
+ }
|
|
|
+ break;
|
|
|
+
|
|
|
+ case '图生图':
|
|
|
+ // 如果图生图需要多个字段,可以在这里添加
|
|
|
+ if (item.imgtoimg_url?.trim()) {
|
|
|
+ paths.push({ type: 'imgtoimg_url', path: item.imgtoimg_url });
|
|
|
+ }
|
|
|
+ // 可以根据需要添加其他字段
|
|
|
+ break;
|
|
|
+
|
|
|
+ default:
|
|
|
+ // 默认情况下,可以保留原来的逻辑或添加其他处理
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ return paths;
|
|
|
+ });
|
|
|
+
|
|
|
+ if (imagePaths.length === 0) {
|
|
|
+ ElMessage.warning(`没有找到${zipselectedOption.value}尺寸的图片`);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+// console.log(imagePaths)
|
|
|
+// return;
|
|
|
+ const packRes = await packImagess({ paths: imagePaths });
|
|
|
+
|
|
|
+ if (packRes.code === 0 && packRes.download_url) {
|
|
|
+ ElMessage.success('打包成功,正在下载...');
|
|
|
+
|
|
|
+ // ✅ 替换为服务的真实 IP 和端口
|
|
|
+ const basePath = import.meta.env.VITE_BASE_PATH || 'http://20.0.16.53';
|
|
|
+ const uploadsPort = import.meta.env.VITE_UPLOADS_PORT || '9093';
|
|
|
+
|
|
|
+ let url = packRes.download_url;
|
|
|
+
|
|
|
+ try {
|
|
|
+ const parsedUrl = new URL(url);
|
|
|
+ if (parsedUrl.hostname === '127.0.0.1' || parsedUrl.hostname === 'localhost') {
|
|
|
+ parsedUrl.hostname = new URL(basePath).hostname;
|
|
|
+ parsedUrl.port = uploadsPort;
|
|
|
+ url = parsedUrl.toString();
|
|
|
+ }
|
|
|
+ } catch (e) {
|
|
|
+ console.error('URL 解析失败:', e);
|
|
|
+ }
|
|
|
+
|
|
|
+ const link = document.createElement('a');
|
|
|
+ link.href = url;
|
|
|
+ link.setAttribute('download', '');
|
|
|
+ document.body.appendChild(link);
|
|
|
+ link.click();
|
|
|
+ document.body.removeChild(link);
|
|
|
+ } else {
|
|
|
+ ElMessage.error(`打包失败:${packRes.msg || '未知错误'}`);
|
|
|
+ }
|
|
|
+ } catch (err) {
|
|
|
+ ElMessage.error('打包请求异常');
|
|
|
+ console.error(err);
|
|
|
+ } finally {
|
|
|
+ isLoading.value = false;
|
|
|
+ zipview.value = false; // 关闭对话框
|
|
|
}
|
|
|
- </style>
|
|
|
-
|
|
|
+};
|
|
|
+
|
|
|
+</script>
|
|
|
+<style scoped>
|
|
|
+.page-container {
|
|
|
+ padding: 20px;
|
|
|
+ background: #fff;
|
|
|
+}
|
|
|
+
|
|
|
+.input-container {
|
|
|
+ margin-bottom: 20px;
|
|
|
+}
|
|
|
+
|
|
|
+.gva-table-box {
|
|
|
+ padding-bottom: 20px;
|
|
|
+}
|
|
|
+
|
|
|
+.table-container {
|
|
|
+ margin-top: 20px;
|
|
|
+}
|
|
|
+
|
|
|
+/* 表格行高细节调整 */
|
|
|
+:deep(.el-table td .cell) {
|
|
|
+ line-height: 20px !important;
|
|
|
+}
|
|
|
+
|
|
|
+:deep(.el-tabs__header) {
|
|
|
+ margin-bottom: 0;
|
|
|
+}
|
|
|
+
|
|
|
+/* 选中高亮 */
|
|
|
+:deep(.el-table__body tr.current-row) > td {
|
|
|
+ background: #ff80ff !important;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+/* 新增上传区域样式 */
|
|
|
+.upload-container {
|
|
|
+ margin: 20px 0;
|
|
|
+ padding: 20px;
|
|
|
+ border: 1px dashed #dcdfe6;
|
|
|
+ border-radius: 4px;
|
|
|
+ background-color: #f5f7fa;
|
|
|
+}
|
|
|
+
|
|
|
+.upload-list {
|
|
|
+ display: flex;
|
|
|
+ flex-wrap: wrap;
|
|
|
+ gap: 10px;
|
|
|
+}
|
|
|
+
|
|
|
+.upload-item {
|
|
|
+ position: relative;
|
|
|
+ width: 100px;
|
|
|
+ height: 100px;
|
|
|
+ border-radius: 4px;
|
|
|
+ overflow: hidden;
|
|
|
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
|
|
|
+}
|
|
|
+
|
|
|
+.upload-item-thumbnail {
|
|
|
+ width: 100%;
|
|
|
+ height: 100%;
|
|
|
+ object-fit: cover;
|
|
|
+}
|
|
|
+/* 修改上传卡片容器 */
|
|
|
+:deep(.el-upload--picture-card) {
|
|
|
+ --el-upload-picture-card-size: 100px;
|
|
|
+}
|
|
|
+
|
|
|
+:deep(.el-upload-list--picture-card) {
|
|
|
+ --el-upload-list-picture-card-size: 100px;
|
|
|
+}
|
|
|
+
|
|
|
+.upload-item-actions {
|
|
|
+ position: absolute;
|
|
|
+ bottom: 0;
|
|
|
+ left: 0;
|
|
|
+ right: 0;
|
|
|
+ padding: 8px;
|
|
|
+ background: rgba(0, 0, 0, 0.6);
|
|
|
+ color: white;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: space-between;
|
|
|
+}
|
|
|
+
|
|
|
+.upload-item-name {
|
|
|
+ flex: 1;
|
|
|
+ font-size: 12px;
|
|
|
+ white-space: nowrap;
|
|
|
+ overflow: hidden;
|
|
|
+ text-overflow: ellipsis;
|
|
|
+ margin-right: 8px;
|
|
|
+}
|
|
|
+
|
|
|
+.upload-progress {
|
|
|
+ font-size: 12px;
|
|
|
+ color: #409eff;
|
|
|
+}
|
|
|
+
|
|
|
+.upload-item-status {
|
|
|
+ margin: 0 8px;
|
|
|
+}
|
|
|
+
|
|
|
+.success-icon {
|
|
|
+ color: #67c23a;
|
|
|
+}
|
|
|
+
|
|
|
+.error-icon {
|
|
|
+ color: #f56c6c;
|
|
|
+}
|
|
|
+
|
|
|
+.upload-item-delete {
|
|
|
+ cursor: pointer;
|
|
|
+ color: #f56c6c;
|
|
|
+}
|
|
|
+
|
|
|
+.upload-item-delete:hover {
|
|
|
+ color: #ff0000;
|
|
|
+}
|
|
|
+
|
|
|
+:deep(.desc-overlay) {
|
|
|
+ position: absolute;
|
|
|
+ top: 0;
|
|
|
+ left: 0;
|
|
|
+ width: 120px;
|
|
|
+ height: 120px;
|
|
|
+ background: rgba(0, 0, 0, 0.75);
|
|
|
+ color: #fff;
|
|
|
+ font-size: 12px;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ padding: 8px;
|
|
|
+ box-sizing: border-box;
|
|
|
+ border-radius: 8px;
|
|
|
+ text-align: center;
|
|
|
+ word-break: break-word;
|
|
|
+ line-height: 1.4;
|
|
|
+ z-index: 10;
|
|
|
+}
|
|
|
+
|
|
|
+:deep(.fade-enter-active,
|
|
|
+.fade-leave-active) {
|
|
|
+ transition: opacity 0.3s;
|
|
|
+}
|
|
|
+:deep(.fade-enter-from,
|
|
|
+.fade-leave-to) {
|
|
|
+ opacity: 0;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+.dialog-scroll-wrapper {
|
|
|
+ max-height: 500px;
|
|
|
+ overflow-y: auto;
|
|
|
+ padding-right: 10px;
|
|
|
+}
|
|
|
+
|
|
|
+.task-card {
|
|
|
+ margin-bottom: 12px;
|
|
|
+}
|
|
|
+
|
|
|
+.task-grid {
|
|
|
+ display: grid;
|
|
|
+ grid-template-columns: 1fr;
|
|
|
+ row-gap: 6px;
|
|
|
+ font-size: 14px;
|
|
|
+ line-height: 1.6;
|
|
|
+}
|
|
|
+
|
|
|
+.task-prompt {
|
|
|
+ word-break: break-word;
|
|
|
+ white-space: pre-wrap;
|
|
|
+}
|
|
|
+
|
|
|
+.task-image {
|
|
|
+ margin-top: 8px;
|
|
|
+}
|
|
|
+.image-preview-overlay {
|
|
|
+ position: fixed;
|
|
|
+ top: 0;
|
|
|
+ left: 0;
|
|
|
+ right: 0;
|
|
|
+ bottom: 0;
|
|
|
+ background: rgba(0, 0, 0, 0.7);
|
|
|
+ display: flex;
|
|
|
+ justify-content: center;
|
|
|
+ align-items: center;
|
|
|
+ z-index: 9999;
|
|
|
+}
|
|
|
+
|
|
|
+.image-preview {
|
|
|
+ max-width: 90%;
|
|
|
+ max-height: 90%;
|
|
|
+ object-fit: contain;
|
|
|
+ cursor: pointer;
|
|
|
+}
|
|
|
+
|
|
|
+.dialog-body {
|
|
|
+ height: 93vh;
|
|
|
+ display: flex;
|
|
|
+ gap: 0px;
|
|
|
+ overflow: hidden;
|
|
|
+}
|
|
|
+
|
|
|
+/* 左侧表格区域 */
|
|
|
+.dialog-left {
|
|
|
+ flex: 1.4;
|
|
|
+ height: 100%;
|
|
|
+ overflow-y: auto;
|
|
|
+}
|
|
|
+
|
|
|
+/* 右侧详情区域 */
|
|
|
+.dialog-right {
|
|
|
+ flex: 2;
|
|
|
+ height: 100%;
|
|
|
+ overflow: hidden;
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+}
|
|
|
+
|
|
|
+.dialog-right-scroll {
|
|
|
+ flex: 1;
|
|
|
+ overflow-y: auto;
|
|
|
+ padding-right: 5px;
|
|
|
+}
|
|
|
+
|
|
|
+/* 按钮区域自动换行不拥挤 */
|
|
|
+.button-group {
|
|
|
+ display: flex;
|
|
|
+ flex-wrap: wrap;
|
|
|
+ gap: 10px;
|
|
|
+ margin-top: 5px;
|
|
|
+}
|
|
|
+
|
|
|
+/* 图片容器 */
|
|
|
+.image-preview-wrap {
|
|
|
+ display: flex;
|
|
|
+ flex-wrap: wrap;
|
|
|
+ gap: 16px;
|
|
|
+}
|
|
|
+.image-item {
|
|
|
+ position: relative;
|
|
|
+ text-align: center;
|
|
|
+ width: 110px;
|
|
|
+}
|
|
|
+.image-item img {
|
|
|
+ width: 120px;
|
|
|
+ height: 120px;
|
|
|
+ border: 1px solid #ccc;
|
|
|
+ object-fit: contain;
|
|
|
+}
|
|
|
+.image-item div {
|
|
|
+ margin-top: 4px;
|
|
|
+ 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: 118px;
|
|
|
+ height: 150px;
|
|
|
+ border: 1px solid #ccc;
|
|
|
+ object-fit: contain;
|
|
|
+}
|
|
|
+.image-itemsimg div {
|
|
|
+ margin-top: 4px;
|
|
|
+ font-size: 12px;
|
|
|
+ color: #666;
|
|
|
+}
|
|
|
+/* 模版样式 */
|
|
|
+.page-container {
|
|
|
+ padding: 20px;
|
|
|
+ background: #fff;
|
|
|
+}
|
|
|
+
|
|
|
+.custom-textarea {
|
|
|
+ width: 100%;
|
|
|
+ font-family: monospace;
|
|
|
+ font-size: 14px;
|
|
|
+ padding: 10px;
|
|
|
+ line-height: 1.6;
|
|
|
+ border: 1px solid #dcdfe6;
|
|
|
+ border-radius: 4px;
|
|
|
+ resize: vertical;
|
|
|
+ box-sizing: border-box;
|
|
|
+}
|
|
|
+
|
|
|
+:deep(.el-descriptions__body .el-descriptions__table.is-bordered .el-descriptions__cell) {
|
|
|
+ width: 100px;
|
|
|
+}
|
|
|
+</style>
|