|
@@ -618,12 +618,32 @@
|
|
|
</el-col>
|
|
</el-col>
|
|
|
<template v-if="item.isFreeGift == 1">
|
|
<template v-if="item.isFreeGift == 1">
|
|
|
<el-col :lg="6" :md="24" :sm="24" :xs="24">
|
|
<el-col :lg="6" :md="24" :sm="24" :xs="24">
|
|
|
- <el-form-item label="赠送开始时间" prop="freeStartTime">
|
|
|
|
|
|
|
+ <el-form-item
|
|
|
|
|
+ label="赠送开始时间"
|
|
|
|
|
+ :prop="'stageExpenses.' + index + '.freeStartTime'"
|
|
|
|
|
+ :rules="[
|
|
|
|
|
+ {
|
|
|
|
|
+ required: item.isFreeGift == 1,
|
|
|
|
|
+ message: '请选择赠送开始时间',
|
|
|
|
|
+ trigger: ['change', 'blur']
|
|
|
|
|
+ }
|
|
|
|
|
+ ]"
|
|
|
|
|
+ >
|
|
|
<TgDatePicker type="date" v-model="item.freeStartTime" format />
|
|
<TgDatePicker type="date" v-model="item.freeStartTime" format />
|
|
|
</el-form-item>
|
|
</el-form-item>
|
|
|
</el-col>
|
|
</el-col>
|
|
|
<el-col :lg="5" :md="24" :sm="24" :xs="24">
|
|
<el-col :lg="5" :md="24" :sm="24" :xs="24">
|
|
|
- <el-form-item label="赠送结束时间" prop="freeEndTime">
|
|
|
|
|
|
|
+ <el-form-item
|
|
|
|
|
+ label="赠送结束时间"
|
|
|
|
|
+ :prop="'stageExpenses.' + index + '.freeEndTime'"
|
|
|
|
|
+ :rules="[
|
|
|
|
|
+ {
|
|
|
|
|
+ required: item.isFreeGift == 1,
|
|
|
|
|
+ message: '请选择赠送结束时间',
|
|
|
|
|
+ trigger: ['change', 'blur']
|
|
|
|
|
+ }
|
|
|
|
|
+ ]"
|
|
|
|
|
+ >
|
|
|
<TgDatePicker type="date" v-model="item.freeEndTime" format />
|
|
<TgDatePicker type="date" v-model="item.freeEndTime" format />
|
|
|
</el-form-item>
|
|
</el-form-item>
|
|
|
</el-col>
|
|
</el-col>
|
|
@@ -877,6 +897,13 @@ const init = async (row, detail = false, status) => {
|
|
|
arr[0] = {
|
|
arr[0] = {
|
|
|
...arr[0],
|
|
...arr[0],
|
|
|
...item,
|
|
...item,
|
|
|
|
|
+ // totalAmount 缺失/非法时优先用 actualAmount 兜底(月费 totalAmount 本就 = actualAmount),
|
|
|
|
|
+ // 避免把真实费用提交成 0 元;两者都缺才归 0
|
|
|
|
|
+ totalAmount: Number.isFinite(Number(item.totalAmount))
|
|
|
|
|
+ ? Number(item.totalAmount)
|
|
|
|
|
+ : Number.isFinite(Number(item.actualAmount))
|
|
|
|
|
+ ? Number(item.actualAmount)
|
|
|
|
|
+ : 0,
|
|
|
discountTemp: item.discount ? formatNum(item.discount) : undefined,
|
|
discountTemp: item.discount ? formatNum(item.discount) : undefined,
|
|
|
discountAmountTemp: item.discountAmount ? formatNum(item.discountAmount) : ''
|
|
discountAmountTemp: item.discountAmount ? formatNum(item.discountAmount) : ''
|
|
|
}
|
|
}
|
|
@@ -884,6 +911,13 @@ const init = async (row, detail = false, status) => {
|
|
|
arr[1] = {
|
|
arr[1] = {
|
|
|
...arr[1],
|
|
...arr[1],
|
|
|
...item,
|
|
...item,
|
|
|
|
|
+ // totalAmount 缺失/非法时优先用 actualAmount 兜底(月费 totalAmount 本就 = actualAmount),
|
|
|
|
|
+ // 避免把真实费用提交成 0 元;两者都缺才归 0
|
|
|
|
|
+ totalAmount: Number.isFinite(Number(item.totalAmount))
|
|
|
|
|
+ ? Number(item.totalAmount)
|
|
|
|
|
+ : Number.isFinite(Number(item.actualAmount))
|
|
|
|
|
+ ? Number(item.actualAmount)
|
|
|
|
|
+ : 0,
|
|
|
discountTemp: item.discount ? formatNum(item.discount) : undefined,
|
|
discountTemp: item.discount ? formatNum(item.discount) : undefined,
|
|
|
discountAmountTemp: item.discountAmount ? formatNum(item.discountAmount) : ''
|
|
discountAmountTemp: item.discountAmount ? formatNum(item.discountAmount) : ''
|
|
|
}
|
|
}
|
|
@@ -891,6 +925,13 @@ const init = async (row, detail = false, status) => {
|
|
|
arr[2] = {
|
|
arr[2] = {
|
|
|
...arr[2],
|
|
...arr[2],
|
|
|
...item,
|
|
...item,
|
|
|
|
|
+ // totalAmount 缺失/非法时优先用 actualAmount 兜底(月费 totalAmount 本就 = actualAmount),
|
|
|
|
|
+ // 避免把真实费用提交成 0 元;两者都缺才归 0
|
|
|
|
|
+ totalAmount: Number.isFinite(Number(item.totalAmount))
|
|
|
|
|
+ ? Number(item.totalAmount)
|
|
|
|
|
+ : Number.isFinite(Number(item.actualAmount))
|
|
|
|
|
+ ? Number(item.actualAmount)
|
|
|
|
|
+ : 0,
|
|
|
discountTemp: item.discount ? formatNum(item.discount) : undefined,
|
|
discountTemp: item.discount ? formatNum(item.discount) : undefined,
|
|
|
discountAmountTemp: item.discountAmount ? formatNum(item.discountAmount) : ''
|
|
discountAmountTemp: item.discountAmount ? formatNum(item.discountAmount) : ''
|
|
|
}
|
|
}
|
|
@@ -898,6 +939,13 @@ const init = async (row, detail = false, status) => {
|
|
|
arr[3] = {
|
|
arr[3] = {
|
|
|
...arr[3],
|
|
...arr[3],
|
|
|
...item,
|
|
...item,
|
|
|
|
|
+ // totalAmount 缺失/非法时优先用 actualAmount 兜底(月费 totalAmount 本就 = actualAmount),
|
|
|
|
|
+ // 避免把真实费用提交成 0 元;两者都缺才归 0
|
|
|
|
|
+ totalAmount: Number.isFinite(Number(item.totalAmount))
|
|
|
|
|
+ ? Number(item.totalAmount)
|
|
|
|
|
+ : Number.isFinite(Number(item.actualAmount))
|
|
|
|
|
+ ? Number(item.actualAmount)
|
|
|
|
|
+ : 0,
|
|
|
discountTemp: item.discount ? formatNum(item.discount) : undefined,
|
|
discountTemp: item.discount ? formatNum(item.discount) : undefined,
|
|
|
discountAmountTemp: item.discountAmount ? formatNum(item.discountAmount) : ''
|
|
discountAmountTemp: item.discountAmount ? formatNum(item.discountAmount) : ''
|
|
|
}
|
|
}
|
|
@@ -915,7 +963,28 @@ const init = async (row, detail = false, status) => {
|
|
|
})
|
|
})
|
|
|
dataForm.value.stageExpenses.map((item) => {
|
|
dataForm.value.stageExpenses.map((item) => {
|
|
|
getNameList(item)
|
|
getNameList(item)
|
|
|
|
|
+ // 兼容后端返回类型不一的 isFreeGift(1 / "1" / true)→ 归一为 0/1,
|
|
|
|
|
+ // 保证模板 v-if="item.isFreeGift == 1" 与必填校验判定一致
|
|
|
|
|
+ item.isFreeGift = Number(item.isFreeGift) === 1 ? 1 : 0
|
|
|
|
|
+ // 兼容后端返回时间戳(Long)/ 带时分秒字符串 → 归一为 YYYY-MM-DD
|
|
|
|
|
+ //(TgDatePicker 的 value-format 为 date,拿到时间戳/长字符串会显示空)
|
|
|
|
|
+ item.freeStartTime = normalizeGiftDate(item.freeStartTime)
|
|
|
|
|
+ item.freeEndTime = normalizeGiftDate(item.freeEndTime)
|
|
|
})
|
|
})
|
|
|
|
|
+ // 诊断:重新发起/编辑回显时后端返回的阶段性收费项(排查赠送时间不回显问题,看控制台)
|
|
|
|
|
+ console.info(
|
|
|
|
|
+ '[入住办理] stageExpenses 回显:',
|
|
|
|
|
+ JSON.parse(
|
|
|
|
|
+ JSON.stringify(
|
|
|
|
|
+ dataForm.value.stageExpenses.map((it: any) => ({
|
|
|
|
|
+ itemName: it.itemName,
|
|
|
|
|
+ isFreeGift: it.isFreeGift,
|
|
|
|
|
+ freeStartTime: it.freeStartTime,
|
|
|
|
|
+ freeEndTime: it.freeEndTime
|
|
|
|
|
+ }))
|
|
|
|
|
+ )
|
|
|
|
|
+ )
|
|
|
|
|
+ )
|
|
|
if (!res.startTenantId) {
|
|
if (!res.startTenantId) {
|
|
|
dataForm.value.startTenantId = getTenantId()
|
|
dataForm.value.startTenantId = getTenantId()
|
|
|
}
|
|
}
|
|
@@ -981,14 +1050,11 @@ const submitForm = async () => {
|
|
|
let result = true
|
|
let result = true
|
|
|
// 长住才校验
|
|
// 长住才校验
|
|
|
if (dataForm.value.inStatusType == '1') {
|
|
if (dataForm.value.inStatusType == '1') {
|
|
|
- try {
|
|
|
|
|
- if (arr[3].amount == '' || arr[3].amount == null || arr[3].amount == undefined) {
|
|
|
|
|
- //没有选择服务费
|
|
|
|
|
- arr.splice(3, 1) //删除
|
|
|
|
|
- }
|
|
|
|
|
- } catch (e) {}
|
|
|
|
|
- // 校验床位护理餐饮
|
|
|
|
|
- arr.map((item) => {
|
|
|
|
|
|
|
+ // 床位/护理/餐饮必填;服务费(type=7)可选,未选择时跳过校验
|
|
|
|
|
+ // ⚠️ 不再 arr.splice(3, 1) 物理删除——arr 必须保持固定 4 项结构
|
|
|
|
|
+ //(getOverheadByType/totalMonthFee/编辑回填 arr[3] 都依赖索引,删项会永久错乱)
|
|
|
|
|
+ arr.forEach((item) => {
|
|
|
|
|
+ if (item.type == 7 && !item.itemId) return
|
|
|
if (!item.itemId) {
|
|
if (!item.itemId) {
|
|
|
item.errMsg = item.label1 + '不能为空'
|
|
item.errMsg = item.label1 + '不能为空'
|
|
|
result = false
|
|
result = false
|
|
@@ -1051,7 +1117,8 @@ const submitForm = async () => {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
if (dataForm.value.inStatusType == '1') {
|
|
if (dataForm.value.inStatusType == '1') {
|
|
|
- data.expenseBO.monthlyExpenses.push(...arr)
|
|
|
|
|
|
|
+ // 只提交已选择的固定费用项(服务费未选则不提交;filter 返回新数组,不破坏 arr 4 项结构)
|
|
|
|
|
+ data.expenseBO.monthlyExpenses.push(...arr.filter((item) => item.itemId))
|
|
|
}
|
|
}
|
|
|
data.expenseBO.monthlyExpenses.forEach((item) => {
|
|
data.expenseBO.monthlyExpenses.forEach((item) => {
|
|
|
item.list = undefined
|
|
item.list = undefined
|
|
@@ -1061,6 +1128,20 @@ const submitForm = async () => {
|
|
|
item.list = undefined
|
|
item.list = undefined
|
|
|
item.isDayCalculate = item.isDayCalculate === 1 ? 1 : 0
|
|
item.isDayCalculate = item.isDayCalculate === 1 ? 1 : 0
|
|
|
})
|
|
})
|
|
|
|
|
+ // 是否赠送=是 时,赠送开始/结束时间必填(兜底校验,防 el-form validate 因动态 prop 未命中而放行)
|
|
|
|
|
+ for (let i = 0; i < dataForm.value.stageExpenses.length; i++) {
|
|
|
|
|
+ const giftItem = dataForm.value.stageExpenses[i]
|
|
|
|
|
+ if (giftItem.isFreeGift == 1) {
|
|
|
|
|
+ if (!giftItem.freeStartTime) {
|
|
|
|
|
+ message.error(`请选择第${i + 1}个收费项目的赠送开始时间`)
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
+ if (!giftItem.freeEndTime) {
|
|
|
|
|
+ message.error(`请选择第${i + 1}个收费项目的赠送结束时间`)
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
// 去除阶段性的actualAmount
|
|
// 去除阶段性的actualAmount
|
|
|
data.expenseBO.stageExpenses.forEach((item) => {
|
|
data.expenseBO.stageExpenses.forEach((item) => {
|
|
|
item.list = undefined
|
|
item.list = undefined
|
|
@@ -1295,6 +1376,16 @@ const getNameList = async (item) => {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+/** 赠送时间归一:数字时间戳(13位毫秒/10位秒)或 "YYYY-MM-DD HH:mm:ss" → "YYYY-MM-DD";空保持空 */
|
|
|
|
|
+const normalizeGiftDate = (val: any): string => {
|
|
|
|
|
+ if (val === undefined || val === null || val === '') return ''
|
|
|
|
|
+ if (typeof val === 'number') {
|
|
|
|
|
+ const d = val >= 1e12 ? dayjs(val) : dayjs.unix(val)
|
|
|
|
|
+ return d.isValid() ? d.format('YYYY-MM-DD') : ''
|
|
|
|
|
+ }
|
|
|
|
|
+ return String(val).slice(0, 10)
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
const deathTime = computed(() => {
|
|
const deathTime = computed(() => {
|
|
|
if (dataForm.value.checkInTime && dataForm.value.times) {
|
|
if (dataForm.value.checkInTime && dataForm.value.times) {
|
|
|
// 要比原来的天数少1天
|
|
// 要比原来的天数少1天
|
|
@@ -1488,11 +1579,16 @@ const handleDelMonth = (index: number) => {
|
|
|
|
|
|
|
|
const totalMonthFee = computed(() => {
|
|
const totalMonthFee = computed(() => {
|
|
|
let total = 0
|
|
let total = 0
|
|
|
|
|
+ // 安全累加:任何 totalAmount 是 undefined / null / 非数字都按 0 计(避免 NaN 污染总和 → formatNum 输出空)
|
|
|
|
|
+ const safeAdd = (v: any) => {
|
|
|
|
|
+ const n = Number(v)
|
|
|
|
|
+ return Number.isFinite(n) ? n : 0
|
|
|
|
|
+ }
|
|
|
dataForm.value.monthlyExpenses.map((item) => {
|
|
dataForm.value.monthlyExpenses.map((item) => {
|
|
|
- total += Number(item.totalAmount)
|
|
|
|
|
|
|
+ total += safeAdd(item.totalAmount)
|
|
|
})
|
|
})
|
|
|
arr.map((item) => {
|
|
arr.map((item) => {
|
|
|
- total += Number(item.totalAmount)
|
|
|
|
|
|
|
+ total += safeAdd(item.totalAmount)
|
|
|
})
|
|
})
|
|
|
return total
|
|
return total
|
|
|
})
|
|
})
|