From 5cb5f6d2e7ebb5bfdf0fd6b68604977491185059 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=A0=82=E7=B3=96?= Date: Wed, 21 Jan 2026 13:53:55 +0800 Subject: [PATCH] =?UTF-8?q?feat(leave):=20=E5=AE=9E=E7=8E=B0=E6=89=B9?= =?UTF-8?q?=E9=87=8F=E8=AF=B7=E5=81=87=E6=97=B6=E6=AE=B5=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 添加多时段请假表单支持,允许用户一次提交多个请假时段 重构表单数据结构为数组格式,支持动态增减时段 实现批量提交逻辑,自动处理成功和失败情况 添加时段校验规则和样式优化 --- klp-ui/src/views/wms/hrm/apply/leave.vue | 294 +++++++++++++++-------- 1 file changed, 197 insertions(+), 97 deletions(-) diff --git a/klp-ui/src/views/wms/hrm/apply/leave.vue b/klp-ui/src/views/wms/hrm/apply/leave.vue index e14b53ae..20db9dce 100644 --- a/klp-ui/src/views/wms/hrm/apply/leave.vue +++ b/klp-ui/src/views/wms/hrm/apply/leave.vue @@ -9,8 +9,6 @@ - @@ -26,28 +24,54 @@ - - - - - - - - - - - - - - - - - - + + +
+
+ 请假时段 {{ index + 1 }} + + 删除 +
+ + + + + + + + + + + + + + + + + + + + + +
+ + + + + 新增请假时段 + + @@ -56,8 +80,7 @@
- {{ form.leaveId ? '更新申请' : '提交申请' - }} + {{ form.leaveId ? '更新申请' : '批量提交申请' }} 重置表单
@@ -108,7 +131,6 @@ @@ -137,7 +159,15 @@ export default { data() { return { // 表单参数 - form: {}, + form: { + list: [{ // 初始化默认一行请假时段 + startTime: undefined, + endTime: undefined, + leaveShift: undefined, + leaveDays: undefined, + leaveReason: undefined + }] + }, loading: false, buttonLoading: false, leaveRequestList: [], @@ -149,37 +179,25 @@ export default { applyType: 'leave', createBy: this.$store.getters.name, }, - // 表单校验规则【核心新增:完整必填校验】 + // 表单校验规则【适配数组嵌套校验】 rules: { - leaveTitle: [{ required: true, message: '请假原因不能为空', trigger: ['blur', 'change'] }], leaveType: [{ required: true, message: '请假类型不能为空', trigger: 'change' }], applicantName: [{ required: true, message: '请假人姓名不能为空', trigger: 'change' }], - startTime: [{ required: true, message: '开始时间不能为空', trigger: 'change' }], - endTime: [{ required: true, message: '结束时间不能为空', trigger: 'change' }], - leaveShift: [{ required: true, message: '请假班次不能为空', trigger: 'change' }], - leaveDays: [ - { required: true, message: '请假天数不能为空', trigger: ['blur', 'change'] }, - ], applicantDeptName: [{ required: true, message: '审批部门不能为空', trigger: 'change' }], + attachmentUrls: [{ required: false }], + remark: [{ required: false }], + // 数组项的校验规则 + listItem: { + startTime: [{ required: true, message: '开始时间不能为空', trigger: 'change' }], + endTime: [{ required: true, message: '结束时间不能为空', trigger: 'change' }], + leaveShift: [{ required: true, message: '请假班次不能为空', trigger: 'change' }], + leaveDays: [{ required: true, message: '请假天数不能为空', trigger: ['blur', 'change'] }], + leaveReason: [{ required: true, message: '请假原因不能为空', trigger: ['blur', 'change'] }] + } }, deptOptions: [] } }, - // 核心新增:监听开始/结束时间变化,自动计算天数 - watch: { - 'form.startTime': { - handler() { - this.calculateLeaveDays() - }, - immediate: false - }, - 'form.endTime': { - handler() { - this.calculateLeaveDays() - }, - immediate: false - }, - }, created() { this.getList(); this.getDeptList(); @@ -218,6 +236,24 @@ export default { this.loading = false; }); }, + // 新增请假时段行 + addLeaveItem() { + this.form.list.push({ + startTime: undefined, + endTime: undefined, + leaveShift: undefined, + leaveDays: undefined, + leaveReason: undefined + }); + }, + // 删除指定索引的请假时段行 + removeLeaveItem(index) { + if (this.form.list.length <= 1) { + this.$message.warning('至少保留一行请假时段'); + return; + } + this.form.list.splice(index, 1); + }, handleReset() { this.reset() }, @@ -225,22 +261,19 @@ export default { reset() { this.form = { leaveId: undefined, - leaveTitle: undefined, leaveType: undefined, applicantName: undefined, applicantDeptName: undefined, - startTime: undefined, - endTime: undefined, - leaveShift: undefined, - leaveDays: undefined, - leaveReason: undefined, + approverName: undefined, attachmentUrls: undefined, - createBy: undefined, - createTime: undefined, - updateBy: undefined, - updateTime: undefined, - delFlag: undefined, - remark: undefined + remark: undefined, + list: [{ // 重置后保留默认一行 + startTime: undefined, + endTime: undefined, + leaveShift: undefined, + leaveDays: undefined, + leaveReason: undefined + }] }; this.resetForm("form"); }, @@ -261,34 +294,93 @@ export default { const leaveId = row.applyId getLeaveRequest(leaveId).then(response => { this.loading = false; - this.form = response.data; + const data = response.data; + // 编辑时默认填充为单行数据(因为后端是单条记录) + this.form = { + ...data, + list: [{ + startTime: data.startTime, + endTime: data.endTime, + leaveShift: data.leaveShift, + leaveDays: data.leaveDays, + leaveReason: data.leaveReason + }] + }; }); }, - /** 提交按钮 */ - handleSubmit() { - this.form.leaveTitle = `${this.form.applicantName}-${this.form.leaveType}-${this.form.startTime}-${this.form.leaveReason || ''}` - this.$refs["form"].validate(valid => { - if (valid) { - this.buttonLoading = true; - if (this.form.leaveId != null) { - updateLeaveRequest(this.form).then(response => { - this.$modal.msgSuccess("修改成功"); - this.getList(); - this.reset() - }).finally(() => { - this.buttonLoading = false; - }); - } else { - addLeaveRequest(this.form).then(response => { - this.$modal.msgSuccess("新增成功"); - this.getList(); - this.reset() - }).finally(() => { - this.buttonLoading = false; - }); + /** 批量提交按钮(核心修改) */ + async handleSubmit() { + try { + // 1. 先校验表单 + const valid = await new Promise((resolve) => { + this.$refs["form"].validate((valid) => { + resolve(valid); + }); + }); + + if (!valid) return; + + this.buttonLoading = true; + const { list, ...commonFields } = this.form; // 拆分公共字段和时段列表 + let successCount = 0; + let failCount = 0; + const failReasons = []; + + // 2. 循环处理每个时段,逐个发送请求 + for (let i = 0; i < list.length; i++) { + const item = list[i]; + // 组装单个请求的数据(公共字段 + 当前时段字段) + const singleRequestData = { + ...commonFields, + startTime: item.startTime, + endTime: item.endTime, + leaveShift: item.leaveShift, + leaveDays: item.leaveDays, + leaveReason: item.leaveReason, + // 生成单条记录的标题 + leaveTitle: `${commonFields.applicantName}-${commonFields.leaveType}-时段${i+1}-${item.startTime}-${item.leaveReason || ''}` + }; + + try { + if (commonFields.leaveId != null) { + // 编辑模式:仅支持修改单条(因为后端是单条记录) + if (list.length > 1) { + this.$message.warning('编辑模式仅支持单条修改,已自动取第一行数据'); + await updateLeaveRequest({ ...singleRequestData, leaveId: commonFields.leaveId }); + successCount++; + break; // 编辑时只处理第一条 + } else { + await updateLeaveRequest({ ...singleRequestData, leaveId: commonFields.leaveId }); + successCount++; + } + } else { + // 新增模式:批量提交多条 + await addLeaveRequest(singleRequestData); + successCount++; + } + } catch (error) { + failCount++; + failReasons.push(`时段${i+1}提交失败:${error.message || '未知错误'}`); + // 失败后继续提交下一条,不中断批量操作 + continue; } } - }); + + // 3. 提交完成后反馈结果 + if (failCount === 0) { + this.$modal.msgSuccess(`批量提交成功!共提交${successCount}条请假申请`); + } else { + this.$modal.msgWarning(`批量提交完成!成功${successCount}条,失败${failCount}条\n失败原因:${failReasons.join(';')}`); + } + + // 4. 刷新列表并重置表单 + this.getList(); + this.reset(); + } catch (error) { + this.$modal.msgError('批量提交异常:' + error.message); + } finally { + this.buttonLoading = false; + } }, handleWithdraw(row) { this.$modal.confirm('是否确认撤回请假申请编号为"' + row.applyId + '"的数据项?').then(() => { @@ -316,7 +408,6 @@ export default { } return typeMap[status] || 'default' }, - // 获取审批状态的中文文本 getStatusText(status) { const textMap = { @@ -327,27 +418,36 @@ export default { } return textMap[status] || '未知状态' }, - // 核心新增:自动计算请假天数的方法 - calculateLeaveDays() { - const { startTime, endTime } = this.form; + // 计算指定行的请假天数 + calculateLeaveDays(index) { + const item = this.form.list[index]; // 两个时间都选择后才计算 - if (startTime && endTime) { + if (item.startTime && item.endTime) { // 转成时间戳 - const start = new Date(startTime).getTime(); - const end = new Date(endTime).getTime(); + const start = new Date(item.startTime).getTime(); + const end = new Date(item.endTime).getTime(); // 判断结束时间不能小于开始时间 if (end < start) { this.$modal.msgWarning('结束时间不能早于开始时间,请重新选择!'); - this.form.leaveDays = undefined; + item.leaveDays = undefined; return; } // 计算时间差(毫秒) → 转天 → 保留2位小数 const diffTime = end - start; const diffDays = (diffTime / (1000 * 60 * 60 * 24)).toFixed(2); - // 赋值到天数输入框 - this.form.leaveDays = diffDays; + // 赋值到对应行的天数输入框 + item.leaveDays = diffDays; } } } } - \ No newline at end of file + + + \ No newline at end of file