From 41bcd5f09e1a357ddafdd7b02c32d93327333e62 Mon Sep 17 00:00:00 2001
From: sd <shidong@jhsoft.cc>
Date: 星期四, 07 八月 2025 11:55:18 +0800
Subject: [PATCH] 模型训练-卡片样式:根据容器大小自适应调整卡片大小

---
 src/pages/modelTuning/components/rightCardList.vue |  610 ++++++++++++++++++++++++++++++++++++++++++++++++-------
 1 files changed, 531 insertions(+), 79 deletions(-)

diff --git a/src/pages/modelTuning/components/rightCardList.vue b/src/pages/modelTuning/components/rightCardList.vue
index f4d15d7..1eeb450 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 hh:mm:ss" 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,96 +104,277 @@
                     @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" 
-                    @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="paginationChange" />
     </div>
 </template>
 
 <script>
+import _ from 'lodash'; // 鐢ㄤ簬闃叉姈
+import BatchImport from './batchImport';
 import imageCard from './imageCard';
+import Pagination from '@/components/rightPagination';
+import { getTrains, updateTrainStatus, deleteTrains, batchUpdateTrainStatus, batchDeleteTrains, uploadDataTrainTags } from "@/api/modelTuning";
 export default {
     components: {
-        imageCard
+        imageCard,
+        Pagination,
+        BatchImport
+
     },
     name: 'ImageGallery',
     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: 15,     // 姣忛〉鏁伴噺
+            tableData: [],    // 琛ㄦ牸鏁版嵁
             // 鏄惁鎵归噺妯″紡
             isBatchMode: false,
             batchSelected: [],  // 宸查�夋嫨鐨勫崱鐗囩储寮�
             // 绛涢�夋潯浠�
             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: [
-                {
-                    image: "@/assets/img/鏍锋湰鍥�.png",
-                    date: '2025-07-01 10:00:09',
-                    camera: '澶ч棬鍙f娴嬫憚鍍忓ご',
-                    status: 'correct'
-                },
-                {
-                    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'
-                },
-                {
-                    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'
-                },
-                {
-                    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'
-                },
-                {
-                    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'
-                },
-                {
-                    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.calculateCardWidth();
+        // 娣诲姞闃叉姈鐨剅esize鐩戝惉
+        window.addEventListener('resize', _.debounce(this.calculateCardWidth, 100));
+    },
+    beforeDestroy() {
+        window.removeEventListener('resize', this.calculateCardWidth);
+    },
     methods: {
+        // 鏂板鍗$墖瀹藉害璁$畻鏂规硶
+        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) {
+            // console.info(this.currentPage)
+            this.galleryItems = []
+            // 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) {
+                if (rspc.data.list) {
+                    this.galleryItems = rspc.data.list.map(item => ({
+                        ...item,
+                        selected: false // 纭繚姣忎釜鍗$墖閮芥湁鍒濆鍊�
+                    }));
+                }
+            }
+            // console.log('trainId:', this.trainId);
+            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) {
+            // console.log('鍒犻櫎', item);
+            this.$confirm('姝ゆ搷浣滃皢姘镐箙鍒犻櫎鏁版嵁, 鏄惁缁х画?', '鎻愮ず', {
+                confirmButtonText: '纭畾',
+                cancelButtonText: '鍙栨秷',
+                type: 'warning'
+            }).then(async () => {
+                let rspc = await deleteTrains({
+                    trainId: item.trainId,
+                });
+                if (rspc && rspc.status === 200) {
+                    this.$message({
+                        type: 'success',
+                        message: '鎴愬姛'
+                    });
+                    // 鍒犻櫎鎴愬姛鍚庤嚜鍔ㄤ慨姝i〉鐮�
+                    if (this.galleryItems && this.galleryItems.length === 1 && this.currentPage > 1) {
+                        this.currentPage -= 1
+                    }
+                    this.fetchTableData()
+                } else {
+                    this.$message({
+                        type: 'error',
+                        message: rspc.msg
+                    });
+
+                }
+            }).catch(() => {
+                console.info("鍙栨秷")
+            });
+        },
+        //淇敼鍥剧墖鐘舵��
+        async handleStatusChange(parm) {
+            // console.log('淇敼鐘舵��', parm);
+            let rspc = await updateTrainStatus(parm);
+            if (rspc && rspc.status === 200) {
+                this.$message({
+                    type: 'success',
+                    message: '鎴愬姛'
+                });
+
+                // 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',
+                    message: rspc.msg
+                });
+
+            }
+        },
+        //璇︽儏
+        handleCardClick1() {
+            console.log('鎵ц璇︽儏');
+        },
         // 澶勭悊鎼滅储
         handleSearch() {
-            console.log('鎵ц鎼滅储:', this.filter);
-            // 杩欓噷鍙互娣诲姞瀹為檯鐨勬悳绱㈤�昏緫
+            // console.log('鎵ц鎼滅储:', this.filter);
+            // console.log('filter:', this.filter.cameraName);
+            this.currentPage = 1,    // 褰撳墠椤电爜
+                // 杩欓噷鍙互娣诲姞瀹為檯鐨勬悳绱㈤�昏緫
+                this.fetchTableData()
         },
 
         // 閲嶇疆绛涢�夋潯浠�
         handleReset() {
             this.filter = {
                 cameraName: '',
-                timeRange: ['2025-06-22', '2025-06-28'],
-                category: 'all'
+                timeRange: ['', ''],
+                category: -1
             };
             console.log('宸查噸缃瓫閫夋潯浠�');
         },
@@ -163,6 +382,7 @@
         enterBatchMode() {
             this.isBatchMode = true;
             this.selectAll = false;
+            this.isIndeterminate = false;
             this.batchSelected = [];
 
             // 娓呴櫎宸查�夌姸鎬�
@@ -175,50 +395,194 @@
         exitBatchMode() {
             this.isBatchMode = false;
             this.selectAll = false;
+            this.isIndeterminate = false;
             this.batchSelected = [];
 
             // 娓呴櫎宸查�夌姸鎬�
             this.galleryItems.forEach(item => {
-                item.selected = false;
+                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 {
     background-color: #ffffff;
     padding: 20px;
@@ -229,8 +593,8 @@
 
 /* 绛涢�夊尯鍩熸牱寮� */
 .filter-section {
-    padding: 20px;
-    background-color: #f5f7fa;
+    /* padding: 20px; */
+    /* background-color: #f5f7fa; */
     border-radius: 4px;
     margin-bottom: 20px;
 }
@@ -280,11 +644,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); */
 
 }
 
@@ -297,4 +662,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