yxh
2026-09-30 d21d7dd23f15a0ca395a4c9d1b3bb31330ff56c0
src/views/project/travelexpenseapply/index.vue
@@ -642,7 +642,7 @@
        </el-row>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button type="primary" @click="submitForm" v-if="dialogType == 'edit'">保 存</el-button>
        <el-button type="primary" :loading="saveLoading" @click="submitForm" v-if="dialogType == 'edit'">保 存</el-button>
        <el-button @click="cancel">取 消</el-button>
      </div>
    </el-dialog>
@@ -687,6 +687,7 @@
import { addorupdateFund } from "@/api/project/fund";
import { listReportname, listUser } from "@/api/project/organization";
import { getToken } from "@/utils/auth";
import { moneySum, moneyAdd } from "@/utils/money";
export default {
  components: {
    Treeselect,
@@ -738,6 +739,8 @@
      loading: true,
      // 导出遮罩层
      exportLoading: false,
      // 保存按钮 loading,防止重复提交
      saveLoading: false,
      // 选中数组
      ids: [],
      // 非单个禁用
@@ -1335,19 +1338,26 @@
      //获取报销主信息
      const id = row.id || this.ids;
      getReimbursement(id).then(response => {
        this.form = response.data;
        this.fileList = this.form.annexfiles
          ? this.form.annexfiles
            .split(",")
            .map(item => ({ url: item, name: item }))
          : [];
        this.form.recordstatus = response.data.recordstatus + "";
      getReimbursement(id)
        .then(async response => {
          this.form = response.data;
          this.fileList = this.form.annexfiles
            ? this.form.annexfiles
              .split(",")
              .map(item => ({ url: item, name: item }))
            : [];
          this.form.recordstatus = response.data.recordstatus + "";
        let ids = response.data.id;
        //获取报销明细信息
        getReimbursementdetaillist(ids).then(res => {
          this.rbDetails = res.data;
          const ids = response.data.id;
          this.queryParamsPayee.rbid = ids;
          //明细与打款信息互不依赖,并发获取,减少等待时间
          const [detailRes, payeeRes] = await Promise.all([
            getReimbursementdetaillist(ids),
            listReimbursementpayee(this.queryParamsPayee)
          ]);
          this.rbDetails = detailRes.data;
          if (this.rbDetails.length == 0) {
            this.addDetailRow(0);
          }
@@ -1366,17 +1376,15 @@
          //实时合计金额
          //this.sumTotalFee();
        });
        //获取报销打款信息
        this.queryParamsPayee.rbid = ids;
        listReimbursementpayee(this.queryParamsPayee).then(res => {
          this.rbPayees = res.rows;
          this.rbPayees = payeeRes.rows;
          if (this.rbPayees.length == 0) {
            this.addPayeeRow(0);
          }
        })
        .catch(() => {
          this.$modal.msgError("报销单信息加载失败,请重试!");
        });
      });
    },
    /** 查看按钮操作 */
@@ -1393,59 +1401,56 @@
      this.open = true;
      const id = row.id || this.ids;
      getReimbursement(id).then(response => {
        this.form = response.data;
        //附件
        this.fileList = this.form.annexfiles
          ? this.form.annexfiles
            .split(",")
            .map(item => ({ url: item, name: item }))
          : [];
      getReimbursement(id)
        .then(async response => {
          this.form = response.data;
          //附件
          this.fileList = this.form.annexfiles
            ? this.form.annexfiles
              .split(",")
              .map(item => ({ url: item, name: item }))
            : [];
        //审核状态
        this.form.recordstatus = response.data.recordstatus + "";
          //审核状态
          this.form.recordstatus = response.data.recordstatus + "";
        let ids = response.data.id;
        let listFundflowparams = {
          fundid: row.id,
          fundtype: 1
        };
        listFundflow(listFundflowparams).then(res => {
          this.fundflowList = res.rows;
        });
          const ids = response.data.id;
          const listFundflowparams = {
            fundid: row.id,
            fundtype: 1
          };
          this.queryParamsPayee.rbid = ids;
        //报销明细
        getReimbursementdetaillist(ids).then(res => {
          this.rbDetails = res.data;
          /*
          for (let i = 0; i < this.rbDetails.length; i++) {
            this.rbDetails[i].index = i;
            this.rbDetails[i].searchAddress = {
              sheng: this.rbDetails[i].travelprovincename,
              shi: this.rbDetails[i].travelcityname,
              qu: this.rbDetails[i].traveltownname,
            };
          }
          */
        });
          //资金流水、报销明细、打款信息互不依赖,并发获取
          const [fundflowRes, detailRes, payeeRes] = await Promise.all([
            listFundflow(listFundflowparams),
            getReimbursementdetaillist(ids),
            listReimbursementpayee(this.queryParamsPayee)
          ]);
        if (this.rbDetails.length > 0) this.sumTotalFee();
          this.fundflowList = fundflowRes.rows;
          this.rbDetails = detailRes.data;
        //付款信息
        this.queryParamsPayee.rbid = ids;
        listReimbursementpayee(this.queryParamsPayee).then(res => {
          this.rbPayees = res.rows;
          //明细加载完成后再计算合计,修复原代码在明细返回前就 sumTotalFee 的竞态问题
          if (this.rbDetails.length > 0) this.sumTotalFee();
          //付款信息
          this.rbPayees = payeeRes.rows;
          if (this.rbPayees.length == 0) {
            this.addPayeeRow(0);
          }
        })
        .catch(() => {
          this.$modal.msgError("报销单信息加载失败,请重试!");
        });
      });
    },
    /** 提交按钮 */
    submitForm() {
      this.$refs["form"].validate(valid => {
        if (valid) {
      //防止重复提交:保存中直接忽略再次点击
      if (this.saveLoading) return;
      this.$refs["form"].validate(async valid => {
        if (!valid) return;
          /**
           let indexErrTime = this.rbDetails.findIndex((item) => {
             if (item.endtime && item.starttime) {
@@ -1502,6 +1507,8 @@
          }
          */
          try {
          this.saveLoading = true;
          //附件文件处理
          let list = this.fileList;
          if (list.length > 0) {
@@ -1527,71 +1534,75 @@
          const rbDetails = [...this.rbDetails];
          const rbPayees = [...this.rbPayees];
          if (this.form.id != null) {
            updateReimbursement(this.form)
              .then(res => {
                //保存明细
                for (let i = 0; i < rbDetails.length; i++) {
                  if (rbDetails[i].rbid != null) {
                    updateReimbursementdetail(rbDetails[i]);
                  } else {
                    //rbid关联主表Id
                    rbDetails[i].rbid = this.form.id;
                    addReimbursementdetail(rbDetails[i]);
                  }
                }
            //第1步:更新主表,成功后再处理子表
            await updateReimbursement(this.form);
                //保存账户
                for (let i = 0; i < rbPayees.length; i++) {
                  if (rbPayees[i].rbid != null) {
                    updateReimbursementpayee(rbPayees[i]);
                  } else {
                    //rbid关联主表Id
                    rbPayees[i].rbid = this.form.id;
                    addReimbursementpayee(rbPayees[i]);
                  }
            //第2步:并发保存明细,等待全部完成,任一失败则走 catch 提示
            await Promise.all(
              rbDetails.map(detail => {
                if (detail.rbid != null) {
                  return updateReimbursementdetail(detail);
                }
                this.$modal.msgSuccess("修改报销单保存成功!");
                this.open = false;
                this.getList();
                //rbid关联主表Id
                detail.rbid = this.form.id;
                return addReimbursementdetail(detail);
              })
              .catch(err => {
                this.$modal.msgError("修改报销单保存失败!");
              });
            );
            //第3步:并发保存账户
            await Promise.all(
              rbPayees.map(payee => {
                if (payee.rbid != null) {
                  return updateReimbursementpayee(payee);
                }
                //rbid关联主表Id
                payee.rbid = this.form.id;
                return addReimbursementpayee(payee);
              })
            );
            this.$modal.msgSuccess("修改报销单保存成功!");
          } else {
            this.form.recordstatus = -1;
            addReimbursement(this.form)
              .then(response => {
                //保存明细
                for (let i = 0; i < rbDetails.length; i++) {
                  //rbid关联主表Id
                  rbDetails[i].rbid = response.data;
                  addReimbursementdetail(rbDetails[i]);
                }
            //第1步:新增主表,返回主表Id
            const response = await addReimbursement(this.form);
                //保存账号
                for (let i = 0; i < rbPayees.length; i++) {
                  //rbid关联主表Id
                  rbPayees[i].rbid = response.data;
                  addReimbursementpayee(rbPayees[i]);
                }
                this.$modal.msgSuccess("新增报销单保存成功!");
                this.open = false;
                this.getList();
            //第2步:并发保存明细
            await Promise.all(
              rbDetails.map(detail => {
                //rbid关联主表Id
                detail.rbid = response.data;
                return addReimbursementdetail(detail);
              })
              .catch(err => {
                this.$modal.msgError("新增报销单保存失败!");
              });
            );
            //第3步:并发保存账号
            await Promise.all(
              rbPayees.map(payee => {
                //rbid关联主表Id
                payee.rbid = response.data;
                return addReimbursementpayee(payee);
              })
            );
            this.$modal.msgSuccess("新增报销单保存成功!");
          }
          //所有保存步骤全部成功后才关闭弹窗并刷新列表
          this.open = false;
          this.getList();
          } catch (err) {
            this.$modal.msgError("报销单保存失败,请重试!");
          } finally {
            this.saveLoading = false;
          }
        }
      });
      );
    },
    /** 删除按钮操作 */
    handleDelete(row) {
      const ids = row.id || this.ids;
      console.log(ids);
      this.$modal
        .confirm("是否确认删除该条记录?")
        .then(function () {
@@ -1599,7 +1610,10 @@
          return delReimbursement(ids);
        })
        .then(() => {
          delReimbursementdetail(ids);
          //等待明细删除完成后再刷新列表,避免列表刷新时明细尚未删除
          return delReimbursementdetail(ids);
        })
        .then(() => {
          this.getList();
          this.$modal.msgSuccess("删除成功");
        })
@@ -1619,7 +1633,10 @@
          this.$download.name(response.msg);
          this.exportLoading = false;
        })
        .catch(() => { });
        .catch(() => {
          //失败时也要复位 loading,否则按钮永久转圈
          this.exportLoading = false;
        });
    },
    //新增一行
@@ -1800,107 +1817,30 @@
    },
    //计算一行合计
    //计算当前行报销内容费用合计
    //计算当前行报销内容费用合计(金额一律走精确运算)
    sumRowFee(row) {
      let totalFee = 0;
      if (!isNaN(parseFloat(row.trafficexpense))) {
        totalFee += parseFloat(row.trafficexpense);
      }
      if (!isNaN(parseFloat(row.cityfee))) {
        totalFee += parseFloat(row.cityfee);
      }
      if (!isNaN(parseFloat(row.hotelexpense))) {
        totalFee += parseFloat(row.hotelexpense);
      }
      if (!isNaN(parseFloat(row.otherexpense))) {
        totalFee += parseFloat(row.otherexpense);
      }
      if (!isNaN(parseFloat(row.foodexpenses))) {
        totalFee += parseFloat(row.foodexpenses);
      }
      if (!isNaN(parseFloat(row.foodallowance))) {
        totalFee += parseFloat(row.foodallowance);
      }
      if (!isNaN(parseFloat(row.otherfeeamount))) {
        totalFee += parseFloat(row.otherfeeamount);
      }
      row.total = totalFee;
      row.total = moneySum([
        row.trafficexpense,
        row.cityfee,
        row.hotelexpense,
        row.otherexpense,
        row.foodexpenses,
        row.foodallowance,
        row.otherfeeamount
      ]);
      /*
      if (!isNaN(parseFloat(this.rbDetails[rowIndex].trafficexpense))) {
        totalFee += parseFloat(this.rbDetails[rowIndex].trafficexpense);
      }
      if (!isNaN(parseFloat(this.rbDetails[rowIndex].cityfee))) {
        totalFee += parseFloat(this.rbDetails[rowIndex].cityfee);
      }
      if (!isNaN(parseFloat(this.rbDetails[rowIndex].hotelexpense))) {
        totalFee += parseFloat(this.rbDetails[rowIndex].hotelexpense);
      }
      if (!isNaN(parseFloat(this.rbDetails[rowIndex].otherexpense))) {
        totalFee += parseFloat(this.rbDetails[rowIndex].otherexpense);
      }
      if (!isNaN(parseFloat(this.rbDetails[rowIndex].foodexpenses))) {
        totalFee += parseFloat(this.rbDetails[rowIndex].foodexpenses);
      }
      if (!isNaN(parseFloat(this.rbDetails[rowIndex].foodallowance))) {
        totalFee += parseFloat(this.rbDetails[rowIndex].foodallowance);
      }
      if (!isNaN(parseFloat(this.rbDetails[rowIndex].otherfeeamount))) {
        totalFee += parseFloat(this.rbDetails[rowIndex].otherfeeamount);
      }
      this.rbDetails[rowIndex].total = parseFloat(totalFee).toFixed(2);
      this.$set(this.rbDetails, rowIndex, this.rbDetails[rowIndex]);
      */
      //重新计算整个报销单的合计
      this.sumTotalFee();
    },
    //计算费用合计
    sumTotalFee() {
      let allSum = 0;
      //捐献者家属费用
      if (!isNaN(parseFloat(this.form.donoramount))) {
        allSum += parseFloat(this.form.donoramount);
      }
      //报销明细费用
      try {
        for (let i = 0; i < this.rbDetails.length; i++) {
          /*
          let totalFee = 0;
          //计算当前报销内容费用合计
          if (!isNaN(parseFloat(this.rbDetails[i].total))) {
            totalFee += parseFloat(this.rbDetails[i].total);
          }
          if (!isNaN(parseFloat(this.rbDetails[i].cityfee))) {
            totalFee += parseFloat(this.rbDetails[i].cityfee);
          }
          if (!isNaN(parseFloat(this.rbDetails[i].hotelexpense))) {
            totalFee += parseFloat(this.rbDetails[i].hotelexpense);
          }
          if (!isNaN(parseFloat(this.rbDetails[i].otherexpense))) {
            totalFee += parseFloat(this.rbDetails[i].otherexpense);
          }
          if (!isNaN(parseFloat(this.rbDetails[i].foodexpenses))) {
            totalFee += parseFloat(this.rbDetails[i].foodexpenses);
          }
          if (!isNaN(parseFloat(this.rbDetails[i].foodallowance))) {
            totalFee += parseFloat(this.rbDetails[i].foodallowance);
          }
          if (!isNaN(parseFloat(this.rbDetails[i].otherfeeamount))) {
            totalFee += parseFloat(this.rbDetails[i].otherfeeamount);
          }
          this.rbDetails[i].total = parseFloat(totalFee).toFixed(2);
          this.$set(this.rbDetails, i, this.rbDetails[i]);
          */
          if (!isNaN(parseFloat(this.rbDetails[i].total))) {
            allSum += parseFloat(this.rbDetails[i].total);
          }
        }
        this.form.amountrequested = allSum.toFixed(2);
        this.form.amountrequested = moneyAdd(
          moneySum(this.rbDetails, "total"),
          this.form.donoramount
        ).toFixed(2);
        this.form.bigstrmoney = this.convertCurrency(this.form.amountrequested);
      } catch { }
    },