为社么根据父组件传值后初始化页面时子组件的第一个级联和最后两个下拉框没有回显?
console.log("this.expenseList[0].options", this.expenseList[0].options.userOptions);打印了三次最后一次数据正确
父组件
<!-- 表格内容 - 收款 -->
<div class="tableClass">
<ReimbDetail
ref="reimbDetailRef"
:formData="formData"
:isEdit="
(!formData.isDraft || Number(formData.isUpdate) === 1) &&
isShowWhilePrint
"
v-model="formData.expenseList"
></ReimbDetail>
</div>
子组件代码
<template>
<div class="detail-cont">
<el-form :model="formData" :rules="rules" ref="formRef">
<!-- 报销明细 -->
<div class="title-cont">
<h3>
<span>收款</span>
</h3>
<div class="btn-cont" v-if="isEdit == '1'">
<!-- 添加 -->
<i class="el-icon-circle-plus-outline" @click="handleAdd"></i>
<!-- 删除 -->
<i class="el-icon-remove-outline" @click="handleDel" v-if="expenseList && expenseList.length > 1"></i>
</div>
</div>
<el-table :data="expenseList" style="width: 100%" max-height="550px" ref="tableRef" border>
<el-table-column type="selection" width="36" />
<!-- 报销类型 -->
<el-table-column prop="reimbursementType" :label="$t('travel.reimburseType')">
<template slot-scope="scope">
<el-form-item :prop="'expenseList.' + scope.$index + '.reimbursementType'"
:rules="[{ required: true, trigger: 'change' }]">
<span>{{
selectDictLabels(
dict.type.oa_reimbursement_type,
scope.row.reimbursementType
)
}}</span>
</el-form-item>
</template>
</el-table-column>
<!-- 承担部门 -->
<el-table-column prop="deptId" :label="'承担部门'">
<template slot="header">
<a class="label-required">*</a>承担部门
</template>
<template slot-scope="scope">
<el-form-item :prop="'expenseList.' + scope.$index + '.payDeptId'"
:rules="[{ required: true, trigger: 'change' }]">
<el-cascader v-if="isEdit == '1'" v-model="scope.row.payDeptId" :options="deptOptions" :props="{
value: 'id',
label: 'label',
children: 'children',
}" filterable :show-all-levels="false" style="width: 100%"
@change="(value) => handleDepBudget(scope.row, 'payDeptId', value)"></el-cascader>
<span v-else>{{ scope.row.deptName }}</span>
</el-form-item>
</template>
</el-table-column>
<!-- 费用科目 -->
<el-table-column prop="expenseType" :label="$t('travel.expenseItem')">
<template slot="header">
<a class="label-required">*</a>{{ $t("travel.expenseItem") }}
</template>
<template slot-scope="scope">
<el-form-item :prop="'expenseList.' + scope.$index + '.expenseType'"
:rules="[{ required: true, trigger: 'change' }]">
<div v-if="isEdit == '1'" style="display: flex; align-items: center">
<el-select v-if="isEdit == '1'" v-model="scope.row.expenseType" clearable filterable
:placeholder="$t('travel.pleaseSelect')" style="width: 100%"
@change="handleDepBudget(scope.row, 'expenseType')">
<el-option v-for="item in dict.type.financial_budget_type" :key="item.value" :label="item.label"
:value="item.value">
</el-option>
</el-select>
</div>
<span v-else>{{
selectDictLabels(
dict.type.financial_budget_type,
scope.row.expenseType
)
}}</span>
</el-form-item>
</template>
</el-table-column>
<!-- 承担部门预算 -->
<el-table-column prop="depBudget" :label="'承担部门预算'">
<template slot="header">
<a class="label-required">*</a>承担部门预算
</template>
<template slot-scope="scope">
<el-form-item :prop="'expenseList.' + scope.$index + '.depBudget'"
:rules="[{ required: true, trigger: 'change' }]">
<!-- 可用预算 -->
<div style="color: #000000; font-weight: 600">
{{ $t("travel.availableBudget") }}: {{ scope.row.currency }}
{{ scope.row.budgetAmount || "0.00" }}
</div>
<!-- 已发生费用 -->
<div style="color: #0000ff; font-weight: 600">
{{ $t("travel.incurredFee") }}: {{ scope.row.currency }}
{{ scope.row.incurredAmount || "0.00" }}
</div>
<!-- 审批中费用 -->
<div style="color: #008000; font-weight: 600">
{{ $t("travel.reviewFee") }}:{{ scope.row.currency }}
{{ scope.row.approveAmount || "0.00" }}
</div>
</el-form-item>
</template>
</el-table-column>
<!-- 申请金额 -->
<el-table-column prop="consumeAmount" :label="'申请金额'">
<template slot="header">
<a class="label-required">*</a>申请金额
</template>
<template slot-scope="scope">
<el-form-item :prop="'expenseList.' + scope.$index + '.consumeAmount'"
:rules="[{ required: true, trigger: 'blur' }]">
<div v-if="isEdit == '1'" style="display: flex; align-items: center">
<el-input :placeholder="$t('travel.pleaseEnter')" style="width: 100%"
v-model.trim="scope.row.consumeAmount" maxlength="13"
oninput="value=value.replace(/^([0-9-]\d*\.?\d{0,2})?.*$/,'$1')"
@input="(val) => handleInputChange(val, scope.row, 'consumeAmount')" @blur="
handleInputBlur(
scope.row.consumeAmount,
scope.row,
'consumeAmount'
)
">
<template slot="append">{{ scope.row.currency }}</template>
</el-input>
</div>
<span v-else-if="isEdit != '1' && scope.row.consumeAmount">{{ scope.row.currency }} {{
scope.row.consumeAmount
}}</span>
</el-form-item>
</template>
</el-table-column>
<!-- 负责人 -->
<el-table-column prop="userId" :label="'负责人'">
<template slot="header">
<a class="label-required">*</a>负责人
</template>
<template slot-scope="scope">
<el-form-item :prop="'expenseList.' + scope.$index + '.userId'"
:rules="[{ required: true, trigger: 'change' }]">
<el-select v-if="isEdit == '1'" v-model="scope.row.userId" clearable filterable remote reserve-keyword
:remote-method="(value) => getCostBearerList(value, scope.row.deptId)"
@focus="(value) => getCostBearerList(value, scope.row.deptId)" :placeholder="$t('travel.pleaseSelect')"
style="width: 100%" @change="(value) => handleSelect(value, 'user', scope)">
<el-option v-for="item in scope.row.options.userOptions" :key="item.leaderId" :label="item.leaderName"
:value="item.leaderId">
</el-option>
</el-select>
<span v-else>{{ scope.row.leaderName }}</span>
</el-form-item>
</template>
</el-table-column>
<!-- 高级/运营总监 -->
<el-table-column prop="leaderId" :label="'高级/运营总监'">
<template slot="header">
<a class="label-required">*</a>高级/运营总监
</template>
<template slot-scope="scope">
<el-form-item :prop="'expenseList.' + scope.$index + '.leaderId'"
:rules="[{ required: true, trigger: 'change' }]">
<el-select v-if="isEdit == '1'" v-model="scope.row.leaderId" clearable filterable remote reserve-keyword
:remote-method="(value) => getCostBearerList2(value, scope.row.deptId)"
@focus="(value) => getCostBearerList2(value, scope.row.deptId)" :placeholder="$t('travel.pleaseSelect')"
style="width: 100%" @change="(value) => handleSelect(value, 'leader', scope)">
<el-option v-for="item in scope.row.options.leaderOptions" :key="item.rosterId" :label="item.rosterName"
:value="item.rosterId">
</el-option>
</el-select>
<span v-else>{{ scope.row.leaderName }}</span>
</el-form-item>
</template>
</el-table-column>
</el-table>
</el-form>
</div>
</template>
<script>
import { getBdDeptAllList, depBudgetS } from "@/api/agentFollow/travel";
import { rosteruser } from "@/api/user.js";
import { printLeaderList } from "@/api/financial/commiProcess";
import { getDate } from "@/utils";
import { message } from '../../config_file/config_file';
import {
getDeptreeChild,
approval,
} from "@/api/agentFollow/process.js";
export default {
name: "ReimbDetail",
components: {},
dicts: ["oa_reimbursement_type", "financial_budget_type"],
props: {
defaultExpenseList: {
type: Array,
default() {
return [];
},
},
dataState: {
type: Number,
},
applyDate: {
type: String,
},
formData: {
type: Object,
default() {
return {};
},
},
},
data() {
return {
isEdit: this.$route.query.isEdit || "1", // 0 详情 1编辑
validateFlag: false,
rules: {
'expenseList.0.reimbursementType': [{ required: true, trigger: 'change' }],
'expenseList.0.payDeptId': [{ required: true, trigger: 'change' }],
'expenseList.0.expenseType': [{ required: true, trigger: 'change' }],
'expenseList.0.depBudget': [{ required: true, trigger: 'change' }],
'expenseList.0.consumeAmount': [{ required: true, trigger: 'blur' }],
'expenseList.0.userId': [{ required: true, trigger: 'change' }],
'expenseList.0.leaderId': [{ required: true, trigger: 'change' }]
},
expenseList: [
{
reimbursementType: "1", // 费用类型
payDeptId: this.formData.deptId, // 承担部门id
payDeptName: this.formData.deptId, // 承担部门名称
expenseType: null, // 费用科目
// 承担部门预算
currency: null, // 币种
approveAmount: null, // 审批中费用
budgetAmount: null, // 可用预算
incurredAmount: null, // 已发生费用
consumeAmount: null, // 申请金额
userId: this.formData.leaderId, // 负责人id
userName: this.formData.leaderName, // 负责人名称
leaderId: this.formData.leaderId, // 高级/运营总监id
leaderName: this.formData.leaderName, // 高级/运营总监名称
deptOptions: [], // 承担部门列表
// 下拉选项
options: {
divisionOption: [], // 报销承担分部列表
userOptions: [], // 负责人列表
leaderOptions: [], // 高级/运营总列表
},
}
],
arr: {},
deptOptions: [],
};
},
watch: {
expenseList: {
handler(newVal) {
this.$emit('input', newVal);
},
deep: true
}
},
mounted() {
this.onDictReady();
},
methods: {
// 初始化
async onDictReady() {
this.arr = {
reimbursementType: "1", // 费用类型
payDeptId: this.formData.deptId, // 承担部门id
payDeptName: this.formData.deptName, // 承担部门名称
userId: this.formData.leaderId, // 负责人id
userName: this.formData.leaderName, // 负责人名称
leaderId: this.formData.leaderId, // 高级/运营总监id
leaderName: this.formData.leaderName, // 高级/运营总监名称
options: {
divisionOption: [], // 报销承担分部列表
userOptions: [], // 负责人列表
leaderOptions: [], // 高级/运营总列表
},
}
if (this.formData.expenseList && this.formData.expenseList.length > 0) {
this.expenseList = this.formData.expenseList;
} else {
this.expenseList = []
this.expenseList.push(this.arr)
}
try {
// 获取所有需要的数据
const [divisionOption, userOptions, leaderOptions] = await Promise.all([
this.getDivisionList(""),
this.getCostBearerList("", this.formData.deptId),
this.getCostBearerList2("", this.formData.deptId)
]);
// 更新每个行的options
this.expenseList.forEach((item, index) => {
this.$set(this.expenseList, index, { ...item, options }); // 替换整个对象以触发响应式更新
});
console.log("this.expenseList[0].options", this.expenseList[0].options.userOptions);
// 强制更新视图
this.$nextTick(() => {
this.expenseList = [...this.expenseList];
});
} catch (error) {
console.error('初始化数据失败:', error);
}
},
// 金额/汇率处理
handleInputBlur(item, row, str) {
// 保留两位小数
if (item !== "" && item != undefined) {
row[str] = (item / 1).toFixed(2);
} else {
row.consumeAmount = 0;
}
if (row.consumeAmount && row.budgetAmount) {
if (parseFloat(row.consumeAmount) > parseFloat(row.budgetAmount)) {
this.$modal.confirm(this.$t("travel.amountCompareTips")); // 报销金额不能大于可用预算
row.consumeAmount = "";
return false;
}
}
},
// 输入框内容变化处理
handleInputChange(val, row, str) {
if (val === '') {
row[str] = '';
// 触发校验
this.$refs.formRef.validateField(`expenseList.${this.expenseList.indexOf(row)}.${str}`);
}
},
// 计算承担主体预算(部门)
async handleDepBudget(row, type, value) {
console.log("handleDepBudget--row", row.expenseType, row.payDeptId);
if (row.expenseType || row.payDeptId) {
row.deptId = row.payDeptId.length > 0 ? row.payDeptId[row.payDeptId.length - 1] : "";
console.log("2222222--row", row.expenseType, row.deptId);
// 获取负责人列表
const userOptions = await this.getCostBearerList("", row.deptId);
row.options.userOptions = userOptions;
// 获取高级/运营总监列表
const leaderOptions = await this.getCostBearerList2("", row.deptId);
row.options.leaderOptions = leaderOptions;
// 获取预算信息
depBudgetS({
deptId: row.deptId,
reimburseDate: this.applyDate,
subjectType: row.expenseType,
}).then((res) => {
this.$set(row, "approveAmount", res.data.approveAmount);
this.$set(row, "budgetAmount", res.data.budgetAmount);
this.$set(row, "incurredAmount", res.data.incurredAmount);
this.$set(row, "currency", res.data.currency);
});
}
if (type == "payDeptId") {
// 清空费用承担人
row.userId = "";
row.userName = "";
row.leaderId = "";
row.leaderName = "";
row.expenseType = "";
// 触发校验
this.$nextTick(() => {
this.$refs.formRef.validateField([
`expenseList.${this.expenseList.indexOf(row)}.userId`,
`expenseList.${this.expenseList.indexOf(row)}.leaderId`,
`expenseList.${this.expenseList.indexOf(row)}.expenseType`
]);
});
}
},
// 远程检索 -- 报销承担分部
async getDivisionList() {
try {
let res = await getDeptreeChild();
this.deptOptions = res.data;
} catch (error) { }
},
// 远程检索 -- 负责人
async getCostBearerList(val, deptId) {
const params = {
deptId: deptId || "",
userName: typeof val === "string" ? val : "",
};
try {
const res = await printLeaderList(params);
if (res.code === "000") {
return res.data;
} else {
return [];
}
} catch (error) {
return [];
}
},
// 远程检索 -- 高级/运营总监
async getCostBearerList2(val, deptId) {
const params = {
deptId: deptId || "",
userName: typeof val === "string" ? val : "",
};
try {
const res = await rosteruser(params);
if (res.code === "000") {
return res.data;
} else {
return [];
}
} catch (error) {
return [];
}
},
// 负责人&高级/运营总监 选择
handleSelect(value, type, scope) {
const target = scope.row.options[type + "Options"].find((item) => {
if (type === 'user') {
return item.leaderId === value;
} else {
return item.rosterId === value;
}
}) || null;
if (type === 'user') {
scope.row[type + "Id"] = target?.leaderId;
scope.row[type + "Name"] = target?.leaderName;
} else {
scope.row[type + "Id"] = target?.rosterId;
scope.row[type + "Name"] = target?.rosterName;
}
// 强制更新视图
this.$nextTick(() => {
this.expenseList = [...this.expenseList];
});
},
// 添加
async handleAdd() {
try {
// 获取所有需要的数据
const [divisionOption, userOptions, leaderOptions] = await Promise.all([
this.getDivisionList(""),
this.getCostBearerList("", this.formData.deptId),
this.getCostBearerList2("", this.formData.deptId)
]);
// 创建新行数据
const newRow = {
...this.arr,
options: {
divisionOption: divisionOption || [],
userOptions: userOptions || [],
leaderOptions: leaderOptions || []
}
};
console.log("ADD111111111--options.userOption", userOptions)
// 添加到列表
this.expenseList.push(newRow);
// 强制更新视图
this.$nextTick(() => {
this.expenseList = [...this.expenseList];
});
} catch (error) {
console.error('添加行数据失败:', error);
this.$message.error('添加行数据失败');
}
},
},
};
</script>