u
This commit is contained in:
1 parent
f9eaacf02a
commit
69eda8b8ad
27 files changed
+2797
-616
No files matched your search
@@ -1,4 +1,8 @@
|
||||
<script lang="js" setup>
|
||||
import G3ContainerFile from "@/components/g3-container-file/index.vue";
|
||||
import HighDownloadDialog from "./high-download-dialog.vue";
|
||||
import UpdateDialog from "./update-dialog.vue";
|
||||
|
||||
import {
|
||||
deleteFileApi,
|
||||
loadDataApi,
|
||||
@@ -6,16 +10,16 @@ import {
|
||||
loadViewColumnsApi,
|
||||
saveObjectApi,
|
||||
} from "@/request/api";
|
||||
import { getAlignByFormat, formatValueByFormat } from "@/utils/columns";
|
||||
import { formatValueByFormat } from "@/utils/columns";
|
||||
import { updateViewTableColumns } from "@/utils/columns";
|
||||
import { downloadZip, getAliyunFileBlob } from "@/utils/file";
|
||||
import { downloadZip, getFileBlob } from "@/utils/file";
|
||||
import { formatToDate } from "@/utils/time";
|
||||
import { ElLoading, ElMessage } from "element-plus";
|
||||
import { saveAs } from "file-saver";
|
||||
import JSZip from "jszip";
|
||||
import { usePermissionStore } from "@/store/permission";
|
||||
import { ExportVxeTableExcel, exportExcel } from "@/utils/excel";
|
||||
import HighDownloadDialog from "./high-download-dialog.vue";
|
||||
import { ExportVxeTableExcel } from "@/utils/excel";
|
||||
import { buildPublicUrl } from "@/utils/file";
|
||||
|
||||
const viewName = "v_container";
|
||||
|
||||
@@ -32,6 +36,7 @@ const loading = reactive({
|
||||
});
|
||||
|
||||
const showHighDownload = ref(false);
|
||||
const showUpdate = ref(false);
|
||||
|
||||
const searchForm = ref({
|
||||
startTime: "",
|
||||
@@ -130,6 +135,14 @@ async function loadTableDatas() {
|
||||
orderField: "b_inputdatetime DESC",
|
||||
}).then((res) => {
|
||||
if (res.success) {
|
||||
console.log(res.data.rows);
|
||||
|
||||
res.data.rows.forEach((row) => {
|
||||
if (row.b_container_img) {
|
||||
row.b_container_img = buildPublicUrl(row.b_container_img);
|
||||
}
|
||||
});
|
||||
|
||||
tableData.value = res.data.rows;
|
||||
pagination.total = res.data.total;
|
||||
|
||||
@@ -204,9 +217,7 @@ async function deleteRows(rows = []) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (const file of fileRes.data) {
|
||||
await deleteFileApi(file.subid);
|
||||
}
|
||||
await Promise.all(fileRes.data.map((file) => deleteFileApi(file.subid)));
|
||||
|
||||
const requestData = [
|
||||
{
|
||||
@@ -267,6 +278,12 @@ function handleFileShow(data) {
|
||||
showFile.value = true;
|
||||
}
|
||||
|
||||
function handleUpdateShow(data) {
|
||||
currentRow.value = data;
|
||||
|
||||
showUpdate.value = true;
|
||||
}
|
||||
|
||||
async function handleDownloadOne(data) {
|
||||
const loading = ElLoading.service({
|
||||
lock: true,
|
||||
@@ -342,29 +359,55 @@ async function handleDownloadBatch() {
|
||||
let finished = 0;
|
||||
let totalFiles = 0;
|
||||
|
||||
// 1. 收集所有下载任务
|
||||
const allTasks = [];
|
||||
|
||||
// ✅ 关键:箱号计数器
|
||||
const containerCountMap = new Map();
|
||||
|
||||
for (const item of records) {
|
||||
const fileRes = await loadDataApi("bf_file", `father='${item.b_id}'`, "mx_xh asc");
|
||||
|
||||
const files = (fileRes.success && fileRes.data) || [];
|
||||
totalFiles += files.length;
|
||||
|
||||
// 按 年/月/日/集装箱号 生成层级文件夹
|
||||
const ymdFolderName = formatToDate(item.b_inputdatetime, "YYYY/MM/DD"); // 2026/03/27
|
||||
const containerFolderName = item.b_container_no;
|
||||
// =========================
|
||||
// ✅ 箱号文件夹去重逻辑
|
||||
// =========================
|
||||
const containerNo = item.b_container_no || "未知箱号";
|
||||
|
||||
const count = containerCountMap.get(containerNo) || 0;
|
||||
|
||||
let containerFolderName = containerNo;
|
||||
|
||||
if (count === 1) {
|
||||
containerFolderName = `${containerNo}_01`;
|
||||
} else if (count > 1) {
|
||||
containerFolderName = `${containerNo}_${String(count - 1).padStart(2, "0")}`;
|
||||
}
|
||||
|
||||
containerCountMap.set(containerNo, count + 1);
|
||||
|
||||
// =========================
|
||||
// 日期文件夹
|
||||
// =========================
|
||||
const ymdFolderName = formatToDate(item.b_inputdatetime, "YYYY/MM/DD");
|
||||
|
||||
let folder = zip.folder(ymdFolderName);
|
||||
folder = folder ? folder.folder(containerFolderName) : zip.folder(containerFolderName);
|
||||
|
||||
// =========================
|
||||
// 收集任务
|
||||
// =========================
|
||||
files.forEach((file, idx) => {
|
||||
allTasks.push(async () => {
|
||||
try {
|
||||
const blob = await getAliyunFileBlob(file.mx_mapfilename);
|
||||
const fileName =
|
||||
buildFileName(item.b_container_no, idx + 1, file.mx_filename) || "未命名文件";
|
||||
const blob = await getFileBlob(file.mx_mapfilename);
|
||||
|
||||
const fileName = buildFileName(containerNo, idx + 1, file.mx_filename) || "未命名文件";
|
||||
|
||||
folder.file(fileName, blob);
|
||||
} catch (e) {
|
||||
console.error(item.b_container_no + "下载失败:", file.mx_mapfilename, e);
|
||||
console.error(containerNo + "下载失败:", file.mx_mapfilename, e);
|
||||
} finally {
|
||||
finished++;
|
||||
loading.setText(`正在下载 ${finished}/${totalFiles} 个文件...`);
|
||||
@@ -373,23 +416,25 @@ async function handleDownloadBatch() {
|
||||
});
|
||||
}
|
||||
|
||||
// 2. 并发执行下载任务,限制同时 3 个
|
||||
// =========================
|
||||
// 并发执行(限制3个)
|
||||
// =========================
|
||||
await runWithLimit(allTasks, 3);
|
||||
|
||||
loading.setText("正在生成压缩包...");
|
||||
|
||||
const content = await zip.generateAsync({ type: "blob" });
|
||||
|
||||
// 3. 保存压缩包
|
||||
saveAs(content, "批量下载");
|
||||
|
||||
ElMessage.success("下载完成");
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
ElMessage.error("下载失败");
|
||||
} finally {
|
||||
loading.close();
|
||||
}
|
||||
}
|
||||
|
||||
function buildFileName(containerNo, index, fileName) {
|
||||
const formattedIndex = String(index).padStart(2, "0");
|
||||
|
||||
@@ -575,29 +620,59 @@ function buildFileName(containerNo, index, fileName) {
|
||||
</vxe-column>
|
||||
<vxe-column width="220" align="center" fixed="right" title="操作">
|
||||
<template #default="{ row }">
|
||||
<el-button
|
||||
link
|
||||
type="primary"
|
||||
@click="handleDownloadOne(row)"
|
||||
:disabled="!permissionStore.hasActionPermission(1)"
|
||||
>
|
||||
<el-icon class="el-icon--left">
|
||||
<G3Icon icon="lucide:cloud-download" />
|
||||
</el-icon>
|
||||
下载
|
||||
</el-button>
|
||||
<el-button
|
||||
link
|
||||
type="primary"
|
||||
@click="handleFileShow(row)"
|
||||
:disabled="!permissionStore.hasActionPermission(3)"
|
||||
>
|
||||
<el-icon class="el-icon--left">
|
||||
<G3Icon icon="lucide:file-image" />
|
||||
</el-icon>
|
||||
图片
|
||||
</el-button>
|
||||
<el-button
|
||||
<div style="display: flex; align-items: center; justify-content: center">
|
||||
<el-button
|
||||
link
|
||||
type="primary"
|
||||
@click="handleDownloadOne(row)"
|
||||
:disabled="!permissionStore.hasActionPermission(1)"
|
||||
>
|
||||
<el-icon class="el-icon--left">
|
||||
<G3Icon icon="lucide:cloud-download" />
|
||||
</el-icon>
|
||||
下载
|
||||
</el-button>
|
||||
<el-button
|
||||
link
|
||||
type="primary"
|
||||
@click="handleFileShow(row)"
|
||||
:disabled="!permissionStore.hasActionPermission(3)"
|
||||
>
|
||||
<el-icon class="el-icon--left">
|
||||
<G3Icon icon="lucide:file-image" />
|
||||
</el-icon>
|
||||
图片
|
||||
</el-button>
|
||||
<el-dropdown>
|
||||
<el-button link type="primary" style="margin-left: 8px">
|
||||
<el-icon class="el-icon--left">
|
||||
<G3Icon icon="lucide:circle-ellipsis" />
|
||||
</el-icon>
|
||||
更多
|
||||
</el-button>
|
||||
<template #dropdown>
|
||||
<el-dropdown-menu>
|
||||
<el-dropdown-item @click="handleUpdateShow(row)">
|
||||
<el-icon class="el-icon--left">
|
||||
<G3Icon icon="lucide:refresh-ccw" />
|
||||
</el-icon>
|
||||
更新
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item
|
||||
@click="handleDeleteRow(row)"
|
||||
:disabled="!permissionStore.hasActionPermission(2)"
|
||||
>
|
||||
<el-icon class="el-icon--left">
|
||||
<G3Icon icon="lucide:trash-2" />
|
||||
</el-icon>
|
||||
删除
|
||||
</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</template>
|
||||
</el-dropdown>
|
||||
</div>
|
||||
|
||||
<!-- <el-button
|
||||
link
|
||||
type="danger"
|
||||
@click="handleDeleteRow(row)"
|
||||
@@ -607,7 +682,7 @@ function buildFileName(containerNo, index, fileName) {
|
||||
<G3Icon icon="lucide:trash-2" />
|
||||
</el-icon>
|
||||
删除
|
||||
</el-button>
|
||||
</el-button> -->
|
||||
</template>
|
||||
</vxe-column>
|
||||
</vxe-table>
|
||||
@@ -634,14 +709,16 @@ function buildFileName(containerNo, index, fileName) {
|
||||
@close="handlePreviewClose"
|
||||
/>
|
||||
|
||||
<G3File
|
||||
<G3ContainerFile
|
||||
v-model="showFile"
|
||||
:father="currentRow.b_id"
|
||||
module-id="b_container"
|
||||
:categories="fileCategories"
|
||||
:container-no="currentRow.b_container_no"
|
||||
/>
|
||||
|
||||
<HighDownloadDialog v-model="showHighDownload" />
|
||||
<UpdateDialog v-model="showUpdate" :data="currentRow" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
Reference in new issue
Block a user