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