feat: Excel导入支持多文件选择(Ctrl/Shift多选)+逐文件结果展示
This commit is contained in:
Binary file not shown.
@@ -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
|
||||
result.value = ''
|
||||
const msgs: string[] = []
|
||||
for (const f of files.value) {
|
||||
try {
|
||||
const r: any = await dataApi.importExcel(file.value)
|
||||
result.value = r.message || '导入成功'
|
||||
file.value = null
|
||||
} catch (e) { ElMessage.error('导入失败') }
|
||||
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
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user