feat: Excel导入支持多文件选择(Ctrl/Shift多选)+逐文件结果展示

This commit is contained in:
Hermes CI Fix
2026-07-13 15:04:08 +08:00
parent e7d581db59
commit 311f772ca9
2 changed files with 35 additions and 11 deletions
Binary file not shown.
+35 -11
View File
@@ -6,12 +6,15 @@
<el-tab-pane label="Excel导入" name="import">
<el-card>
<template #header>Excel导入</template>
<el-upload drag :auto-upload="false" :on-change="handleFile" accept=".xlsx,.xls" :limit="1">
<el-upload drag :auto-upload="false" :on-change="handleFile" :on-remove="handleRemove" multiple accept=".xlsx,.xls">
<el-icon :size="32"><UploadFilled /></el-icon>
<div>拖拽或点击上传Excel文件</div>
<div style="color:#999;font-size:12px;">支持 .xlsx .xls需包含 kpi_code, period, actual_value 三列</div>
<div style="color:#999;font-size:12px;">支持 .xlsx .xls可一次选择多个文件按住Ctrl/Shift多选</div>
</el-upload>
<el-button v-if="file" type="primary" style="margin-top:12px;" :loading="uploading" @click="doImport">导入数据</el-button>
<div v-if="files.length > 0" style="margin-top:8px;">
<el-tag v-for="(f, i) in files" :key="i" closable @close="removeFile(i)" style="margin:2px;">{{ f.name }}</el-tag>
</div>
<el-button v-if="files.length > 0" type="primary" style="margin-top:12px;" :loading="uploading" @click="doImport">导入 {{ files.length }} 个文件</el-button>
<div v-if="result" style="margin-top:12px;"><el-alert :title="result" type="success" show-icon /></div>
</el-card>
</el-tab-pane>
@@ -94,18 +97,39 @@ import MyDialog from '../components/MyDialog.vue'
const activeTab = ref('import')
// === Excel导入 ===
const file = ref<any>(null)
const files = ref<any[]>([])
const uploading = ref(false)
const result = ref('')
function handleFile(f: any) { file.value = f.raw }
function handleFile(f: any) {
// el-upload multiple 模式下每次 onChange 传单个文件
if (f.raw && !files.value.some(ex => ex.name === f.raw.name && ex.size === f.raw.size)) {
files.value.push(f.raw)
}
}
function handleRemove(f: any) {
files.value = files.value.filter(ex => !(ex.name === f.name && ex.size === f.size))
}
function removeFile(i: number) {
files.value.splice(i, 1)
}
async function doImport() {
if (!file.value) return
if (files.value.length === 0) return
uploading.value = true
try {
const r: any = await dataApi.importExcel(file.value)
result.value = r.message || '导入成功'
file.value = null
} catch (e) { ElMessage.error('导入失败') }
result.value = ''
const msgs: string[] = []
for (const f of files.value) {
try {
const r: any = await dataApi.importExcel(f)
const skipped = r.skipped || 0
const total = r.total || 0
msgs.push(`📄 ${f.name}: ${total}条导入${skipped > 0 ? `, ${skipped}条跳过` : ''}`)
} catch (e: any) {
msgs.push(`${f.name}: ${e?.response?.data?.detail || '导入失败'}`)
}
}
files.value = []
result.value = msgs.join('\n')
uploading.value = false
}