<template>
  <span><el-button v-if="isAdmin" type="primary" plain size="small" @click="visible=true"><el-icon><Upload /></el-icon>Excel 导入</el-button>
  <el-dialog v-model="visible" :title="`${title} · Excel 导入`" width="min(760px, 94vw)" append-to-body destroy-on-close @closed="reset">
    <div class="head"><div><strong>当前页面数据导入</strong><p>下载当前范围模板，填写后先预检，确认无误再写入。</p></div><el-button @click="download"><el-icon><Download /></el-icon>下载模板</el-button></div>
    <el-steps :active="result ? (result.error_count ? 1 : 2) : (file ? 1 : 0)" simple finish-status="success"><el-step title="选择文件"/><el-step title="预检"/><el-step title="确认导入"/></el-steps>
    <el-upload ref="upload" drag action="#" accept=".xlsx" :auto-upload="false" :limit="1" :on-change="change" :on-remove="reset"><el-icon class="upload-icon"><UploadFilled/></el-icon><div class="el-upload__text">拖入文件，或<em>点击选择</em></div></el-upload>
    <div v-if="result" class="result" :class="{error:result.error_count}"><div class="stats"><span>工作表 <b>{{result.sheet_count}}</b></span><span>数据行 <b>{{result.row_count}}</b></span><span>错误 <b>{{result.error_count}}</b></span><span>提示 <b>{{result.warning_count}}</b></span></div><el-table v-if="result.issues?.length" :data="result.issues.slice(0,8)" size="small" max-height="220"><el-table-column prop="sheet_name" label="工作表" width="120"/><el-table-column prop="row_number" label="行" width="55"/><el-table-column prop="column_name" label="列" width="130"/><el-table-column prop="message" label="问题"/></el-table><el-button v-if="result.error_count" text type="danger" @click="report">下载错误报告</el-button></div>
    <template #footer><el-button @click="visible=false">关闭</el-button><el-button v-if="!result||result.error_count" type="primary" :disabled="!file" :loading="loading" @click="precheck">开始预检</el-button><el-button v-else type="primary" :loading="loading" @click="commit">确认导入</el-button></template>
  </el-dialog></span>
</template>
<script setup>
import{ref}from'vue';import{ElMessage}from'element-plus';import{Download,Upload,UploadFilled}from'@element-plus/icons-vue';import{isAdmin as getIsAdmin}from'../utils/auth'
const props=defineProps({title:String,scopeKey:String});const emit=defineEmits(['success']);const isAdmin=getIsAdmin(),visible=ref(false),file=ref(null),result=ref(null),loading=ref(false),upload=ref(null)
const json=async(res)=>{const d=await res.json();if(!res.ok||d.status==='error')throw new Error(d.message||d.detail||'请求失败');return d.data};const save=(blob,name)=>{const u=URL.createObjectURL(blob),a=document.createElement('a');a.href=u;a.download=name;a.click();URL.revokeObjectURL(u)}
const download=async()=>save(await(await fetch(`/api/excel-import/template?scope_key=${encodeURIComponent(props.scopeKey)}`)).blob(),`${props.title}_导入模板.xlsx`);const change=f=>{file.value=f.raw;result.value=null};const reset=()=>{file.value=null;result.value=null;upload.value?.clearFiles()}
const precheck=async()=>{loading.value=true;try{const fd=new FormData();fd.append('file',file.value);result.value=await json(await fetch(`/api/excel-import/precheck?scope_key=${encodeURIComponent(props.scopeKey)}`,{method:'POST',body:fd}));ElMessage[result.value.error_count?'warning':'success'](result.value.error_count?'预检发现问题':'预检通过')}catch(e){ElMessage.error(e.message)}finally{loading.value=false}}
const commit=async()=>{loading.value=true;try{const d=await json(await fetch(`/api/excel-import/${result.value.batch_id}/commit`,{method:'POST'}));ElMessage.success(`导入成功：写入 ${d.imported_count} 条，跳过 ${d.skipped_count} 条`);visible.value=false;emit('success')}catch(e){ElMessage.error(e.message)}finally{loading.value=false}}
const report=async()=>save(await(await fetch(`/api/excel-import/batches/${result.value.batch_id}/error-report`)).blob(),`${props.title}_错误报告.xlsx`)
</script>
<style scoped>.head{display:flex;align-items:center;justify-content:space-between;margin-bottom:16px;padding:16px 18px;border-radius:18px;background:rgba(235,245,255,.72)}.head p{margin:5px 0 0;color:#71839a;font-size:13px}.el-steps{margin-bottom:16px}:deep(.el-upload),:deep(.el-upload-dragger){width:100%}:deep(.el-upload-dragger){min-height:150px;border-radius:18px}.upload-icon{margin-top:20px;font-size:38px;color:#75a2d2}.result{margin-top:16px;padding:16px;border-radius:18px;background:#eff8f5}.result.error{background:#fff3f3}.stats{display:grid;grid-template-columns:repeat(4,1fr);gap:10px;margin-bottom:12px}.stats span{padding:10px;border-radius:12px;background:#ffffffb8;color:#75859a}.stats b{display:block;margin-top:4px;font-size:20px;color:#263b55}</style>
