除员工外 取消导入更新
This commit is contained in:
@@ -52,11 +52,30 @@ export function importTemplate() {
|
||||
}
|
||||
|
||||
// 导入招聘信息
|
||||
export function importData(data, updateSupport) {
|
||||
export function importData(file) {
|
||||
const formData = new FormData()
|
||||
formData.append('file', file)
|
||||
return request({
|
||||
url: '/ccdi/staffRecruitment/importData?updateSupport=' + updateSupport,
|
||||
url: '/ccdi/staffRecruitment/importData',
|
||||
method: 'post',
|
||||
data: data
|
||||
data: formData
|
||||
})
|
||||
}
|
||||
|
||||
// 查询导入状态
|
||||
export function getImportStatus(taskId) {
|
||||
return request({
|
||||
url: '/ccdi/staffRecruitment/importStatus/' + taskId,
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
// 查询导入失败记录
|
||||
export function getImportFailures(taskId, pageNum, pageSize) {
|
||||
return request({
|
||||
url: '/ccdi/staffRecruitment/importFailures/' + taskId,
|
||||
method: 'get',
|
||||
params: { pageNum, pageSize }
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -81,6 +81,20 @@
|
||||
v-hasPermi="['ccdi:staffRecruitment:export']"
|
||||
>导出</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5" v-if="showFailureButton">
|
||||
<el-tooltip
|
||||
:content="getLastImportTooltip()"
|
||||
placement="top"
|
||||
>
|
||||
<el-button
|
||||
type="warning"
|
||||
plain
|
||||
icon="el-icon-warning"
|
||||
size="mini"
|
||||
@click="viewImportFailures"
|
||||
>查看导入失败记录</el-button>
|
||||
</el-tooltip>
|
||||
</el-col>
|
||||
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
|
||||
</el-row>
|
||||
|
||||
@@ -308,7 +322,7 @@
|
||||
</el-dialog>
|
||||
|
||||
<!-- 导入对话框 -->
|
||||
<el-dialog :title="upload.title" :visible.sync="upload.open" width="400px" append-to-body @close="handleImportDialogClose" v-loading="upload.isUploading" element-loading-text="正在导入数据,请稍候..." element-loading-spinner="el-icon-loading" element-loading-background="rgba(0, 0, 0, 0.7)">
|
||||
<el-dialog :title="upload.title" :visible.sync="upload.open" width="400px" append-to-body @close="handleImportDialogClose">
|
||||
<el-upload
|
||||
ref="upload"
|
||||
:limit="1"
|
||||
@@ -343,12 +357,59 @@
|
||||
title="导入结果"
|
||||
@close="handleImportResultClose"
|
||||
/>
|
||||
|
||||
<!-- 导入失败记录对话框 -->
|
||||
<el-dialog
|
||||
title="导入失败记录"
|
||||
:visible.sync="failureDialogVisible"
|
||||
width="1200px"
|
||||
append-to-body
|
||||
>
|
||||
<el-alert
|
||||
v-if="lastImportInfo"
|
||||
:title="lastImportInfo"
|
||||
type="info"
|
||||
:closable="false"
|
||||
style="margin-bottom: 15px"
|
||||
/>
|
||||
|
||||
<el-table :data="failureList" v-loading="failureLoading">
|
||||
<el-table-column label="招聘项目编号" prop="recruitId" align="center" width="150" />
|
||||
<el-table-column label="招聘项目名称" prop="recruitName" align="center" :show-overflow-tooltip="true"/>
|
||||
<el-table-column label="职位名称" prop="posName" align="center" :show-overflow-tooltip="true"/>
|
||||
<el-table-column label="候选人姓名" prop="candName" align="center" width="120"/>
|
||||
<el-table-column label="证件号码" prop="candId" align="center" width="180"/>
|
||||
<el-table-column label="失败原因" prop="errorMessage" align="center" min-width="200"
|
||||
:show-overflow-tooltip="true" />
|
||||
</el-table>
|
||||
|
||||
<pagination
|
||||
v-show="failureTotal > 0"
|
||||
:total="failureTotal"
|
||||
:page.sync="failureQueryParams.pageNum"
|
||||
:limit.sync="failureQueryParams.pageSize"
|
||||
@pagination="getFailureList"
|
||||
/>
|
||||
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button @click="failureDialogVisible = false">关闭</el-button>
|
||||
<el-button type="danger" plain @click="clearImportHistory">清除历史记录</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { addStaffRecruitment, delStaffRecruitment, getStaffRecruitment, listStaffRecruitment, updateStaffRecruitment, importTemplate } from "@/api/ccdiStaffRecruitment";
|
||||
import { getToken } from "@/utils/auth";
|
||||
import {
|
||||
addStaffRecruitment,
|
||||
delStaffRecruitment,
|
||||
getImportFailures,
|
||||
getImportStatus,
|
||||
getStaffRecruitment,
|
||||
listStaffRecruitment,
|
||||
updateStaffRecruitment
|
||||
} from "@/api/ccdiStaffRecruitment";
|
||||
import {getToken} from "@/utils/auth";
|
||||
import ImportResultDialog from "@/components/ImportResultDialog.vue";
|
||||
|
||||
// 身份证号校验正则
|
||||
@@ -463,11 +524,46 @@ export default {
|
||||
},
|
||||
// 导入结果弹窗
|
||||
importResultVisible: false,
|
||||
importResultContent: ""
|
||||
importResultContent: "",
|
||||
// 导入轮询定时器
|
||||
importPollingTimer: null,
|
||||
// 是否显示查看失败记录按钮
|
||||
showFailureButton: false,
|
||||
// 当前导入任务ID
|
||||
currentTaskId: null,
|
||||
// 失败记录对话框
|
||||
failureDialogVisible: false,
|
||||
failureList: [],
|
||||
failureLoading: false,
|
||||
failureTotal: 0,
|
||||
failureQueryParams: {
|
||||
pageNum: 1,
|
||||
pageSize: 10
|
||||
}
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
/**
|
||||
* 上次导入信息摘要
|
||||
*/
|
||||
lastImportInfo() {
|
||||
const savedTask = this.getImportTaskFromStorage();
|
||||
if (savedTask && savedTask.totalCount) {
|
||||
return `导入时间: ${this.parseTime(savedTask.saveTime)} | 总数: ${savedTask.totalCount}条 | 成功: ${savedTask.successCount}条 | 失败: ${savedTask.failureCount}条`;
|
||||
}
|
||||
return '';
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.getList();
|
||||
this.restoreImportState(); // 恢复导入状态
|
||||
},
|
||||
beforeDestroy() {
|
||||
// 清理定时器
|
||||
if (this.importPollingTimer) {
|
||||
clearInterval(this.importPollingTimer);
|
||||
this.importPollingTimer = null;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
/** 查询招聘信息列表 */
|
||||
@@ -601,11 +697,255 @@ export default {
|
||||
handleFileSuccess(response, file, fileList) {
|
||||
this.upload.isUploading = false;
|
||||
this.upload.open = false;
|
||||
this.getList();
|
||||
// 显示导入结果弹窗
|
||||
this.importResultContent = response.msg || response;
|
||||
this.importResultVisible = true;
|
||||
this.$refs.upload.clearFiles();
|
||||
|
||||
if (response.code === 200) {
|
||||
// 验证响应数据完整性
|
||||
if (!response.data || !response.data.taskId) {
|
||||
this.$modal.msgError('导入任务创建失败:缺少任务ID');
|
||||
this.upload.isUploading = false;
|
||||
this.upload.open = true;
|
||||
return;
|
||||
}
|
||||
|
||||
const taskId = response.data.taskId;
|
||||
|
||||
// 清除旧的轮询定时器
|
||||
if (this.importPollingTimer) {
|
||||
clearInterval(this.importPollingTimer);
|
||||
this.importPollingTimer = null;
|
||||
}
|
||||
|
||||
this.clearImportTaskFromStorage();
|
||||
|
||||
// 保存新任务的初始状态
|
||||
this.saveImportTaskToStorage({
|
||||
taskId: taskId,
|
||||
status: 'PROCESSING',
|
||||
timestamp: Date.now(),
|
||||
hasFailures: false
|
||||
});
|
||||
|
||||
// 重置状态
|
||||
this.showFailureButton = false;
|
||||
this.currentTaskId = taskId;
|
||||
|
||||
// 显示后台处理提示
|
||||
this.$notify({
|
||||
title: '导入任务已提交',
|
||||
message: '正在后台处理中,处理完成后将通知您',
|
||||
type: 'info',
|
||||
duration: 3000
|
||||
});
|
||||
|
||||
// 开始轮询检查状态
|
||||
this.startImportStatusPolling(taskId);
|
||||
} else {
|
||||
this.$modal.msgError(response.msg);
|
||||
}
|
||||
},
|
||||
/** 开始轮询导入状态 */
|
||||
startImportStatusPolling(taskId) {
|
||||
let pollCount = 0;
|
||||
const maxPolls = 150; // 最多轮询150次(5分钟)
|
||||
|
||||
this.importPollingTimer = setInterval(async () => {
|
||||
try {
|
||||
pollCount++;
|
||||
|
||||
// 超时检查
|
||||
if (pollCount > maxPolls) {
|
||||
clearInterval(this.importPollingTimer);
|
||||
this.$modal.msgWarning('导入任务处理超时,请联系管理员');
|
||||
return;
|
||||
}
|
||||
|
||||
const response = await getImportStatus(taskId);
|
||||
|
||||
if (response.data && response.data.status !== 'PROCESSING') {
|
||||
clearInterval(this.importPollingTimer);
|
||||
this.handleImportComplete(response.data);
|
||||
}
|
||||
} catch (error) {
|
||||
clearInterval(this.importPollingTimer);
|
||||
this.$modal.msgError('查询导入状态失败: ' + error.message);
|
||||
}
|
||||
}, 2000); // 每2秒轮询一次
|
||||
},
|
||||
/** 处理导入完成 */
|
||||
handleImportComplete(statusResult) {
|
||||
// 更新localStorage中的任务状态
|
||||
this.saveImportTaskToStorage({
|
||||
taskId: statusResult.taskId,
|
||||
status: statusResult.status,
|
||||
hasFailures: statusResult.failureCount > 0,
|
||||
totalCount: statusResult.totalCount,
|
||||
successCount: statusResult.successCount,
|
||||
failureCount: statusResult.failureCount
|
||||
});
|
||||
|
||||
if (statusResult.status === 'SUCCESS') {
|
||||
// 全部成功
|
||||
this.$notify({
|
||||
title: '导入完成',
|
||||
message: `全部成功!共导入${statusResult.totalCount}条数据`,
|
||||
type: 'success',
|
||||
duration: 5000
|
||||
});
|
||||
this.showFailureButton = false;
|
||||
this.getList();
|
||||
} else if (statusResult.failureCount > 0) {
|
||||
// 部分失败
|
||||
this.$notify({
|
||||
title: '导入完成',
|
||||
message: `成功${statusResult.successCount}条,失败${statusResult.failureCount}条`,
|
||||
type: 'warning',
|
||||
duration: 5000
|
||||
});
|
||||
|
||||
// 显示查看失败记录按钮
|
||||
this.showFailureButton = true;
|
||||
this.currentTaskId = statusResult.taskId;
|
||||
|
||||
// 刷新列表
|
||||
this.getList();
|
||||
}
|
||||
},
|
||||
/** 查询失败记录列表 */
|
||||
getFailureList() {
|
||||
this.failureLoading = true;
|
||||
getImportFailures(
|
||||
this.currentTaskId,
|
||||
this.failureQueryParams.pageNum,
|
||||
this.failureQueryParams.pageSize
|
||||
).then(response => {
|
||||
this.failureList = response.rows;
|
||||
this.failureTotal = response.total;
|
||||
this.failureLoading = false;
|
||||
}).catch(error => {
|
||||
this.failureLoading = false;
|
||||
|
||||
// 处理不同类型的错误
|
||||
if (error.response) {
|
||||
const status = error.response.status;
|
||||
|
||||
if (status === 404) {
|
||||
// 记录不存在或已过期
|
||||
this.$modal.msgWarning('导入记录已过期,无法查看失败记录');
|
||||
this.clearImportTaskFromStorage();
|
||||
this.showFailureButton = false;
|
||||
this.currentTaskId = null;
|
||||
this.failureDialogVisible = false;
|
||||
} else if (status === 500) {
|
||||
this.$modal.msgError('服务器错误,请稍后重试');
|
||||
} else {
|
||||
this.$modal.msgError(`查询失败: ${error.response.data.msg || '未知错误'}`);
|
||||
}
|
||||
} else if (error.request) {
|
||||
// 请求发送了但没有收到响应
|
||||
this.$modal.msgError('网络连接失败,请检查网络');
|
||||
} else {
|
||||
this.$modal.msgError('查询失败记录失败: ' + error.message);
|
||||
}
|
||||
});
|
||||
},
|
||||
/** 查看导入失败记录 */
|
||||
viewImportFailures() {
|
||||
this.failureDialogVisible = true;
|
||||
this.getFailureList();
|
||||
},
|
||||
/** 恢复导入状态 */
|
||||
restoreImportState() {
|
||||
const savedTask = this.getImportTaskFromStorage();
|
||||
|
||||
if (!savedTask) {
|
||||
this.showFailureButton = false;
|
||||
this.currentTaskId = null;
|
||||
return;
|
||||
}
|
||||
|
||||
// 如果有失败记录,恢复按钮显示
|
||||
if (savedTask.hasFailures && savedTask.taskId) {
|
||||
this.currentTaskId = savedTask.taskId;
|
||||
this.showFailureButton = true;
|
||||
}
|
||||
},
|
||||
/** 获取上次导入的提示信息 */
|
||||
getLastImportTooltip() {
|
||||
const savedTask = this.getImportTaskFromStorage();
|
||||
if (savedTask && savedTask.saveTime) {
|
||||
const date = new Date(savedTask.saveTime);
|
||||
const timeStr = this.parseTime(date, '{y}-{m}-{d} {h}:{i}');
|
||||
return `上次导入: ${timeStr}`;
|
||||
}
|
||||
return '';
|
||||
},
|
||||
/** 保存导入任务到localStorage */
|
||||
saveImportTaskToStorage(taskData) {
|
||||
try {
|
||||
const data = {
|
||||
...taskData,
|
||||
saveTime: Date.now()
|
||||
};
|
||||
localStorage.setItem('staff_recruitment_import_last_task', JSON.stringify(data));
|
||||
} catch (error) {
|
||||
console.error('保存导入任务状态失败:', error);
|
||||
}
|
||||
},
|
||||
/** 从localStorage读取导入任务 */
|
||||
getImportTaskFromStorage() {
|
||||
try {
|
||||
const data = localStorage.getItem('staff_recruitment_import_last_task');
|
||||
if (!data) return null;
|
||||
|
||||
const task = JSON.parse(data);
|
||||
|
||||
// 数据格式校验
|
||||
if (!task || !task.taskId) {
|
||||
this.clearImportTaskFromStorage();
|
||||
return null;
|
||||
}
|
||||
|
||||
// 时间戳校验
|
||||
if (task.saveTime && typeof task.saveTime !== 'number') {
|
||||
this.clearImportTaskFromStorage();
|
||||
return null;
|
||||
}
|
||||
|
||||
// 过期检查(7天)
|
||||
const sevenDays = 7 * 24 * 60 * 60 * 1000;
|
||||
if (Date.now() - task.saveTime > sevenDays) {
|
||||
this.clearImportTaskFromStorage();
|
||||
return null;
|
||||
}
|
||||
|
||||
return task;
|
||||
} catch (error) {
|
||||
console.error('读取导入任务状态失败:', error);
|
||||
this.clearImportTaskFromStorage();
|
||||
return null;
|
||||
}
|
||||
},
|
||||
/** 清除导入历史记录 */
|
||||
clearImportHistory() {
|
||||
this.$confirm('确认清除上次导入记录?', '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
this.clearImportTaskFromStorage();
|
||||
this.showFailureButton = false;
|
||||
this.currentTaskId = null;
|
||||
this.failureDialogVisible = false;
|
||||
this.$message.success('已清除');
|
||||
}).catch(() => {});
|
||||
},
|
||||
/** 清除localStorage中的导入任务 */
|
||||
clearImportTaskFromStorage() {
|
||||
try {
|
||||
localStorage.removeItem('staff_recruitment_import_last_task');
|
||||
} catch (error) {
|
||||
console.error('清除导入任务状态失败:', error);
|
||||
}
|
||||
},
|
||||
// 导入结果弹窗关闭
|
||||
handleImportResultClose() {
|
||||
|
||||
Reference in New Issue
Block a user