Commit 1cb39071 by 焦子成

j

parent 3344c4a5
File added
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
// Excel处理Worker
// 使用本地XLSX库
importScripts('./xlsx.full.min.js');
self.onmessage = function(e) {
try {
const { data, type, neededColumns } = e.data;
if (type === 'parseExcel') {
const result = parseExcelData(data, neededColumns);
self.postMessage({
type: 'success',
data: result
});
}
} catch (error) {
console.error('Worker error:', error);
self.postMessage({
type: 'error',
error: error.message || '未知错误'
});
}
};
function parseExcelData(arrayBuffer, neededColumns = null) {
try {
if (!arrayBuffer) {
throw new Error('没有接收到数据');
}
const data = new Uint8Array(arrayBuffer);
const workbook = XLSX.read(data, {
type: 'array',
cellDates: true,
cellNF: false,
cellStyles: false,
cellHTML: false,
cellFormula: false,
cellText: false
});
if (!workbook.SheetNames || workbook.SheetNames.length === 0) {
throw new Error('Excel文件中没有找到工作表');
}
const sheetName = workbook.SheetNames[0];
const worksheet = workbook.Sheets[sheetName];
if (!worksheet) {
throw new Error('无法读取工作表数据');
}
// 限制最大行数,防止内存溢出
const maxRows = 100000; // 增加到10万行
const range = XLSX.utils.decode_range(worksheet['!ref'] || 'A1');
if (range.e.r > maxRows) {
range.e.r = maxRows - 1;
worksheet['!ref'] = XLSX.utils.encode_range(range);
}
const jsonData = XLSX.utils.sheet_to_json(worksheet, {
header: 1,
defval: '',
blankrows: false
});
if (!jsonData || jsonData.length === 0) {
throw new Error('Excel文件中没有数据');
}
// 转换为对象数组
const headers = jsonData[0];
if (!headers || headers.length === 0) {
throw new Error('Excel文件中没有列标题');
}
const rows = jsonData.slice(1).map(row => {
const obj = {};
headers.forEach((header, index) => {
obj[header] = row[index] || '';
});
return obj;
});
// 如果指定了需要的列,则只保留这些列
if (neededColumns && neededColumns.length > 0) {
return rows.map(row => {
const optimizedRow = {};
neededColumns.forEach(col => {
optimizedRow[col] = row[col] || '';
});
return optimizedRow;
});
}
return rows;
} catch (error) {
console.error('Excel解析错误:', error);
throw new Error('Excel解析失败: ' + error.message);
}
}
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>文件下载器 - 类似迅雷的下载工具</title>
<script type="module" crossorigin src="/assets/index-4ea3f23e.js"></script>
<link rel="stylesheet" href="/assets/index-1cc07315.css">
</head>
<body>
<div id="app"></div>
</body>
</html>
......@@ -349,13 +349,22 @@
</template>
</el-table-column> -->
<el-table-column label="大小" width="120" align="center" prop="fileLength">
<!-- <el-table-column label="大小" width="120" align="center" prop="fileLength">
<template #default="{ row }">
<span v-if="row.totalBytes > 0" class="size-info">
{{ formatBytes(row.downloadedBytes) }} / {{ formatBytes(row.totalBytes) }}
</span>
<span v-else class="size-info">-</span>
</template>
</el-table-column> -->
<el-table-column label="大小" width="120" align="center">
<template #default="{ row }">
<span v-if="row.fileSize" class="size-info">
<!-- {{ formatBytes(row.downloadedBytes) }} / {{ formatBytes(row.totalBytes) }} -->
{{ row.fileSize }}
</span>
<span v-else class="size-info">-</span>
</template>
</el-table-column>
<el-table-column label="操作" width="200" align="center" fixed="right">
......@@ -543,11 +552,18 @@ const selectExcelFile = async (fileId) => {
excelColumns.value = res.data.fileColumnNameAll || []
columnMapping.value.fileNameColumns = res.data.fileColumnName || []
columnMapping.value.url = res.data.urlColumnName
rawExcelData.value = res.data.details || []
if (res.data.details.length > 5) {
previewData.value = res.data.details.slice(0, 5)
var list = []
for (const element of res.data.details) {
list.push({
fileName: element.fileName,
url: element.fileUrl
})
}
rawExcelData.value = list || []
if (list.length > 5) {
previewData.value = list.slice(0, 5)
} else {
previewData.value = res.data.details || []
previewData.value = list || []
}
customSubFolder.value = res.data.filePrefix || ''
} else {
......@@ -689,7 +705,7 @@ const optimizeDataAfterColumnMapping = () => {
// 重新生成预览数据
generatePreviewData()
console.log(`数据优化完成:从 ${Object.keys(originalData[0] || {}).length} 个字段优化到 ${Object.keys(optimizedData[0] || {}).length} 个字段`)
// console.log(`数据优化完成:从 ${Object.keys(originalData[0] || {}).length} 个字段优化到 ${Object.keys(optimizedData[0] || {}).length} 个字段`)
}
// 生成预览数据
......@@ -941,8 +957,8 @@ function deleteRow(row) {
// 解析Excel文件
const parseExcelFile = async () => {
if (rawExcelData.value.length > 3000) {
ElMessage.error('文件数据量太大,请拆分处理,每次不超过3000条')
if (rawExcelData.value.length > 10000) {
ElMessage.error('文件数据量太大,请拆分处理,每次不超过10000条')
return
}
if (!canParse.value) {
......@@ -1153,7 +1169,7 @@ function uploadDetailsFile() {
uplist = detailList
detailList = []
}
console.log('list-->', detailList.length)
// console.log('list-->', detailList.length)
http.post(config.fileUploadDetail, {
batchId: upDetailId,
details: uplist
......@@ -1163,6 +1179,7 @@ function uploadDetailsFile() {
uploadDetailsFile()
} else {
ElMessage.success('上传任务完成')
loadUpTableData()
loadDetailTableData()
}
}
......
......@@ -48,20 +48,20 @@
<div class="card-header">
<span>历史记录</span>
<div class="header-actions">
<el-select v-model="statusFilter" placeholder="状态筛选" size="small" style="width: 120px;">
<el-option label="全部" value="" />
<el-option label="已完成" :value="3" />
<el-option label="失败" :value="4" />
<el-option label="暂停" :value="2" />
<el-select v-model="statusFilter" placeholder="状态筛选" size="small" style="width: 120px;" @change="statusChange">
<el-option label="全部" value="all" />
<el-option label="已完成" value="completed" />
<el-option label="失败" value="error" />
<el-option label="暂停" value="paused" />
</el-select>
<el-select v-model="excelFileFilter" placeholder="Excel文件筛选" size="small"
style="width: 150px; margin-left: 10px;">
style="width: 150px; margin-left: 10px;" @change="excelFileFilterChange">
<el-option label="全部Excel文件" value="" />
<el-option v-for="excelFile in excelFileFilterList" :key="excelFile" :label="excelFile"
:value="excelFile" />
</el-select>
<el-input v-model="searchKeyword" placeholder="搜索文件名或Excel文件" size="small"
style="width: 200px; margin-left: 10px;" clearable>
style="width: 200px; margin-left: 10px;" clearable @change="searchKeywordChange">
<template #prefix>
<el-icon>
<Search />
......@@ -114,7 +114,7 @@
</template>
</el-table-column>
<el-table-column prop="progress" label="进度" width="120">
<!-- <el-table-column prop="progress" label="进度" width="120">
<template #default="scope">
<div v-if="scope.row.status === 'completed'">
<el-progress :percentage="100" status="success" />
......@@ -126,17 +126,19 @@
<el-progress :percentage="scope.row.progress || 0" />
</div>
</template>
</el-table-column>
</el-table-column> -->
<el-table-column prop="fileSize" label="文件大小" width="120">
<template #default="scope">
{{ formatFileSize(scope.row.fileSize) }}
<!-- {{ formatFileSize(scope.row.fileSize) }} -->
{{ scope.row.fileSize }}
</template>
</el-table-column>
<el-table-column prop="downloadedBytes" label="已下载" width="120">
<template #default="scope">
{{ formatFileSize(scope.row.downloadedBytes) }}
<!-- {{ formatFileSize(scope.row.downloadedBytes) }} -->
{{ scope.row.fileSize }}
</template>
</el-table-column>
......@@ -201,13 +203,14 @@ import { Clock, Search } from '@element-plus/icons-vue'
import { useAuthStore } from '../stores/auth'
import http from '@/utils/request.js';
import config from '@/api/api.js';
import { ca } from 'element-plus/es/locales.mjs'
const router = useRouter()
const authStore = useAuthStore()
// 状态
const historyData = ref([])
const statusFilter = ref('')
const statusFilter = ref('completed')
const excelFileFilter = ref('')
const searchKeyword = ref('')
const currentPage = ref(1)
......@@ -241,13 +244,19 @@ function laodFileAll(){
}
})
}
const statusFilterMap = {
'all': '',
'completed': 3,
'error': 4,
'paused': 2
}
// 加载历史数据
const loadHistory = () => {
// historyData.value = authStore.getDownloadHistory()
http.post(config.uploadDetailList, {
current: currentPage.value,
pageSize: pageSize.value,
fileStatus: statusFilter.value,
fileStatus: statusFilterMap[statusFilter.value],
uploadName: excelFileFilter.value,
fileName: searchKeyword.value
}).then(res => {
......@@ -306,6 +315,18 @@ function loadUploadDetailTotalNum(){
}
})
}
function statusChange(){
currentPage.value = 1
loadHistory()
}
function excelFileFilterChange(){
currentPage.value = 1
loadHistory()
}
function searchKeywordChange(){
currentPage.value = 1
loadHistory()
}
// 获取唯一的Excel文件列表
const uniqueExcelFiles = computed(() => {
......@@ -407,6 +428,7 @@ const getStatusText = (status) => {
case 'error': return '失败'
case 'paused': return '暂停'
case 'downloading': return '下载中'
case 'pending': return '等待中'
default: return '未知'
}
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment