refactor: 抽离导入结果弹窗为通用组件并适配所有导入页面

新增组件:
- ImportResultDialog.vue: 通用导入结果弹窗组件
  * 支持HTML内容渲染
  * 60vh高度限制,内容独立滚动
  * 美化滚动条样式(6px宽度、圆角设计)
  * 提供visible、content、title等props配置

适配页面:
1. 员工信息管理页面 (ccdiEmployee)
   - 使用ImportResultDialog组件替代内嵌Dialog
   - 简化数据状态管理(importResultVisible、importResultContent)
   - 添加handleImportResultClose方法处理关闭事件

2. 员工招聘信息页面 (ccdiStaffRecruitment)
   - 使用ImportResultDialog替代$modal.msgSuccess/msgError
   - 统一导入结果展示方式
   - 支持HTML格式的错误列表展示

3. 中介黑名单导入组件 (ccdiIntermediary/ImportDialog)
   - 使用ImportResultDialog替代$msgbox
   - 保留原有的消息解析逻辑(成功/失败分类处理)
   - 移除内联样式,使用组件样式

优势:
- 统一导入结果展示样式和交互体验
- 组件复用,减少代码重复
- 便于维护和扩展(一处修改,全局生效)
- 自适应滚动,支持大量失败数据展示

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
wkc
2026-02-05 16:31:01 +08:00
parent bb0e0b5dc9
commit 9aa3faf452
4 changed files with 172 additions and 73 deletions

View File

@@ -0,0 +1,108 @@
<template>
<el-dialog
:title="title"
:visible.sync="dialogVisible"
:width="width"
:append-to-body="appendToBody"
:close-on-click-modal="closeOnClickModal"
@close="handleClose"
class="import-result-dialog-wrapper"
>
<div class="import-result-content" v-html="content"></div>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="handleClose"> </el-button>
</div>
</el-dialog>
</template>
<script>
export default {
name: "ImportResultDialog",
props: {
// 控制弹窗显示/隐藏
visible: {
type: Boolean,
default: false
},
// 弹窗标题
title: {
type: String,
default: "导入结果"
},
// 导入结果内容支持HTML
content: {
type: String,
default: ""
},
// 弹窗宽度
width: {
type: String,
default: "700px"
},
// 是否插入到body元素上
appendToBody: {
type: Boolean,
default: true
},
// 是否可以通过点击modal关闭
closeOnClickModal: {
type: Boolean,
default: false
}
},
computed: {
dialogVisible: {
get() {
return this.visible;
},
set(val) {
this.$emit("update:visible", val);
}
}
},
methods: {
handleClose() {
this.dialogVisible = false;
this.$emit("close");
}
}
};
</script>
<style scoped>
/* 导入结果弹窗样式 */
.import-result-dialog-wrapper .import-result-content {
max-height: 60vh;
overflow-y: auto;
overflow-x: hidden;
padding: 10px 0;
line-height: 1.8;
font-size: 14px;
color: #606266;
}
/* 滚动条美化 - WebKit浏览器Chrome/Safari/Edge */
.import-result-dialog-wrapper .import-result-content::-webkit-scrollbar {
width: 6px;
}
.import-result-dialog-wrapper .import-result-content::-webkit-scrollbar-track {
background: #f5f7fa;
border-radius: 3px;
}
.import-result-dialog-wrapper .import-result-content::-webkit-scrollbar-thumb {
background: #c0c4cc;
border-radius: 3px;
}
.import-result-dialog-wrapper .import-result-content::-webkit-scrollbar-thumb:hover {
background: #909399;
}
/* Firefox滚动条 */
.import-result-dialog-wrapper .import-result-content {
scrollbar-width: thin;
scrollbar-color: #c0c4cc #f5f7fa;
}
</style>

View File

@@ -249,18 +249,12 @@
</el-dialog>
<!-- 导入结果对话框 -->
<el-dialog
:title="importResult.title"
:visible.sync="importResult.open"
width="700px"
append-to-body
class="import-result-dialog-wrapper"
>
<div class="import-result-content" v-html="importResult.content"></div>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="importResult.open = false"> </el-button>
</div>
</el-dialog>
<import-result-dialog
:visible.sync="importResultVisible"
:content="importResultContent"
title="导入结果"
@close="handleImportResultClose"
/>
</div>
</template>
@@ -270,6 +264,7 @@ import {deptTreeSelect} from "@/api/system/user";
import {getToken} from "@/utils/auth";
import Treeselect from "@riophae/vue-treeselect";
import "@riophae/vue-treeselect/dist/vue-treeselect.css";
import ImportResultDialog from "@/components/ImportResultDialog.vue";
// 身份证号校验正则
const idCardPattern = /^[1-9]\d{5}(18|19|20)\d{2}(0[1-9]|1[0-2])(0[1-9]|[12]\d|3[01])\d{3}[\dXx]$/;
@@ -278,7 +273,7 @@ const phonePattern = /^1[3|4|5|6|7|8|9][0-9]\d{8}$/;
export default {
name: "Employee",
components: { Treeselect },
components: { Treeselect, ImportResultDialog },
data() {
return {
// 遮罩层
@@ -362,11 +357,8 @@ export default {
url: process.env.VUE_APP_BASE_API + "/ccdi/employee/importData"
},
// 导入结果弹窗
importResult: {
open: false,
title: "导入结果",
content: ""
}
importResultVisible: false,
importResultContent: ""
};
},
created() {
@@ -522,8 +514,13 @@ export default {
this.upload.open = false;
this.getList();
// 显示导入结果弹窗
this.importResult.content = response.msg;
this.importResult.open = true;
this.importResultContent = response.msg;
this.importResultVisible = true;
},
// 导入结果弹窗关闭
handleImportResultClose() {
this.importResultVisible = false;
this.importResultContent = "";
},
// 提交上传文件
submitFileForm() {
@@ -651,42 +648,6 @@ export default {
font-size: 13px;
margin-right: 8px;
}
/* 导入结果弹窗样式 */
.import-result-dialog-wrapper .import-result-content {
max-height: 60vh;
overflow-y: auto;
overflow-x: hidden;
padding: 10px 0;
line-height: 1.8;
font-size: 14px;
color: #606266;
}
/* 滚动条美化 */
.import-result-dialog-wrapper .import-result-content::-webkit-scrollbar {
width: 6px;
}
.import-result-dialog-wrapper .import-result-content::-webkit-scrollbar-track {
background: #f5f7fa;
border-radius: 3px;
}
.import-result-dialog-wrapper .import-result-content::-webkit-scrollbar-thumb {
background: #c0c4cc;
border-radius: 3px;
}
.import-result-dialog-wrapper .import-result-content::-webkit-scrollbar-thumb:hover {
background: #909399;
}
/* Firefox滚动条 */
.import-result-dialog-wrapper .import-result-content {
scrollbar-width: thin;
scrollbar-color: #c0c4cc #f5f7fa;
}
</style>
<!-- 旧版MessageBox样式已废弃现使用Dialog组件 -->
<!-- 导入结果弹窗已抽离为独立组件 ImportResultDialog -->

View File

@@ -85,13 +85,23 @@
</el-button>
</div>
</el-dialog>
<!-- 导入结果对话框 -->
<import-result-dialog
:visible.sync="importResultVisible"
:content="importResultContent"
title="导入结果"
@close="handleImportResultClose"
/>
</template>
<script>
import {getToken} from "@/utils/auth";
import ImportResultDialog from "@/components/ImportResultDialog.vue";
export default {
name: "ImportDialog",
components: { ImportResultDialog },
props: {
visible: {
type: Boolean,
@@ -110,7 +120,10 @@ export default {
},
headers: { Authorization: "Bearer " + getToken() },
isUploading: false,
isFileSelected: false
isFileSelected: false,
// 导入结果弹窗
importResultVisible: false,
importResultContent: ""
};
},
computed: {
@@ -182,15 +195,16 @@ export default {
displayMessage = lines[0]; // 只取错误部分
}
this.$msgbox({
title: '导入结果',
dangerouslyUseHTMLString: true,
message: `<div style="overflow-y: auto; max-height: 60vh; padding-right: 10px; line-height: 1.6;">${displayMessage}</div>`,
confirmButtonText: '确定',
customClass: 'import-result-dialog'
});
// 显示导入结果弹窗
this.importResultContent = displayMessage;
this.importResultVisible = true;
this.$refs.upload.clearFiles();
},
// 导入结果弹窗关闭
handleImportResultClose() {
this.importResultVisible = false;
this.importResultContent = "";
},
handleFileError() {
this.isUploading = false;
this.$modal.msgError("导入失败,请检查文件格式是否正确");

View File

@@ -336,12 +336,21 @@
<el-button @click="upload.open = false" :disabled="upload.isUploading"> </el-button>
</div>
</el-dialog>
<!-- 导入结果对话框 -->
<import-result-dialog
:visible.sync="importResultVisible"
:content="importResultContent"
title="导入结果"
@close="handleImportResultClose"
/>
</div>
</template>
<script>
import { addStaffRecruitment, delStaffRecruitment, getStaffRecruitment, listStaffRecruitment, updateStaffRecruitment, importTemplate } from "@/api/ccdiStaffRecruitment";
import { getToken } from "@/utils/auth";
import ImportResultDialog from "@/components/ImportResultDialog.vue";
// 身份证号校验正则
const idCardPattern = /^[1-9]\d{5}(18|19|20)\d{2}(0[1-9]|1[0-2])(0[1-9]|[12]\d|3[01])\d{3}[\dXx]$/;
@@ -350,6 +359,7 @@ const gradPattern = /^((19|20)\d{2})(0[1-9]|1[0-2])$/;
export default {
name: "StaffRecruitment",
components: { ImportResultDialog },
data() {
return {
// 遮罩层
@@ -453,7 +463,10 @@ export default {
headers: { Authorization: "Bearer " + getToken() },
// 上传的地址
url: process.env.VUE_APP_BASE_API + "/ccdi/staffRecruitment/importData"
}
},
// 导入结果弹窗
importResultVisible: false,
importResultContent: ""
};
},
created() {
@@ -590,15 +603,18 @@ export default {
// 文件上传成功处理
handleFileSuccess(response, file, fileList) {
this.upload.isUploading = false;
if (response.code === 200) {
this.$modal.msgSuccess(response.msg);
this.upload.open = false;
this.getList();
} else {
this.$modal.msgError(response.msg);
}
this.upload.open = false;
this.getList();
// 显示导入结果弹窗
this.importResultContent = response.msg || response;
this.importResultVisible = true;
this.$refs.upload.clearFiles();
},
// 导入结果弹窗关闭
handleImportResultClose() {
this.importResultVisible = false;
this.importResultContent = "";
},
// 提交上传文件
submitFileForm() {
this.$refs.upload.submit();