|
|
@ -1,25 +1,181 @@ |
|
|
|
<template> |
|
|
|
<el-dialog :close-on-click-modal="false" :modal-append-to-body="false" append-to-body title="批量导入" :visible.sync="batchImportVisible"> |
|
|
|
<div class="setting-dialog" style="display: flex; justify-content: center; flex-direction: column; align-items: center;"> |
|
|
|
<p>注意:批量导入,需在指定的模板文件内完成数据录入后,上传文件,再由系统执行导入操作!</p> |
|
|
|
<div class="btn-wrap"> |
|
|
|
<el-button size="mini"> <i class="iconfont icon-xiazai" />下载模板</el-button> |
|
|
|
<el-button size="mini"> <i class="iconfont icon-piliangchengjian" />导入文件</el-button> |
|
|
|
<div> |
|
|
|
<el-dialog :close-on-click-modal="false" :modal-append-to-body="false" append-to-body title="批量导入" :visible.sync="batchImportVisible" :before-close="handleClose"> |
|
|
|
<div class="setting-dialog" style="display: flex; justify-content: center; flex-direction: column; align-items: center;"> |
|
|
|
<p>注意:批量导入,需在指定的模板文件内完成数据录入后,上传文件,再由系统执行导入操作!</p> |
|
|
|
<div class="btn-wrap"> |
|
|
|
<el-button size="mini"> <i class="iconfont icon-xiazai" />下载模板</el-button> |
|
|
|
<el-button size="mini" :loading="isParsing" @click="openFileDialog"> |
|
|
|
<i class="iconfont icon-piliangchengjian" />导入文件 |
|
|
|
</el-button> |
|
|
|
</div> |
|
|
|
<div style="display: flex; flex-direction: column; align-items: center;"> |
|
|
|
<input |
|
|
|
ref="fileInput" |
|
|
|
type="file" |
|
|
|
style="display: none" |
|
|
|
accept=".xlsx,.xls" |
|
|
|
@change="handleBatchImport" |
|
|
|
> |
|
|
|
<div v-if="fileNames" class="file-name">{{ fileNames }}</div> |
|
|
|
|
|
|
|
<!-- 文件解析状态提示 --> |
|
|
|
<div v-if="isParsing" class="parsing-status"> |
|
|
|
<span style="margin-left: 10px;">{{ parsingProgress }}% 正在解析文件,请稍候...</span> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
</el-dialog> |
|
|
|
|
|
|
|
<el-dialog :close-on-click-modal="false" :modal-append-to-body="false" append-to-body title="批量导入" :visible.sync="importPreviewVisible" :before-close="handleClose"> |
|
|
|
<div class="setting-dialog"> |
|
|
|
<el-table ref="table" highlight-current-row style="width: 100%;" height="calc(100vh - 330px)" :data="tableData"> |
|
|
|
<el-table-column type="index" align="center" width="55" /> |
|
|
|
<el-table-column prop="barcode" label="证号" /> |
|
|
|
<el-table-column prop="libcode" label="馆代码" /> |
|
|
|
<el-table-column prop="personName" label="姓名" /> |
|
|
|
<el-table-column prop="idcard" label="身份证" /> |
|
|
|
<el-table-column prop="personSex" label="性别" /> |
|
|
|
<el-table-column prop="personPhotoBase64" label="照片"> |
|
|
|
<template slot-scope="scope"> |
|
|
|
<img v-if="scope.row.personPhotoBase64" :src="scope.row.personPhotoBase64" style="width: 100px; height: 100px;"> |
|
|
|
<img v-else src="~@/assets/images/cover-bg.png" style="width: 100px; height: 100px;"> |
|
|
|
</template> |
|
|
|
</el-table-column> |
|
|
|
<el-table-column label="操作" align="center" prop="columnStatus" width="240"> |
|
|
|
<template slot-scope="scope"> |
|
|
|
<el-button size="mini" style="padding: 5px;" @click="handleDeleteRow(scope.row)"> |
|
|
|
<i class="iconfont icon-shanchu1" /> |
|
|
|
删除 |
|
|
|
</el-button> |
|
|
|
</template> |
|
|
|
</el-table-column> |
|
|
|
</el-table> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
</el-dialog> |
|
|
|
<div slot="footer" class="dialog-footer"> |
|
|
|
<el-button type="text" @click="handleClose">取消</el-button> |
|
|
|
<el-button :loading="btnLoading" type="primary" @click="handleComfired">确认</el-button> |
|
|
|
</div> |
|
|
|
</el-dialog> |
|
|
|
</div> |
|
|
|
</template> |
|
|
|
|
|
|
|
<script> |
|
|
|
import { upload } from '@/utils/upload' |
|
|
|
export default { |
|
|
|
data() { |
|
|
|
return { |
|
|
|
batchImportVisible: false |
|
|
|
batchImportVisible: false, |
|
|
|
importPreviewVisible: false, |
|
|
|
tableData: [], |
|
|
|
btnLoading: false, |
|
|
|
file: null, |
|
|
|
fileNames: '', |
|
|
|
filePath: '', |
|
|
|
isParsing: false, // 解析状态 |
|
|
|
parsingProgress: 0, // 解析进度 |
|
|
|
progressTimer: null // 进度计时器 |
|
|
|
} |
|
|
|
}, |
|
|
|
mounted() { |
|
|
|
beforeDestroy() { |
|
|
|
if (this.progressTimer) { |
|
|
|
clearInterval(this.progressTimer) |
|
|
|
} |
|
|
|
}, |
|
|
|
methods: { |
|
|
|
openFileDialog() { |
|
|
|
this.$refs.fileInput.value = '' |
|
|
|
this.$refs.fileInput.click() |
|
|
|
}, |
|
|
|
updateProgress() { |
|
|
|
this.progressTimer = setInterval(() => { |
|
|
|
if (this.parsingProgress < 90) { |
|
|
|
this.parsingProgress += Math.floor(Math.random() * 5) + 1 |
|
|
|
if (this.parsingProgress > 90) { |
|
|
|
this.parsingProgress = 90 |
|
|
|
} |
|
|
|
} |
|
|
|
}, 500) |
|
|
|
}, |
|
|
|
handleBatchImport(e) { |
|
|
|
if (!e.target.files || e.target.files.length === 0) { |
|
|
|
this.$message.warning('请选择要上传的文件') |
|
|
|
return |
|
|
|
} |
|
|
|
|
|
|
|
this.file = e.target.files[0] |
|
|
|
this.fileNames = this.file.name |
|
|
|
|
|
|
|
const fileExtension = this.file.name.split('.').pop().toLowerCase() |
|
|
|
if (!['xlsx', 'xls'].includes(fileExtension)) { |
|
|
|
this.$message.error('请上传Excel文件(.xlsx或.xls格式)') |
|
|
|
this.file = null |
|
|
|
this.fileNames = '' |
|
|
|
return |
|
|
|
} |
|
|
|
|
|
|
|
this.isParsing = true |
|
|
|
this.parsingProgress = 0 |
|
|
|
this.updateProgress() |
|
|
|
|
|
|
|
upload(this.baseApi + '/api/person/previewFileInfo', this.file).then(res => { |
|
|
|
clearInterval(this.progressTimer) |
|
|
|
console.log(res) |
|
|
|
console.log('res.data.data', res.data.data) |
|
|
|
|
|
|
|
if (res.data.code === 200) { |
|
|
|
this.parsingProgress = 100 |
|
|
|
setTimeout(() => { |
|
|
|
this.isParsing = false |
|
|
|
this.parsingProgress = 0 |
|
|
|
}, 500) |
|
|
|
|
|
|
|
this.batchImportVisible = false |
|
|
|
this.importPreviewVisible = true |
|
|
|
this.tableData = res.data.data || [] |
|
|
|
} else { |
|
|
|
this.isParsing = false |
|
|
|
this.parsingProgress = 0 |
|
|
|
this.$message({ message: res.data.message || '文件解析失败', type: 'error', offset: 8 }) |
|
|
|
} |
|
|
|
}).catch(error => { |
|
|
|
clearInterval(this.progressTimer) |
|
|
|
this.isParsing = false |
|
|
|
this.parsingProgress = 0 |
|
|
|
|
|
|
|
console.error('上传失败', error) |
|
|
|
this.$message({ message: '文件上传失败,请重试', type: 'error', offset: 8 }) |
|
|
|
}) |
|
|
|
}, |
|
|
|
handleDeleteRow(currentRow) { |
|
|
|
this.$confirm('此操作将删除当前所选' + this.crud.title + '<span>你是否还要继续?</span>', '提示', { |
|
|
|
confirmButtonText: '确定', |
|
|
|
cancelButtonText: '取消', |
|
|
|
type: 'warning' |
|
|
|
}).then(() => { |
|
|
|
this.tableData = this.tableData.filter( |
|
|
|
item => item.barcode !== currentRow.barcode |
|
|
|
) |
|
|
|
this.$message({ message: '删除成功', type: 'success', offset: 8 }) |
|
|
|
}).catch(() => { |
|
|
|
this.$message({ message: '取消删除', type: 'info', offset: 8 }) |
|
|
|
}) |
|
|
|
}, |
|
|
|
handleComfired() { |
|
|
|
|
|
|
|
}, |
|
|
|
handleClose() { |
|
|
|
this.batchImportVisible = false |
|
|
|
this.importPreviewVisible = false |
|
|
|
|
|
|
|
this.file = null |
|
|
|
this.fileNames = '' |
|
|
|
|
|
|
|
clearInterval(this.progressTimer) |
|
|
|
this.isParsing = false |
|
|
|
this.parsingProgress = 0 |
|
|
|
this.tableData = [] |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
</script> |
|
|
@ -27,5 +183,26 @@ export default { |
|
|
|
<style lang="scss" scoped> |
|
|
|
.btn-wrap{ |
|
|
|
padding: 30px 0 20px 0; |
|
|
|
display: flex; |
|
|
|
gap: 15px; |
|
|
|
align-items: center; |
|
|
|
} |
|
|
|
|
|
|
|
.file-name { |
|
|
|
color: #666; |
|
|
|
font-size: 14px; |
|
|
|
max-width: 340px; |
|
|
|
white-space: nowrap; |
|
|
|
overflow: hidden; |
|
|
|
text-overflow: ellipsis; |
|
|
|
margin-bottom: 10px; |
|
|
|
} |
|
|
|
|
|
|
|
.parsing-status { |
|
|
|
display: flex; |
|
|
|
align-items: center; |
|
|
|
margin-top: 15px; |
|
|
|
color: #666; |
|
|
|
font-size: 14px; |
|
|
|
} |
|
|
|
</style> |