|
@@ -1,2061 +0,0 @@
|
|
|
-<template>
|
|
|
|
|
- <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" 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,watch} from 'vue'
|
|
|
|
|
-import {ElMessage, ElMessageBox,ElLoading } from 'element-plus'
|
|
|
|
|
-import axios from 'axios'
|
|
|
|
|
-import {Plus,Delete,CircleCheck,CircleClose} from '@element-plus/icons-vue'
|
|
|
|
|
-import {stopQueueProcesses, queueStats, viewQueueStatus,ImgUpload,getPreviewSubDirs,getPreviewimg,getlsit,
|
|
|
|
|
-imageToText,txttoimg_moxing,txttoimg_update,
|
|
|
|
|
-textToImage,Template_ids,sd_models,getSide,
|
|
|
|
|
-TemplateList,
|
|
|
|
|
-Template,
|
|
|
|
|
-updatetemplate,getPreviewFolders,
|
|
|
|
|
-setActiveTemplate,GetHttpUrl,
|
|
|
|
|
-packImagess,getUploadPath,get_queue_logs,getTaskProgress
|
|
|
|
|
-} from '@/api/mes/job'
|
|
|
|
|
-import { useUserStore } from '@/pinia/modules/user';
|
|
|
|
|
-
|
|
|
|
|
-//获取登录用户信息
|
|
|
|
|
-const userStore = useUserStore()
|
|
|
|
|
-const _username = ref('')
|
|
|
|
|
-_username.value = userStore.userInfo.userName + '/' + userStore.userInfo.nickName
|
|
|
|
|
-console.log('获取用户信息',_username.value)
|
|
|
|
|
-console.log('获取用户名称',userStore.userInfo.nickName)
|
|
|
|
|
-
|
|
|
|
|
-//获取服务器地址
|
|
|
|
|
-const baseUrl = ref('')
|
|
|
|
|
-const port = ref('')
|
|
|
|
|
-const full_url = ref('')
|
|
|
|
|
-// 从接口获取服务器地址
|
|
|
|
|
-const fetchServerUrl = async () => {
|
|
|
|
|
- try {
|
|
|
|
|
- const res = await GetHttpUrl()
|
|
|
|
|
- if (res.code === 0 && res.data && res.data.full_url) {
|
|
|
|
|
- full_url.value = res.data.full_url
|
|
|
|
|
- baseUrl.value = res.data.baseUrl
|
|
|
|
|
- port.value = res.data.port
|
|
|
|
|
- console.log('获取服务器地址',full_url.value)
|
|
|
|
|
- console.log('IP地址',baseUrl.value)
|
|
|
|
|
- console.log('端口',port.value)
|
|
|
|
|
- }
|
|
|
|
|
- } catch (error) {
|
|
|
|
|
- console.error('获取服务器地址失败:', error)
|
|
|
|
|
- }
|
|
|
|
|
-}
|
|
|
|
|
-fetchServerUrl();
|
|
|
|
|
-
|
|
|
|
|
-const formatImageUrl = (path) => {
|
|
|
|
|
- if (!path) return ''
|
|
|
|
|
- // 如果path已经是完整URL,直接返回
|
|
|
|
|
- if (path.startsWith('http://') || path.startsWith('https://')) {
|
|
|
|
|
- return path
|
|
|
|
|
- }
|
|
|
|
|
- // 如果path是相对路径,拼接baseUrl
|
|
|
|
|
- return `${full_url.value}/${path.replace(/^public\//, '')}`
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
-// --------------------- 图片上传 ---------------------
|
|
|
|
|
-const tableData = ref([])
|
|
|
|
|
-const getPreviewSubDirslist = async () => {
|
|
|
|
|
- const res = await getPreviewSubDirs()
|
|
|
|
|
- console.log('getPreviewSubDirs',res)
|
|
|
|
|
- const processedData = res.data.map(item => {
|
|
|
|
|
- return {
|
|
|
|
|
- ...item,
|
|
|
|
|
- new_image_url: `${item.new_image_url}${item.name}/`
|
|
|
|
|
- };
|
|
|
|
|
- });
|
|
|
|
|
- tableData.value = processedData;
|
|
|
|
|
-}
|
|
|
|
|
-getPreviewSubDirslist()
|
|
|
|
|
-
|
|
|
|
|
-// 环境配置
|
|
|
|
|
-const uploadUrl = ref(`${full_url.value}/api/Facility/ImgUpload`)
|
|
|
|
|
-
|
|
|
|
|
-// 确保上传URL与服务器地址同步
|
|
|
|
|
-watch(full_url, (newUrl) => {
|
|
|
|
|
- uploadUrl.value = `${newUrl}/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
|
|
|
|
|
-
|
|
|
|
|
- if (!isImage) {
|
|
|
|
|
- ElMessage.error('只能上传 JPG/PNG 格式的图片!')
|
|
|
|
|
- return false
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- if (!isLt5M) {
|
|
|
|
|
- ElMessage.error('图片大小不能超过 5MB!')
|
|
|
|
|
- return false
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // 显示加载中
|
|
|
|
|
- const loading = ElLoading.service({
|
|
|
|
|
- lock: true,
|
|
|
|
|
- text: '正在上传图片...',
|
|
|
|
|
- background: 'rgba(0, 0, 0, 0.7)'
|
|
|
|
|
- })
|
|
|
|
|
-
|
|
|
|
|
- // 将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秒超时
|
|
|
|
|
- })
|
|
|
|
|
-
|
|
|
|
|
- } catch (error) {
|
|
|
|
|
-
|
|
|
|
|
- } finally {
|
|
|
|
|
- // 关闭加载中
|
|
|
|
|
- if (file.loadingInstance) {
|
|
|
|
|
- file.loadingInstance.close()
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-// 预览图片
|
|
|
|
|
-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) // 释放内存
|
|
|
|
|
- }
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-// 上传成功
|
|
|
|
|
-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
|
|
|
|
|
- }
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-//任务列表
|
|
|
|
|
-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
|
|
|
|
|
- }
|
|
|
|
|
-}
|
|
|
|
|
-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 = "高清放大"
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // 获取分页数据
|
|
|
|
|
- const res = await getPreviewimg(params);
|
|
|
|
|
-
|
|
|
|
|
- if (res.code === 0) {
|
|
|
|
|
- tableData_lsit.value = res.data;
|
|
|
|
|
- total.value = res.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;
|
|
|
|
|
-
|
|
|
|
|
- //获取图出图自定义尺寸
|
|
|
|
|
- const TemplateList_res = await TemplateList({path:row['old_image_url']})
|
|
|
|
|
-
|
|
|
|
|
- const res = await Template_ids({path:row['old_image_url']});
|
|
|
|
|
- height.value = res.data.height
|
|
|
|
|
- width.value = res.data.width
|
|
|
|
|
-
|
|
|
|
|
- // 获取模型列表
|
|
|
|
|
- const response = await txttoimg_moxing();
|
|
|
|
|
-
|
|
|
|
|
- // 设置模型列表
|
|
|
|
|
- imgtotxt_modelList.value = response.data.models.tushengwen;
|
|
|
|
|
- txttotxt_modelList.value = response.data.models.wenshengwen;
|
|
|
|
|
- txttoimg_modelList.value = response.data.models.wenshengtu;
|
|
|
|
|
-
|
|
|
|
|
- // 设置当前使用的ID
|
|
|
|
|
- usedIds.value = response.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;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
-}
|
|
|
|
|
-//设置模型
|
|
|
|
|
-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']})
|
|
|
|
|
- templateList.value = res.data.list || []
|
|
|
|
|
- usedId.value = res.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.content || ''
|
|
|
|
|
- english_content.value = res.data.english_content || ''
|
|
|
|
|
- width.value = res.data.width || ''
|
|
|
|
|
- height.value = res.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
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- 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.code === 0) {
|
|
|
|
|
- ElMessage.success('模版保存成功')
|
|
|
|
|
- loadTemplateList()
|
|
|
|
|
- } else {
|
|
|
|
|
- ElMessage.error('保存失败')
|
|
|
|
|
- }
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-// 设为当前模版
|
|
|
|
|
-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('设置失败')
|
|
|
|
|
- }
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-// 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
|
|
|
|
|
- })
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- 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('无效的类型');
|
|
|
|
|
- }
|
|
|
|
|
-};
|
|
|
|
|
-
|
|
|
|
|
-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;
|
|
|
|
|
- }
|
|
|
|
|
-};
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
-//操作 统一执行操作按钮处理方法
|
|
|
|
|
-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('打包成功,正在下载...');
|
|
|
|
|
- let url = packRes.download_url;
|
|
|
|
|
- try {
|
|
|
|
|
- const parsedUrl = new URL(url);
|
|
|
|
|
- if (parsedUrl.hostname === '127.0.0.1' || parsedUrl.hostname === 'localhost') {
|
|
|
|
|
- // 使用从接口获取的服务器地址
|
|
|
|
|
- const serverUrl = new URL(full_url.value);
|
|
|
|
|
- parsedUrl.hostname = serverUrl.hostname;
|
|
|
|
|
- parsedUrl.port = serverUrl.port;
|
|
|
|
|
- url = parsedUrl.toString();
|
|
|
|
|
- }
|
|
|
|
|
- console.log('修改前URL:', packRes.download_url);
|
|
|
|
|
- console.log('修改后URL:', url);
|
|
|
|
|
- console.log('使用的服务器地址:', full_url.value);
|
|
|
|
|
- } 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; // 关闭对话框
|
|
|
|
|
- }
|
|
|
|
|
-};
|
|
|
|
|
-
|
|
|
|
|
-</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>
|
|
|