|
|
@@ -0,0 +1,435 @@
|
|
|
+<script setup lang="ts">
|
|
|
+import { ref, computed, onMounted } from 'vue';
|
|
|
+import { GetPhotoListApp,RenameFolderFileNameApp,OpenFolder } from '../../wailsjs/go/main/App';
|
|
|
+import { ElMessageBox ,ElLoading} from 'element-plus'
|
|
|
+// 页面状态
|
|
|
+const loading = ref(false);
|
|
|
+const loadingMore = ref(false);
|
|
|
+const error = ref<string | null>(null);
|
|
|
+const fullscreenLoading = ref(false)
|
|
|
+// 数据
|
|
|
+const photoList = ref<any[]>([]);
|
|
|
+const selectedProducts = ref<number[]>([]); // 存储选中的货号索引
|
|
|
+
|
|
|
+// 分页状态
|
|
|
+const currentPage = ref(1);
|
|
|
+const pageSize = ref(20); // 每页显示10条记录
|
|
|
+const totalCount = ref(0);
|
|
|
+const totalPages = ref(1);
|
|
|
+const hasPrev = ref(false);
|
|
|
+const hasNext = ref(true); // 默认有下一页,直到加载完成
|
|
|
+const dialogTableVisible = ref(false)
|
|
|
+const output_folder = ref<any[]>([])
|
|
|
+// 计算已选择的图片数量
|
|
|
+const selectedCount = computed(() => {
|
|
|
+ return selectedProducts.value.length;
|
|
|
+});
|
|
|
+
|
|
|
+// 获取拍照列表数据
|
|
|
+const fetchPhotoList = async (page: number = 1, append = false) => {
|
|
|
+ if (page === 1) {
|
|
|
+ loading.value = true;
|
|
|
+ } else {
|
|
|
+ loadingMore.value = true;
|
|
|
+ }
|
|
|
+
|
|
|
+ error.value = null;
|
|
|
+
|
|
|
+ try {
|
|
|
+ // 调用API时传递分页参数
|
|
|
+ const data = await GetPhotoListApp(page.toString());
|
|
|
+ console.log("获取的拍照列表数据:", data);
|
|
|
+
|
|
|
+ if (data) {
|
|
|
+ if (append) {
|
|
|
+ // 追加数据到现有列表
|
|
|
+ photoList.value = [...photoList.value, ...data.list];
|
|
|
+ } else {
|
|
|
+ // 替换整个列表
|
|
|
+ photoList.value = data.list || [];
|
|
|
+ }
|
|
|
+
|
|
|
+ // 设置分页信息
|
|
|
+ currentPage.value = data.current_page || 1;
|
|
|
+ pageSize.value = data.size || 10;
|
|
|
+ totalCount.value = data.total_count || 0;
|
|
|
+ totalPages.value = data.total_pages || 1;
|
|
|
+ hasPrev.value = data.has_prev || false;
|
|
|
+ hasNext.value = data.has_next || false;
|
|
|
+ } else {
|
|
|
+ console.warn('返回的数据格式不正确:', data);
|
|
|
+ error.value = '获取的数据格式不正确';
|
|
|
+ }
|
|
|
+ } catch (err) {
|
|
|
+ console.error('获取拍照列表失败:', err);
|
|
|
+ error.value = err instanceof Error ? err.message : '获取数据失败';
|
|
|
+ } finally {
|
|
|
+ loading.value = false;
|
|
|
+ loadingMore.value = false;
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+// 加载更多数据
|
|
|
+const loadMore = async () => {
|
|
|
+ if (!hasNext.value) return;
|
|
|
+
|
|
|
+ const nextPage = currentPage.value + 1;
|
|
|
+ await fetchPhotoList(nextPage, true); // 追加数据
|
|
|
+};
|
|
|
+
|
|
|
+// 刷新数据(重新从第一页开始)
|
|
|
+const refreshData = async () => {
|
|
|
+ await fetchPhotoList(1, false);
|
|
|
+};
|
|
|
+
|
|
|
+// 检查货号是否被选中
|
|
|
+const isProductSelected = (index: number) => {
|
|
|
+ // 由于列表现在是追加的,我们需要根据实际数据的索引判断
|
|
|
+ return selectedProducts.value.includes(index);
|
|
|
+};
|
|
|
+
|
|
|
+// 处理货号选择变化
|
|
|
+const handleProductSelectionChange = (index: number) => {
|
|
|
+ const isSelected = selectedProducts.value.includes(index);
|
|
|
+ if (isSelected) {
|
|
|
+ // 如果已选中,则取消选中
|
|
|
+ selectedProducts.value = selectedProducts.value.filter(i => i !== index);
|
|
|
+ } else {
|
|
|
+ // 如果未选中,则添加到选中列表
|
|
|
+ selectedProducts.value.push(index);
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+// 发起批量抠图的事件处理函数
|
|
|
+const handleBatchCutout = async() => {
|
|
|
+ console.log('发起批量抠图请求');
|
|
|
+ console.log('选中的货号索引:', selectedProducts.value);
|
|
|
+ // 获取选中的货号和对应的图片
|
|
|
+ const selectedData = selectedProducts.value.map(index => {
|
|
|
+ // 确保索引在当前列表范围内
|
|
|
+ if (index >= 0 && index < photoList.value.length) {
|
|
|
+ return photoList.value[index].goods_art_no;
|
|
|
+ }
|
|
|
+ return null;
|
|
|
+ }).filter(item => item !== null);
|
|
|
+ console.log('选中的数据:', selectedData);
|
|
|
+ const loading = ElLoading.service({
|
|
|
+ lock: true,
|
|
|
+ text: '处理中,请稍后...',
|
|
|
+ background: 'rgba(0, 0, 0, 0.7)',
|
|
|
+ })
|
|
|
+ try {
|
|
|
+ // 这里可以调用 API 或触发其他逻辑
|
|
|
+ output_folder.value = await RenameFolderFileNameApp(selectedData)
|
|
|
+ if (output_folder.value.length>0) {
|
|
|
+ console.log('抠图成功,输出文件夹:', output_folder.value)
|
|
|
+ // await ElMessageBox.confirm('重命名成功,点击确认打开目录',{
|
|
|
+ // closeOnClickModal: false, // 点击遮罩层不关闭
|
|
|
+ // closeOnPressEscape: false, // 按ESC键不关闭
|
|
|
+ // showCancelButton: false, // 隐藏取消按钮
|
|
|
+ // }).then(async () => {
|
|
|
+ // // await OpenFolder(output_folder)
|
|
|
+ // })
|
|
|
+ dialogTableVisible.value = true
|
|
|
+ selectedProducts.value = []
|
|
|
+ } else {
|
|
|
+ console.error('抠图失败')
|
|
|
+ await ElMessageBox.confirm('重命名失败,请选择其他货号重试',{
|
|
|
+ closeOnClickModal: false, // 点击遮罩层不关闭
|
|
|
+ closeOnPressEscape: false, // 按ESC键不关闭
|
|
|
+ showCancelButton: false, // 隐藏取消按钮
|
|
|
+ })
|
|
|
+ }
|
|
|
+ }catch (err){
|
|
|
+ loading.close ()
|
|
|
+ await ElMessageBox.confirm('重命名失败,请选择其他货号重试',{
|
|
|
+ closeOnClickModal: false, // 点击遮罩层不关闭
|
|
|
+ closeOnPressEscape: false, // 按ESC键不关闭
|
|
|
+ showCancelButton: false, // 隐藏取消按钮
|
|
|
+ })
|
|
|
+ }finally {
|
|
|
+ loading.close ()
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+onMounted(() => {
|
|
|
+ fetchPhotoList(1, false);
|
|
|
+});
|
|
|
+</script>
|
|
|
+
|
|
|
+<template>
|
|
|
+ <div class="cutout-page">
|
|
|
+ <!-- 加载状态 -->
|
|
|
+ <div v-if="loading" class="loading-state">
|
|
|
+ <el-spin size="large" />
|
|
|
+ <p>正在加载拍照记录,请稍候...</p>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 错误状态 -->
|
|
|
+ <div v-else-if="error" class="error-state">
|
|
|
+ <el-alert
|
|
|
+ :title="'错误: ' + error"
|
|
|
+ type="error"
|
|
|
+ :closable="false"
|
|
|
+ />
|
|
|
+ <el-button @click="refreshData" type="primary" style="margin-top: 20px;">
|
|
|
+ 重新加载
|
|
|
+ </el-button>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 正常内容 -->
|
|
|
+ <div v-else>
|
|
|
+ <!-- 货号卡片列表 -->
|
|
|
+ <div class="product-cards-container">
|
|
|
+ <div
|
|
|
+ v-for="(photo, index) in photoList"
|
|
|
+ :key="`${photo.goods_art_no}-${index}`"
|
|
|
+ class="product-card"
|
|
|
+ :class="{ 'selected': isProductSelected(index) }"
|
|
|
+ >
|
|
|
+ <!-- 卡片头部 -->
|
|
|
+ <div class="card-header">
|
|
|
+ <div class="checkbox-wrapper">
|
|
|
+ <el-checkbox
|
|
|
+ :model-value="isProductSelected(index)"
|
|
|
+ @change="handleProductSelectionChange(index)"
|
|
|
+ ></el-checkbox>
|
|
|
+ </div>
|
|
|
+ <div class="card-info">
|
|
|
+ <span class="product-code">{{ photo.goods_art_no }}</span>
|
|
|
+ <span class="timestamp">{{ photo.action_time }}</span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 图片区域 -->
|
|
|
+ <div class="image-container">
|
|
|
+ <div class="image-row">
|
|
|
+ <div
|
|
|
+ v-for="(img, imgIndex) in photo.items"
|
|
|
+ :key="imgIndex"
|
|
|
+ class="image-item"
|
|
|
+ >
|
|
|
+ <el-image
|
|
|
+ :src="`data:image/jpg;base64,${img}`"
|
|
|
+ alt="产品图"
|
|
|
+ class="product-image"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 加载更多按钮 -->
|
|
|
+ <div class="load-more-container">
|
|
|
+ <el-button
|
|
|
+ v-if="hasNext"
|
|
|
+ :loading="loadingMore"
|
|
|
+ @click="loadMore"
|
|
|
+ type="primary"
|
|
|
+ plain
|
|
|
+ >
|
|
|
+ {{ loadingMore ? '加载中...' : '点击加载更多' }}
|
|
|
+ </el-button>
|
|
|
+ <div v-else class="no-more-data">
|
|
|
+ 已加载全部数据
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 底部按钮区域(固定在底部) -->
|
|
|
+ <div class="fixed-bottom-bar">
|
|
|
+ <div class="selected-info">
|
|
|
+ 已选择 <span class="selected-count">{{ selectedCount }}</span> 个货号
|
|
|
+ </div>
|
|
|
+ <el-button
|
|
|
+ type="primary"
|
|
|
+ @click="handleBatchCutout"
|
|
|
+ :disabled="selectedProducts.length === 0"
|
|
|
+ size="medium"
|
|
|
+ >
|
|
|
+ 批量修改名称
|
|
|
+ </el-button>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <el-dialog v-model="dialogTableVisible" title="重命名结果">
|
|
|
+ <el-table :data="output_folder">
|
|
|
+ <el-table-column property="goods_art_no" label="货号" width="150" />
|
|
|
+ <el-table-column property="path" label="操作" width="200" fixed="right">
|
|
|
+ <template #default="scope">
|
|
|
+ <el-button link type="primary" size="small" @click="OpenFolder(scope.row.path)">
|
|
|
+ 打开目录
|
|
|
+ </el-button>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ </el-table>
|
|
|
+ </el-dialog>
|
|
|
+</template>
|
|
|
+
|
|
|
+<style scoped>
|
|
|
+.cutout-page {
|
|
|
+ padding: 20px;
|
|
|
+ background-color: #f9f9f9;
|
|
|
+ min-height: 100vh;
|
|
|
+ padding-bottom: 10px; /* 为固定底部按钮留出空间 */
|
|
|
+}
|
|
|
+
|
|
|
+.product-cards-container {
|
|
|
+ display: grid;
|
|
|
+ grid-template-columns: repeat(auto-fit, minmax(48%, 1fr));
|
|
|
+ gap: 16px;
|
|
|
+ margin-bottom: 16px; /* 调整间距 */
|
|
|
+}
|
|
|
+
|
|
|
+/* 加载更多容器 */
|
|
|
+.load-more-container {
|
|
|
+ margin: 20px 0;
|
|
|
+ display: flex;
|
|
|
+ justify-content: center;
|
|
|
+ align-items: center;
|
|
|
+ padding-bottom: 80px; /* 为底部按钮留出空间 */
|
|
|
+}
|
|
|
+
|
|
|
+.no-more-data {
|
|
|
+ color: #999;
|
|
|
+ font-size: 14px;
|
|
|
+ padding: 10px;
|
|
|
+}
|
|
|
+
|
|
|
+/* 货号卡片 */
|
|
|
+.product-card {
|
|
|
+ background-color: white;
|
|
|
+ border-radius: 8px;
|
|
|
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
|
|
+ border: 1px solid #ddd;
|
|
|
+ overflow: hidden;
|
|
|
+ transition: all 0.3s ease;
|
|
|
+ min-width: 0;
|
|
|
+ width: 100%;
|
|
|
+}
|
|
|
+
|
|
|
+.product-card:hover {
|
|
|
+ transform: translateY(-2px);
|
|
|
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
|
|
|
+}
|
|
|
+
|
|
|
+.product-card.selected {
|
|
|
+ border-color: #409eff;
|
|
|
+ box-shadow: 0 0 0 2px rgba(64, 158, 255, 0.2);
|
|
|
+}
|
|
|
+
|
|
|
+/* 卡片头部 */
|
|
|
+.card-header {
|
|
|
+ padding: 12px 16px;
|
|
|
+ background-color: #eef2ff;
|
|
|
+ border-bottom: 1px solid #d9d9d9;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ gap: 12px;
|
|
|
+}
|
|
|
+
|
|
|
+.checkbox-wrapper {
|
|
|
+ width: 20px;
|
|
|
+ height: 20px;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+}
|
|
|
+
|
|
|
+.card-info {
|
|
|
+ flex: 1;
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ gap: 4px;
|
|
|
+}
|
|
|
+
|
|
|
+.product-code {
|
|
|
+ font-weight: bold;
|
|
|
+ color: #333;
|
|
|
+ font-size: 14px;
|
|
|
+}
|
|
|
+
|
|
|
+.timestamp {
|
|
|
+ color: #666;
|
|
|
+ font-size: 12px;
|
|
|
+}
|
|
|
+
|
|
|
+/* 图片容器 */
|
|
|
+.image-container {
|
|
|
+ padding: 16px;
|
|
|
+}
|
|
|
+
|
|
|
+.image-row {
|
|
|
+ display: flex;
|
|
|
+ gap: 8px;
|
|
|
+ overflow-x: auto;
|
|
|
+ padding: 8px 0;
|
|
|
+}
|
|
|
+
|
|
|
+.image-item {
|
|
|
+ position: relative;
|
|
|
+ border-radius: 4px;
|
|
|
+ overflow: hidden;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+}
|
|
|
+
|
|
|
+.product-image {
|
|
|
+ max-width: 100%;
|
|
|
+ max-height: 100%;
|
|
|
+ object-fit: contain;
|
|
|
+ padding: 8px;
|
|
|
+}
|
|
|
+
|
|
|
+/* 固定底部按钮栏 */
|
|
|
+.fixed-bottom-bar {
|
|
|
+ position: fixed;
|
|
|
+ bottom: 0;
|
|
|
+ left: 0;
|
|
|
+ right: 0;
|
|
|
+ padding: 16px 20px;
|
|
|
+ background-color: white;
|
|
|
+ border-top: 1px solid #ddd;
|
|
|
+ box-shadow: 0 -2px 8px rgba(0, 0, 0, 0.1);
|
|
|
+ display: flex;
|
|
|
+ justify-content: space-between;
|
|
|
+ align-items: center;
|
|
|
+ z-index: 100;
|
|
|
+}
|
|
|
+
|
|
|
+.selected-info {
|
|
|
+ color: #666;
|
|
|
+ font-size: 14px;
|
|
|
+}
|
|
|
+
|
|
|
+.selected-count {
|
|
|
+ color: #409eff;
|
|
|
+ font-weight: bold;
|
|
|
+}
|
|
|
+
|
|
|
+.el-button {
|
|
|
+ padding: 12px 24px;
|
|
|
+ font-size: 16px;
|
|
|
+}
|
|
|
+
|
|
|
+/* 加载状态 */
|
|
|
+.loading-state {
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ padding: 40px 20px;
|
|
|
+ text-align: center;
|
|
|
+}
|
|
|
+
|
|
|
+/* 错误状态 */
|
|
|
+.error-state {
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ padding: 40px 20px;
|
|
|
+ text-align: center;
|
|
|
+}
|
|
|
+</style>
|