From 54572b3c9db78d4374281087a8c66e5c3b3b6200 Mon Sep 17 00:00:00 2001 From: sd <shidong@jhsoft.cc> Date: 星期五, 08 八月 2025 17:28:08 +0800 Subject: [PATCH] 整合文搜万物模块 --- src/pages/modelTuning/components/rightCardList.vue | 600 +++++++++++++++++++++++++++++++++++++++++++++++------------ 1 files changed, 474 insertions(+), 126 deletions(-) diff --git a/src/pages/modelTuning/components/rightCardList.vue b/src/pages/modelTuning/components/rightCardList.vue index a5215fb..7b8ff6b 100644 --- a/src/pages/modelTuning/components/rightCardList.vue +++ b/src/pages/modelTuning/components/rightCardList.vue @@ -1,5 +1,41 @@ <template> <div class="image-gallery"> + <!-- 娣诲姞瀵煎叆缁勪欢 --> + <BatchImport ref="batchImport" :show-type-selector="false" @import="handleImportFiles" /> + <!-- 妯″瀷璁粌寮圭獥 --> + <el-dialog class="dialog1" title="妯″瀷璁粌" :visible.sync="trainDialogVisible" width="372px" top="10vh"> + <div class="info-label">鏍锋湰淇℃伅</div> + <div class="sample-info"> + <div class="sample-count">姝f牱鏈暟閲忥細{{ positiveCount }}</div> + <div class="sample-count">璐熸牱鏈暟閲忥細{{ negativeCount }}</div> + </div> + <div slot="footer" class="dialog-footer"> + <el-button @click="trainDialogVisible = false">鍙栨秷</el-button> + <el-button type="primary" @click="startTraining"> + <i class="el-icon-time"></i> + 寮�濮嬭缁�</el-button> + </div> + </el-dialog> + + <!-- 鎵归噺鏍囨敞寮圭獥 --> + <el-dialog class="dialog2" title="鎵归噺鏍囨敞" :visible.sync="batchLabelDialogVisible" width="472px" top="10vh"> + <div class="label-options"> + <div class="label-option" :class="{ active: batchLabelStatus === 1 }" @click="batchLabelStatus = 1"> + 姝g‘ + </div> + <div class="label-option" :class="{ active: batchLabelStatus === 2 }" @click="batchLabelStatus = 2"> + 閿欒 + </div> + <div class="label-option" :class="{ active: batchLabelStatus === 0 }" @click="batchLabelStatus = 0"> + 涓嶇‘瀹� + </div> + </div> + <div slot="footer" class="dialog-footer"> + <el-button type="danger" @click="handleBatchDelete">鎵归噺鍒犻櫎</el-button> + <el-button @click="batchLabelDialogVisible = false">鍙栨秷</el-button> + <el-button type="primary" @click="confirmBatchLabeling">纭畾</el-button> + </div> + </el-dialog> <!-- 椤堕儴绛涢�夊尯鍩� --> <div class="filter-section"> <el-form :inline="true" class="filter-form"> @@ -11,7 +47,8 @@ <!-- 閫夋嫨鏃舵 --> <el-form-item label="閫夋嫨鏃舵"> <el-date-picker style="width: 256px;" v-model="filter.timeRange" type="daterange" - value-format="yyyy-MM-dd" range-separator="鑷�" start-placeholder="寮�濮嬫棩鏈�" end-placeholder="缁撴潫鏃ユ湡" /> + value-format="yyyy-MM-dd" range-separator="鑷�" start-placeholder="寮�濮嬫棩鏈�" + end-placeholder="缁撴潫鏃ユ湡" /> </el-form-item> <!-- 鍒嗙被 --> @@ -38,13 +75,13 @@ <el-button type="primary" class="action-btn"> <i class="el-icon-download"></i> 瀵煎叆 </el-button> - <el-dropdown-menu slot="dropdown"> - <el-dropdown-item>姝f牱鏈�</el-dropdown-item> - <el-dropdown-item>璐熸牱鏈�</el-dropdown-item> - <el-dropdown-item>寰呮爣璁版牱鏈�</el-dropdown-item> + <el-dropdown-menu slot="dropdown" v-if="!this.trainId == 0"> + <el-dropdown-item @click.native="openImportDialog(1)">姝f牱鏈�</el-dropdown-item> + <el-dropdown-item @click.native="openImportDialog(2)">璐熸牱鏈�</el-dropdown-item> + <el-dropdown-item @click.native="openImportDialog(3)">寰呮爣璁版牱鏈�</el-dropdown-item> </el-dropdown-menu> </el-dropdown> - <el-button type="primary" class="action-btn"> + <el-button type="primary" @click="openTrainDialog" class="action-btn"> 妯″瀷璁粌 </el-button> </div> @@ -54,7 +91,8 @@ <!-- 鎵归噺鎿嶄綔鎺у埗鏍� --> <div class="batch-controls" v-if="isBatchMode"> <div class="select-all"> - <el-checkbox v-model="selectAll" @change="toggleSelectAll">鍏ㄩ��</el-checkbox> + <el-checkbox :indeterminate="isIndeterminate" v-model="selectAll" + @change="toggleSelectAll">鍏ㄩ��</el-checkbox> </div> <!-- <div>宸查�夋嫨 {{ selectedCount }} 涓」鐩�</div> --> <div class="batch-actions"> @@ -66,39 +104,54 @@ @status-change="handleStatusChange" @show-details="showImageDetails" @edit-annotation="editAnnotation" @download="downloadImage"--> <div class="gallery-section"> - <el-row :gutter="20" class="image-grid"> - <image-card v-for="(item, index) in galleryItems" :key="index" :item="item" :is-batch-mode="isBatchMode" - @delete-details="handleDeleteDetails" @status-change="handleStatusChange" - @card-click="handleCardClick1" @toggle-select="toggleSelect(index)" /> - </el-row> + <div class="image-grid" ref="imageGrid"> + <div v-for="(item, index) in galleryItems" :key="index" class="image-card-wrapper" + :style="{ width: cardWidth}"> + <image-card :item="item" :is-batch-mode="isBatchMode" @delete-details="handleDeleteDetails" + @status-change="handleStatusChange" @card-click="handleCardClick1" + @toggle-select="toggleSelect(index)" /> + </div> + </div> </div> <!-- 鍒嗛〉缁勪欢 --> <Pagination :total="totalCount" :current-page.sync="currentPage" :page-size.sync="pageSize" - @pagination-change="fetchTableData" /> + @pagination-change="paginationChange" /> </div> </template> <script> +import _ from 'lodash'; // 鐢ㄤ簬闃叉姈 +import BatchImport from './batchImport'; import imageCard from './imageCard'; import Pagination from '@/components/rightPagination'; -import { getTrainTags, getTrains, updateTrainStatus, deleteTrains } from "@/api/modelTuning"; +import { getTrains, updateTrainStatus, deleteTrains, batchUpdateTrainStatus, batchDeleteTrains, uploadDataTrainTags } from "@/api/modelTuning"; export default { components: { imageCard, Pagination, + BatchImport }, name: 'ImageGallery', - props: { - trainId: { - type: Number - }, - }, data() { return { + cardWidth: 'calc(25% - 20px)', // 榛樿4鍒楀竷灞� + minCardWidth: 300, // 鍗$墖鏈�灏忓搴� + margin: 20, // 鍗$墖闂磋窛 + trainDialogVisible: false, // 妯″瀷璁粌寮圭獥鍙鎬� + batchLabelDialogVisible: false, // 鎵归噺鏍囨敞寮圭獥鍙鎬� + // 妯″瀷璁粌寮圭獥鏁版嵁 + positiveCount: 0, // 姝f牱鏈暟閲� + negativeCount: 0, // 璐熸牱鏈暟閲� + // 鎵归噺鏍囨敞鐘舵�� + batchLabelStatus: 0, // 榛樿閫夋嫨"涓嶇‘瀹�" + isIndeterminate: false, + selectAll: false, + pagination: {}, + trainId: 0, totalCount: 0, // 鎬绘暟鎹噺 currentPage: 1, // 褰撳墠椤电爜 - pageSize: 12, // 姣忛〉鏁伴噺 + pageSize: 15, // 姣忛〉鏁伴噺 tableData: [], // 琛ㄦ牸鏁版嵁 // 鏄惁鎵归噺妯″紡 isBatchMode: false, @@ -106,92 +159,146 @@ // 绛涢�夋潯浠� filter: { cameraName: '', - timeRange: ['2025-06-22', '2025-06-28'], - category: 'all' + timeRange: ['', ''], + category: -1 }, // 鍒嗙被閫夐」 categories: [ - { label: '鍏ㄩ儴', value: 'all' }, - { label: '姝g‘', value: 'correct' }, - { label: '閿欒', value: 'incorrect' }, - { label: '涓嶇‘瀹�', value: 'unknown' } + { label: '鍏ㄩ儴', value: -1 }, + { label: '姝g‘', value: 1 }, + { label: '閿欒', value: 2 }, + { label: '涓嶇‘瀹�', value: 0 } ], // 鍥剧墖鏁版嵁 galleryItems: [ - { - id: 1, - image: "@/assets/img/鏍锋湰鍥�.png", - date: '2025-07-01 10:00:09', - camera: '澶ч棬鍙f娴嬫憚鍍忓ご', - status: 'correct' - }, - { - id: 2, - image: "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='300' height='200' viewBox='0 0 300 200'%3E%3Crect width='300' height='200' fill='%23f0f7ff'/%3E%3Crect x='50' y='30' width='200' height='140' rx='5' ry='5' fill='%23d5e8ff' stroke='%23409EFF' stroke-width='1'/%3E%3Cpath d='M100,60 L200,60 M100,80 L200,80 M100,100 L200,100 M100,120 L200,120 M100,140 L200,140' stroke='%23409EFF' stroke-width='1'/%3E%3Cpath d='M80,80 L120,120 M80,120 L120,80' stroke='%23FF4D4F' stroke-width='2' stroke-linecap='round'/%3E%3C/svg%3E", - date: '2025-07-01 10:00:09', - camera: '澶ч棬鍙f娴嬫憚鍍忓ご', - status: 'incorrect' - }, - { - id: 3, - image: "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='300' height='200' viewBox='0 0 300 200'%3E%3Crect width='300' height='200' fill='%23f0f7ff'/%3E%3Crect x='50' y='30' width='200' height='140' rx='5' ry='5' fill='%23d5e8ff' stroke='%23409EFF' stroke-width='1'/%3E%3Cellipse cx='150' cy='100' rx='70' ry='40' stroke='%23409EFF' stroke-width='1' fill='none'/%3E%3Ccircle cx='130' cy='80' r='5' fill='%23409EFF'/%3E%3Ccircle cx='170' cy='80' r='5' fill='%23409EFF'/%3E%3Cpath d='M150,100 Q160,120 140,120' stroke='%23409EFF' stroke-width='1' fill='none'/%3E%3C/svg%3E", - date: '2025-07-01 10:00:09', - camera: '澶ч棬鍙f娴嬫憚鍍忓ご', - status: 'correct' - }, - { - id: 4, - image: "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='300' height='200' viewBox='0 0 300 200'%3E%3Crect width='300' height='200' fill='%23f0f7ff'/%3E%3Crect x='50' y='30' width='200' height='140' rx='5' ry='5' fill='%23d5e8ff' stroke='%23409EFF' stroke-width='1'/%3E%3Cpath d='M80,80 L220,80 M150,50 L150,110' stroke='%23409EFF' stroke-width='1'/%3E%3Ccircle cx='150' cy='80' r='40' stroke='%23409EFF' stroke-width='1' fill='none'/%3E%3C/svg%3E", - date: '2025-07-01 10:00:09', - camera: '澶ч棬鍙f娴嬫憚鍍忓ご', - status: 'unknown' - }, - { - id: 5, - image: "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='300' height='200' viewBox='0 0 300 200'%3E%3Crect width='300' height='200' fill='%23f0f7ff'/%3E%3Crect x='50' y='30' width='200' height='140' rx='5' ry='5' fill='%23d5e8ff' stroke='%23409EFF' stroke-width='1'/%3E%3Cpath d='M100,60 L200,60 M100,80 L200,80 M100,100 L200,100 M100,120 L200,120' stroke='%23409EFF' stroke-width='1'/%3E%3Cpath d='M120,100 A20,20 0 1,1 180,100 A20,20 0 1,1 120,100' stroke='%23409EFF' stroke-width='1' fill='none'/%3E%3C/svg%3E", - date: '2025-07-01 10:00:09', - camera: '澶ч棬鍙f娴嬫憚鍍忓ご', - status: 'correct' - }, - { - id: 6, - image: "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='300' height='200' viewBox='0 0 300 200'%3E%3Crect width='300' height='200' fill='%23f0f7ff'/%3E%3Crect x='50' y='30' width='200' height='140' rx='5' ry='5' fill='%23d5e8ff' stroke='%23409EFF' stroke-width='1'/%3E%3Crect x='70' y='60' width='60' height='40' rx='3' ry='3' fill='%23a0c8ff' stroke='%23409EFF' stroke-width='1'/%3E%3Crect x='170' y='60' width='60' height='40' rx='3' ry='3' fill='%23a0c8ff' stroke='%23409EFF' stroke-width='1'/%3E%3Crect x='120' y='120' width='60' height='20' rx='2' ry='2' fill='%23a0c8ff' stroke='%23409EFF' stroke-width='1'/%3E%3C/svg%3E", - date: '2025-07-01 10:00:09', - camera: '澶ч棬鍙f娴嬫憚鍍忓ご', - status: 'incorrect' - } ] } }, mounted() { - this.fastFetchTableData() + this.calculateCardWidth(); + // 娣诲姞闃叉姈鐨剅esize鐩戝惉 + window.addEventListener('resize', _.debounce(this.calculateCardWidth, 100)); + }, + beforeDestroy() { + window.removeEventListener('resize', this.calculateCardWidth); }, methods: { - async fastFetchTableData() { - let rspc = await getTrainTags(); - if (rspc && rspc.status === 200) { - this.fetchTableData({ - tagId: rspc.data.list[0].id - }) + // 鏂板鍗$墖瀹藉害璁$畻鏂规硶 + calculateCardWidth() { + if (this.$refs.imageGrid) { + const containerWidth = this.$refs.imageGrid.clientWidth; + // 璁$畻姣忚鍙互鏀剧疆鐨勫崱鐗囨暟閲� + const cardsPerRow = Math.floor(containerWidth / (this.minCardWidth + this.margin)); + const n = Math.max(3, cardsPerRow); // 鑷冲皯1鍒� + // 璁剧疆鍗$墖瀹藉害鍏紡 + this.cardWidth = `calc(${100 / n}% - ${this.margin}px)`; } + }, + // 鎵撳紑瀵煎叆瀵硅瘽妗� + openImportDialog(type) { + this.$refs.batchImport.presetType = type; + this.$refs.batchImport.open(); + }, + // 澶勭悊瀵煎叆鐨勬枃浠� + async handleImportFiles({ type, files }) { + try { + this.$loading({ text: `瀵煎叆${this.getTypeName(type)}涓�...` }); + // 1. 鍒涘缓FormData鐢ㄤ簬鏂囦欢涓婁紶 + let formData = new FormData(); + // 2. 娣诲姞瀹為檯鏂囦欢鍐呭鍒癋ormData + files.forEach(item => { + formData.append('file', item); + }); + formData.append('tagId', this.trainId); + formData.append('status', type === 3 ? 0 : type); + + // console.log(formData) + // // 妯℃嫙涓婁紶璇锋眰锛堝疄闄呭簲璋冪敤API锛� + let rspc = await uploadDataTrainTags(formData) + if (rspc && rspc.status === 200) { + this.$message({ + type: 'success', + message: '鎴愬姛' + }); + this.fetchTableData() + } else { + this.$message({ + type: 'error', + message: rspc.msg + }); + + } + } catch (error) { + this.$message.error(`瀵煎叆澶辫触: ${error.message}`); + } finally { + this.$loading().close(); + } + }, + getTypeName(type) { + return { + 1: '姝f牱鏈�', + 2: '璐熸牱鏈�', + 3: '寰呮爣璁版牱鏈�' + }[type]; + }, + // 妯℃嫙鏂囦欢涓婁紶鍑芥暟 + async uploadFile(file, type) { + // 鍦ㄥ疄闄呭簲鐢ㄤ腑锛岃繖閲屽簲璇ユ槸涓�涓狝PI璋冪敤 + return new Promise((resolve) => { + const formData = new FormData(); + formData.append('file', file); + formData.append('type', type); + formData.append('trainId', this.trainId); + + // 璋冪敤涓婁紶API锛屼緥濡�: + // await uploadSample(formData); + resolve(); + }); + }, + async paginationChange(params) { + this.currentPage = params.page + this.pageSize = params.pageSize + await this.fetchTableData() + }, + async changeTrainId(trainId) { + // console.info(trainId) + this.trainId = trainId + this.isBatchMode = false + await this.fetchTableData() }, // 鑾峰彇琛ㄦ牸鏁版嵁鏂规硶 async fetchTableData(params) { - // yourApi.getData(params).then(res => { - // this.tableData = res.data.list - // this.totalCount = res.data.total - // }) + // console.info(this.currentPage) this.galleryItems = [] - params.page = this.currentPage - params.pageSize = this.pageSize - let rspc = await getTrains(params); + // params.tagId = this.trainId + let rspc = await getTrains({ + tagId: this.trainId, + page: this.currentPage, + pageSize: this.pageSize, + startTime: this.filter.timeRange[0] ? this.filter.timeRange[0] + " 00:00:00" : "", + endTime: this.filter.timeRange[1] ? this.filter.timeRange[1] + " 23:23:59" : "", + searchName: this.filter.cameraName, + status: this.filter.category + }); if (rspc && rspc.status === 200) { - this.galleryItems = rspc.data.list; + if (rspc.data.list) { + this.galleryItems = rspc.data.list.map(item => ({ + ...item, + selected: false // 纭繚姣忎釜鍗$墖閮芥湁鍒濆鍊� + })); + } } // console.log('trainId:', this.trainId); - this.totalCount = 20 + this.totalCount = rspc.data.pagination.total + // 鏇存柊鍒嗛〉鏁版嵁鍓嶅厛鏍¢獙褰撳墠椤电爜 + const totalPage = rspc.data.pagination.totalPage + const currentPage = this.currentPage > totalPage + ? totalPage + : rspc.data.pagination.page + this.currentPage = currentPage, + this.totalPage = totalPage }, //鍒犻櫎 async handleDeleteDetails(item) { @@ -209,7 +316,11 @@ type: 'success', message: '鎴愬姛' }); - this.fetchSelectData() + // 鍒犻櫎鎴愬姛鍚庤嚜鍔ㄤ慨姝i〉鐮� + if (this.galleryItems && this.galleryItems.length === 1 && this.currentPage > 1) { + this.currentPage -= 1 + } + this.fetchTableData() } else { this.$message({ type: 'error', @@ -223,18 +334,20 @@ }, //淇敼鍥剧墖鐘舵�� async handleStatusChange(parm) { - console.log('淇敼鐘舵��', parm); + // console.log('淇敼鐘舵��', parm); let rspc = await updateTrainStatus(parm); if (rspc && rspc.status === 200) { this.$message({ type: 'success', message: '鎴愬姛' }); - this.fetchTableData({ - tagId: this.trainId, - page: this.currentPage, - limit: this.pageSize - }) + + // for (let i = 0; i < this.galleryItems.length; i++) { + // if (parm.trainId === this.galleryItems[i].trainId) { + // this.galleryItems[i].status = parm.status + // } + // } + this.fetchTableData() } else { this.$message({ type: 'error', @@ -250,9 +363,10 @@ // 澶勭悊鎼滅储 handleSearch() { // console.log('鎵ц鎼滅储:', this.filter); - // console.log('trainId:', this.trainId); - // 杩欓噷鍙互娣诲姞瀹為檯鐨勬悳绱㈤�昏緫 - this.fetchTableData({ tagId: this.trainId }) + // console.log('filter:', this.filter.cameraName); + this.currentPage = 1, // 褰撳墠椤电爜 + // 杩欓噷鍙互娣诲姞瀹為檯鐨勬悳绱㈤�昏緫 + this.fetchTableData() }, // 閲嶇疆绛涢�夋潯浠� @@ -260,26 +374,15 @@ this.filter = { cameraName: '', timeRange: ['', ''], - category: 'all' + category: -1 }; console.log('宸查噸缃瓫閫夋潯浠�'); }, // 杩涘叆鎵归噺妯″紡 enterBatchMode() { - // this.isBatchMode = true; - // this.selectAll = false; - // this.batchSelected = []; - - // // 娓呴櫎宸查�夌姸鎬� - // this.galleryItems.forEach(item => { - // item.selected = false; - // }); - }, - - // 閫�鍑烘壒閲忔ā寮� - exitBatchMode() { - this.isBatchMode = false; + this.isBatchMode = true; this.selectAll = false; + this.isIndeterminate = false; this.batchSelected = []; // 娓呴櫎宸查�夌姸鎬� @@ -287,44 +390,201 @@ item.selected = false; }); }, + + // 閫�鍑烘壒閲忔ā寮� + exitBatchMode() { + this.isBatchMode = false; + this.selectAll = false; + this.isIndeterminate = false; + this.batchSelected = []; + + // 娓呴櫎宸查�夌姸鎬� + this.galleryItems.forEach(item => { + if (item.hasOwnProperty('selected')) { + item.selected = false; + } + }); + }, toggleSelect(index) { if (!this.isBatchMode) return; - const position = this.batchSelected.indexOf(index); - if (position === -1) { + const isCurrentlySelected = this.galleryItems[index].selected; + + // 鏇存柊閫変腑鐘舵�� + this.$set(this.galleryItems[index], 'selected', !isCurrentlySelected); + + // 鏇存柊batchSelected鏁扮粍 + if (!isCurrentlySelected) { + // 娣诲姞閫夋嫨 this.batchSelected.push(index); } else { - this.batchSelected.splice(position, 1); + // 绉婚櫎閫夋嫨 + const position = this.batchSelected.indexOf(index); + if (position !== -1) { + this.batchSelected.splice(position, 1); + } } this.checkAllSelected(); }, checkAllSelected() { - this.isAllSelected = this.batchSelected.length === this.galleryItems.length; + this.selectAll = this.batchSelected.length === this.galleryItems.length; + this.isIndeterminate = this.batchSelected.length > 0 && this.batchSelected.length < this.galleryItems.length; + // console.info("batchSelected.length="+this.batchSelected.length) + // console.info("galleryItems.length="+this.galleryItems.length) }, // 鍏ㄩ��/鍙栨秷鍏ㄩ�� toggleSelectAll() { - this.galleryItems.forEach(item => { - item.selected = this.selectAll; + const allSelected = this.selectAll; + this.batchSelected = []; + + this.galleryItems.forEach((_, index) => { + this.$set(this.galleryItems[index], 'selected', allSelected); + if (allSelected) { + this.batchSelected.push(index); + } }); + this.isIndeterminate = this.batchSelected.length > 0 && this.batchSelected.length < this.galleryItems.length; }, // 纭鎵归噺鎿嶄綔 confirmBatch() { - const selectedItems = this.galleryItems.filter(item => item.selected); + this.openBatchLabelDialog() + }, + // 鎵撳紑妯″瀷璁粌寮圭獥 + openTrainDialog() { + // 姝ゅ搴旇皟鐢ˋPI鑾峰彇瀹為檯鐨勬牱鏈暟閲� + // 杩欓噷浣跨敤绀轰緥鏁版嵁 + this.positiveCount = this.galleryItems.filter(item => item.status === 1).length; + this.negativeCount = this.galleryItems.filter(item => item.status === 2).length; + this.trainDialogVisible = true; + }, + // 寮�濮嬭缁� + async startTraining() { + try { + // this.$loading({ text: '妯″瀷璁粌涓�...' }); + // 璋冪敤瀹為檯鐨勮缁傾PI + // await startModelTraining({ + // positive: this.positiveCount, + // negative: this.negativeCount + // }); - this.$message({ - message: `宸插${selectedItems.length}涓」鎵ц鎵归噺鎿嶄綔`, - type: 'success' + // 妯℃嫙API寤惰繜 + // await new Promise(resolve => setTimeout(resolve, 2000)); + + // this.$message.success('妯″瀷璁粌宸插紑濮�'); + this.trainDialogVisible = false; + this.$message.error(`鍔熻兘鏆傛湭瀹炵幇`); + } catch (error) { + this.$message.error(`璁粌澶辫触: ${error.message}`); + } finally { + this.$loading().close(); + } + }, + // 鎵撳紑鎵归噺鏍囨敞寮圭獥 + openBatchLabelDialog() { + if (this.batchSelected.length === 0) { + this.$message.warning('璇峰厛閫夋嫨鍥剧墖杩涜鏍囨敞'); + return; + } + this.batchLabelStatus = 0; // 閲嶇疆涓轰笉纭畾鐘舵�� + this.batchLabelDialogVisible = true; + }, + // 纭鎵归噺鏍囨敞 + async confirmBatchLabeling() { + if (this.batchSelected.length === 0) { + this.$message.warning('璇峰厛閫夋嫨鍥剧墖'); + return; + } + + try { + // this.$loading({ text: '鎵归噺鏍囨敞涓�...' }); + + const selectedItems = this.galleryItems.filter(item => item.selected); + let ids = [] + for (let i = 0; i < selectedItems.length; i++) { + ids.push(selectedItems[i].trainId) + } + + // 璋冪敤鎵归噺鏇存柊鐘舵�佺殑API + let rspc = await batchUpdateTrainStatus({ + ids: ids, + status: this.batchLabelStatus + }) + if (rspc && rspc.status === 200) { + this.$message.success(`宸叉垚鍔熸爣娉�${selectedItems.length}涓暟鎹甡); + this.batchLabelDialogVisible = false; + this.exitBatchMode(); // 閫�鍑烘壒閲忔ā寮� + this.fetchTableData(); // 鍒锋柊鏁版嵁 + } else { + this.$message.error(`鏍囨敞澶辫触: ${rspc.msg}`); + } + } catch (error) { + this.$message.error(`鏍囨敞澶辫触: ${error.message}`); + } finally { + this.$loading().close(); + } + }, + // 鎵归噺鍒犻櫎 + async handleBatchDelete() { + if (this.batchSelected.length === 0) { + this.$message.warning('璇峰厛閫夋嫨鍥剧墖'); + return; + } + + this.$confirm(`纭畾瑕佸垹闄ら�変腑鐨�${this.batchSelected.length}涓暟鎹悧锛焋, '璀﹀憡', { + confirmButtonText: '纭畾', + cancelButtonText: '鍙栨秷', + type: 'warning' + }).then(async () => { + try { + // this.$loading({ text: '鍒犻櫎涓�...' }); + + // 璋冪敤鎵归噺鍒犻櫎API + let rspc = await batchDeleteTrains({ + ids: ids + }) + if (rspc && rspc.status === 200) { + this.$message.success(`宸叉垚鍔熷垹闄�${this.batchSelected.length}涓暟鎹甡); + this.batchLabelDialogVisible = false; + this.exitBatchMode(); // 閫�鍑烘壒閲忔ā寮� + this.fetchTableData(); // 鍒锋柊鏁版嵁 + } else { + this.$message.error(`鍒犻櫎澶辫触: ${rspc.msg}`); + } + } catch (error) { + this.$message.error(`鍒犻櫎澶辫触: ${error.message}`); + } finally { + this.$loading().close(); + } + }).catch(() => { + // 鐢ㄦ埛鍙栨秷鍒犻櫎 }); - - this.exitBatchMode(); }, } } </script> <style scoped> +/* 鏂板鍥剧墖缃戞牸甯冨眬鏍峰紡 */ +.image-grid { + display: flex; + flex-wrap: wrap; + margin: -10px; + min-width: 1000px; + /* 璐熻竟璺濇姷娑堝寘瑁瑰厓绱犵殑杈硅窛 */ + /* width: 100%; */ +} + +.image-card-wrapper { + margin: 10px; + /* 璁剧疆鍗$墖闂磋窛 */ + box-sizing: border-box; + /* transition: width 0.3s ease; */ + /* 娣诲姞骞虫粦杩囨浮鏁堟灉 */ +} + .image-gallery { + min-width: 1265px; background-color: #ffffff; padding: 20px; border-radius: 4px; @@ -334,8 +594,8 @@ /* 绛涢�夊尯鍩熸牱寮� */ .filter-section { - padding: 20px; - background-color: #f5f7fa; + /* padding: 20px; */ + /* background-color: #f5f7fa; */ border-radius: 4px; margin-bottom: 20px; } @@ -385,11 +645,12 @@ display: flex; align-items: center; background: #fff; - border-bottom: 1px solid #e6ebf5; - padding: 10px 20px; + /* border-bottom: 1px solid #e6ebf5; */ + padding: 5px; margin-bottom: 20px; - border-radius: 4px; - box-shadow: 0 1px 4px rgba(0, 0, 0, 0.05); + margin-top: -10px; + /* border-radius: 4px; */ + /* box-shadow: 0 1px 4px rgba(0, 0, 0, 0.05); */ } @@ -402,4 +663,91 @@ display: flex; gap: 10px; } + +/* 鏍囬宸﹀榻� */ +::v-deep .el-dialog__header { + text-align: left; +} + +::v-deep .el-dialog__title { + font-weight: bold; + font-size: 16px; +} + +::v-deep .el-dialog__body { + padding-top: 20px; + padding-bottom: 15px; +} + +/* 妯″瀷璁粌寮圭獥鏍峰紡 */ +.dialog1 { + .info-label { + font-weight: bold; + font-size: 20px; + margin-bottom: 15px; + color: black; + text-align: left; + } + + .sample-info { + display: flex; + justify-content: space-between; + /* padding: 0 10px; */ + margin-bottom: 20px; + } + + .sample-count { + /* font-weight: 600; */ + font-size: 15px; + color: #333; + } + + .dialog-footer { + display: flex; + justify-content: flex-end; + padding: 10px 0; + } +} + +/* 鎵归噺鎯�嶅脊绐楁牱寮� */ +.dialog2 { + + /* 鎵归噺鏍囨敞寮圭獥鍐呭 */ + .label-options { + display: flex; + flex-direction: column; + } + + .label-option { + width: 100%; + padding: 15px 20px; + margin: 8px 0; + border: 1px solid #dcdfe6; + border-radius: 4px; + cursor: pointer; + transition: all 0.3s; + text-align: center; + box-sizing: border-box; + } + + .label-option:hover { + border-color: #409eff; + color: #409eff; + } + + .label-option.active { + border-color: #409eff; + background-color: #ecf5ff; + color: #409eff; + } + + /* 寮圭獥搴曢儴鎸夐挳 */ + .dialog-footer { + /* display: flex; */ + text-align: center; + /* justify-content: space-between; */ + /* padding: 10px 20px; */ + /* border-top: 1px solid #e6ebf5; */ + } +} </style> \ No newline at end of file -- Gitblit v1.8.0