yxh
2 天以前 a79d67f8a9a9fa02f9d25f987b9611af965c484f
src/views/project/travelexpenseapply/travelexpensedetail/index.vue
@@ -9,7 +9,7 @@
              <el-date-picker
                style="width: 100%"
                v-model="form.applyTime"
                type="date"
                type="date" format="yyyy-MM-dd"
                value-format="yyyy-MM-dd HH:mm:ss"
                placeholder="申请日期"
                :disabled="true"
@@ -76,7 +76,7 @@
            <el-form-item
              label="捐献者"
              prop="infoid"
              v-show="form.costtype == 4"
              v-show="form.costtype == 3 || form.costtype == 4"
            >
              <el-select
                v-model="form.infoid"
@@ -94,6 +94,14 @@
                </el-option>
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :span="4">
            <div style="margin-left: 10px;">
              <dict-tag
                :options="dict.type.sys_DonationStatus"
                :value="form.invoicecount"
              />
            </div>
          </el-col>
        </el-row>
        <el-row style="margin-top: 10px">
@@ -145,7 +153,7 @@
            <el-form-item label="出差人" prop="travelers">
              <el-select v-model="form.travelers" clearable filterable allow-create ref="getReportname"
                default-first-option placeholder="请选择" @change="getAccountinfo()">
                <el-option v-for="item in travelers" :key="item.reportNo" :label="item.reportName"
                <el-option v-for="item in travelers"  :label="item.reportName"
                  :value="item.reportName">
                </el-option>
              </el-select>
@@ -326,12 +334,11 @@
                  allow-create
                  default-first-option
                  placeholder="请选择"
                  @focus1="getPersons(scope.row)"
                >
                  <el-option
                    v-for="item in personsSel"
                    :key="item.reportNo"
                    :label="item.reportName"
                    :key="item.id"
                    :label="item.reportNameDesc"
                    :value="item.reportName"
                  >
                  </el-option>
@@ -362,7 +369,7 @@
                  size="small"
                  style="width: 100%"
                  v-model="scope.row.starttime"
                  type="date"
                  type="date" format="yyyy-MM-dd"
                  value-format="yyyy-MM-dd HH:mm:ss"
                  placeholder="开始日期"
                  @blur="getdays(scope.row)"
@@ -394,7 +401,7 @@
                  size="small"
                  style="width: 100%"
                  v-model="scope.row.endtime"
                  type="date"
                  type="date" format="yyyy-MM-dd"
                  value-format="yyyy-MM-dd HH:mm:ss"
                  placeholder="结束日期"
                  @blur="getdays(scope.row)"
@@ -780,9 +787,9 @@
                >
                  <el-option
                    v-for="item in personsSel"
                    :key="item.reportNo"
                    :label="item.reportName"
                    :value="item.reportName"
                    :key="item.id"
                    :label="item.reportNameDesc"
                    :value="item.id"
                  >
                  </el-option>
                </el-select>
@@ -841,7 +848,7 @@
            <!--
            <el-table-column prop="paiddate" slot="" label="打款日期" fixed align="center" width="150">
              <template slot-scope="scope">
                <el-date-picker clearable size="small" style="width: 100%" v-model="scope.row.paiddate" type="date"
                <el-date-picker clearable size="small" style="width: 100%" v-model="scope.row.paiddate" type="date" format="yyyy-MM-dd"
                  value-format="yyyy-MM-dd HH:mm:ss" placeholder="打款日期" :disabled="true">
                </el-date-picker>
              </template>
@@ -917,9 +924,9 @@
          <el-col :span="12">
            <el-form-item label="预审材料" prop="infoid">
              <el-radio-group v-model="form.checkstatus" align="left">
                <el-radio label="1">待申请材料</el-radio>
                <el-radio label="2">审核通过等待邮寄纸质材料</el-radio>
                <el-radio label="3">已收到报销材料</el-radio>
                <el-radio label="1">待申请</el-radio>
                <el-radio label="2">审核通过等待纸质材料</el-radio>
                <el-radio label="3">已收到纸质材料</el-radio>
              </el-radio-group>
            </el-form-item>
          </el-col>
@@ -1109,8 +1116,8 @@
              <!-- <el-image
                style="width: 95%; height: 90%"
                :src="pdfimg"
                :preview-src-list="pdfimgsrcList" -->
              >
                :preview-src-list="pdfimgsrcList"
              > -->
              <el-image
                ref="imagePreview"
                style="width: 95%; height: 90%"
@@ -1275,7 +1282,8 @@
  exportReimbursement,
  getdownload,
  checkfund,
  fundSubmit
  fundSubmit,
  listbypowerone
} from "@/api/project/reimbursement";
import {
  addReimbursementdetail,
@@ -1297,6 +1305,8 @@
import { listReportname, listUser } from "@/api/project/organization";
import { getToken } from "@/utils/auth";
import debounce from "lodash/debounce";
import { moneySum, moneyAdd, moneyRound } from "@/utils/money";
import { checkFileName, checkDetails } from "@/utils/fileNameCheck";
export default {
  components: {
    Treeselect,
@@ -1313,7 +1323,8 @@
    "sys_recordstatus",
    "sys_travelexpensebelong",
    "sys_traffictype",
    "sys_area_name"
    "sys_area_name",
    "sys_DonationStatus"
  ],
  data() {
    return {
@@ -1436,15 +1447,15 @@
      baselisttages: [
        {
          id: 1,
          name: "待申请材料"
          name: "待申请"
        },
        {
          id: 2,
          name: "审核通过等待邮寄纸质材料"
          name: "预审通过等待纸质材料"
        },
        {
          id: 3,
          name: "已收到报销材料"
          name: "已收到纸质材料"
        }
      ],
      baselist: [],
@@ -1484,6 +1495,8 @@
        flowconclusion: null,
        fundid: null
      },
      //连续审批:待审批列表
      pendingList: [],
      jurisdiction: false,
      //保存按钮控制
@@ -1576,7 +1589,7 @@
      if (
        (JSON.stringify(this.form) == sessionStorage.getItem("apiform") &&
          JSON.stringify(this.rbDetails) ==
            sessionStorage.getItem("apifunddetail")) ||
          sessionStorage.getItem("apifunddetail")) ||
        !sessionStorage.getItem("apifunddetail")
      ) {
      } else {
@@ -1639,7 +1652,7 @@
    handleImageLoad() {
      console.log("图片加载成功");
    },
    handleUploadError() {},
    handleUploadError() { },
    // 获取请求头
    Getnetworkheader() {
      console.log(window.location.href);
@@ -1678,7 +1691,43 @@
    },
    //文件上传成功回调
    /**
     * 2026-10-15:上传时校验附件文件名(业务要求:不合格立即提示且不加入列表)。
     * 规则与后端 AttachmentNameValidator 同口径:必须含中文 / 去掉扩展名后主干 ≤20 字 /
     * 不含空格及 / \ : * ? " < > | # % 等特殊字符。
     */
    checkUploadFileName(file) {
      const raw = file && file.raw ? file.raw.name : file && file.name;
      const r = checkFileName(raw);
      if (!r.ok) {
        this.$modal.msgError(r.msg);
        return false;
      }
      return true;
    },
    /**
     * 2026-10-15:保存前校验整单明细附件文件名(含同一行内重名)。
     * 口径(业务确认):只校验"本次变更"的附件——老单据里已存在的不合规附件名不能把保存卡死
     * (否则老单据改一个金额都存不进去)。后端按 id 读旧记录放行历史附件;前端拿不到"哪些是历史"
     * 的权威信息,因此**仅新增单据**做保存前拦截,编辑老单据时新增的不合规附件由后端二次校验拦下。
     */
    checkDetailFileNames() {
      if (this.form && this.form.id) {
        return true;
      }
      const c = checkDetails(this.rbDetails);
      if (!c.ok) {
        this.$modal.msgError(c.msg);
        return false;
      }
      return true;
    },
    uploadSccess(response, file, fileList) {
      if (!this.checkUploadFileName(file)) {
        return;
      }
      this.rbDetails;
      const config = {
        headers: { Authorization: "Bearer " + this.ICDtoken }
@@ -1699,6 +1748,12 @@
                name: file.name,
                url: URL.createObjectURL(blob)
              });
              // 2026-10-15:删除这里的第二次 push。原来一次上传会向 fileListto / pdfimgsrcList
              // 各写两条,且第二条的 name 取的是 file.response.fileName(存储路径);而 remove()
              // 会把整个 fileListto 回写到 rbDetails[atpresent].annexfilesList,导致明细附件里
              // 混入路径形态的 name,被附件文件名校验误拦(前端没有"路径形态跳过"豁免),
              // 同时票据列表会多出一行。
              console.log(URL.createObjectURL(blob), "ur转换");
            })
            .catch(error => {
              console.error("Error loading image", error);
@@ -2046,6 +2101,11 @@
      } else if (row.persontype == "管理人员") {
        this.personsSel = this.personsManager;
      }
      if (this.personsSel && this.personsSel.length) {
        this.personsList.forEach(item => {
          item.reportNameDesc = `${item.reportName}(${item.unitname})`;
        });
      }
    },
    //获取设置人员账号信息
@@ -2075,7 +2135,8 @@
      }
      for (let m = 0; m < dataArr.length; m++) {
        if (dataArr[m].reportName == row.personname) {
        if (dataArr[m].id == row.personname) {
          row.personname = dataArr[m].reportName;
          row.bankname = dataArr[m].depositbank;
          row.bankcardno = dataArr[m].bankcardno;
        }
@@ -2094,7 +2155,7 @@
        row.days = (
          Math.floor(
            Math.abs(Date.parse(row.starttime) - Date.parse(row.endtime)) /
              (1000 * 3600 * 24)
            (1000 * 3600 * 24)
          ) + 1
        ).toString();
      } else {
@@ -2120,9 +2181,9 @@
          if (tempStr == "杭州") {
            row.otherexpense = "";
          } else if (
            tempStr == "杭州-桐庐" ||
            tempStr == "杭州-建德" ||
            tempStr == "杭州-淳安"
            tempStr.includes("桐庐") ||
          tempStr.includes("建德") ||
          tempStr.includes("淳安")
          ) {
            row.otherexpense = (parseInt(row.days) * 60).toString();
          } else {
@@ -2244,10 +2305,22 @@
        if (item.id == this.form.infoid) {
          this.form.donorno = item.donorno;
          this.form.donorname = item.name;
          // 新增:将捐献者的 recordstate 赋值到 invoicecount
          if (item.recordstate !== undefined && item.recordstate !== null) {
            this.form.invoicecount = item.recordstate.toString();
          } else {
            this.form.invoicecount = ""; // 如果 recordstate 为空,清空字段
          }
        }
      });
    },
    // 添加清除方法
    clearDonatorInfo() {
      this.form.donorno = "";
      this.form.donorname = "";
      this.form.invoicecount = ""; // 清空 invoicecount
    },
    onpick(e) {
      // console.log(e,this.value1)
    },
@@ -2425,13 +2498,13 @@
        this.fileListto = this.form.annexfiles
          ? this.form.annexfiles
              .split(",")
              .map(item => ({ url: item, name: item }))
            .split(",")
            .map(item => ({ url: item, name: item }))
          : [];
        this.invoicefileListto = this.form.invoicefilesList
          ? this.form.invoicefilesList
              .split(",")
              .map(item => ({ url: item, name: item }))
            .split(",")
            .map(item => ({ url: item, name: item }))
          : [];
        this.form.recordstatus = response.data.recordstatus + "";
        sessionStorage.removeItem("apiform");
@@ -2490,16 +2563,16 @@
        //票据
        this.fileListto = this.form.annexfiles
          ? this.form.annexfiles
              .split(",")
              .map(item => ({ url: item, name: item }))
            .split(",")
            .map(item => ({ url: item, name: item }))
          : [];
        this.invoicefileListto = this.form.invoicefilesList
          ? this.form.invoicefilesList
              .split(",")
              .map(item => ({ url: item, name: item }))
            .split(",")
            .map(item => ({ url: item, name: item }))
          : [];
        //审核状态
        this.form.recordstatus = response.data.recordstatus + "";
        this.form.recordstatus = this.toStatusText(response.data.recordstatus, "-1");
        let ids = response.data.id;
        let listFundflowparams = {
          fundid: ids,
@@ -2510,14 +2583,19 @@
        });
        //报销明细
        getReimbursementdetaillist(ids).then(res => {
          this.rbDetails = res.data;
          //合计费用
          // if (this.rbDetails.length > 0) this.sumTotalFee();
          for (let i = 0; i < this.rbDetails.length; i++) {
            this.sumRowFee(this.rbDetails[i]);
          }
        });
        getReimbursementdetaillist(ids)
          .then(res => {
            this.rbDetails = this.normalizeDetailList(res);
            //合计费用
            // if (this.rbDetails.length > 0) this.sumTotalFee();
            for (let i = 0; i < this.rbDetails.length; i++) {
              this.sumRowFee(this.rbDetails[i]);
            }
          })
          .catch(err => {
            this.rbDetails = [];
            console.error("获取报销明细失败,id=" + ids, err);
          });
        //付款信息
        this.queryParamsPayee.rbid = ids;
@@ -2540,23 +2618,32 @@
      this.reset();
      this.open = true;
      const id = ids || this.ids;
      this.checkObj.fundid = id;
      // 重置审批信息,避免上一单的审批结果带入下一单
      this.checkObj = {
        flowlevelone: null,
        flowconclusion: null,
        fundid: id
      };
      // 连续审批:加载当前用户的待审批列表
      this.getPendingList();
      getReimbursement(id).then(response => {
        this.form = response.data;
        console.log(this.form.checkstatus, "checkstatus");
        this.form.checkstatus = this.form.checkstatus.toString();
        // checkstatus 在库中可为空(预审状态尚未产生时),直接 toString 会抛 TypeError 中断后续取数
        this.form.checkstatus = this.toStatusText(this.form.checkstatus, "-1");
        //票据
        this.fileListto = this.form.annexfiles
          ? this.form.annexfiles
              .split(",")
              .map(item => ({ url: item, name: item }))
            .split(",")
            .map(item => ({ url: item, name: item }))
          : [];
        this.invoicefileListto = this.form.invoicefilesList
          ? this.form.invoicefilesList
              .split(",")
              .map(item => ({ url: item, name: item }))
            .split(",")
            .map(item => ({ url: item, name: item }))
          : [];
        //审核状态
@@ -2572,16 +2659,22 @@
        });
        //报销明细
        getReimbursementdetaillist(ids).then(res => {
          this.rbDetails = res.data;
          console.log(this.rbDetails);
        getReimbursementdetaillist(ids)
          .then(res => {
            this.rbDetails = this.normalizeDetailList(res);
            console.log("报销明细行数:", this.rbDetails.length, this.rbDetails);
          //合计费用
          // if (this.rbDetails.length > 0) this.sumTotalFee();
          for (let i = 0; i < this.rbDetails.length; i++) {
            this.sumRowFee(this.rbDetails[i]);
          }
        });
            //合计费用
            // if (this.rbDetails.length > 0) this.sumTotalFee();
            for (let i = 0; i < this.rbDetails.length; i++) {
              this.sumRowFee(this.rbDetails[i]);
            }
          })
          .catch(err => {
            // 取数失败时不再静默:置空并打出原因,避免“接口有数据但页面空白”无从排查
            this.rbDetails = [];
            console.error("获取报销明细失败,id=" + ids, err);
          });
        //付款信息
        this.queryParamsPayee.rbid = ids;
@@ -2630,39 +2723,115 @@
        if (res.code == 200) {
          this.$modal.closeLoading();
          this.$modal.msgSuccess("提交审核成功!");
          // 关闭窗口
          this.$store.dispatch("tagsView/delView", this.$route);
          this.$router.go(-1);
          // 连续审批:询问是否继续审批下一单
          this.continueOrExit();
        } else {
          this.$modal.closeLoading();
          if (res.msg) {
            this.$modal.msgError("操作失误");
          } else {
            this.$modal.msgError(res.msg);
          }
          this.$modal.msgError(res.msg || "操作失败");
        }
      });
    },
    // 获取当前用户待审批列表(用于连续审批)
    getPendingList() {
      listbypowerone({
        pageNum: 1,
        pageSize: 1000,
        CHECKFLAG: 1
      })
        .then(res => {
          this.pendingList = res.rows || [];
        })
        .catch(() => {
          this.pendingList = [];
        });
    },
    // 审批完成后:询问是否继续审批下一单
    continueOrExit() {
      const list = this.pendingList || [];
      const curId = String(this.checkObj.fundid);
      const idx = list.findIndex(item => String(item.id) === curId);
      let next = null;
      if (idx > -1 && idx + 1 < list.length) {
        next = list[idx + 1];
      } else {
        // 当前已是末位(或从中间开始),取剩余列表中第一条非当前单据
        next = list.find(item => String(item.id) !== curId) || null;
      }
      if (next) {
        this.$confirm("审批已完成,是否继续审批下一张待审批单据?", "提示", {
          confirmButtonText: "继续审批",
          cancelButtonText: "返回列表",
          type: "info"
        })
          .then(() => {
            // 直接在当前页面加载下一张待审批单据
            this.handleCheck(next.id);
            // 同步更新地址栏,避免刷新后回到上一单
            this.$router
              .replace({
                path: this.$route.path,
                query: { id: next.id, pos: 4 }
              })
              .catch(() => {});
          })
          .catch(() => {
            this.exitToPage();
          });
      } else {
        this.$modal.msgSuccess("已无待审批单据,返回列表");
        this.exitToPage();
      }
    },
    // 返回列表页
    exitToPage() {
      this.$store.dispatch("tagsView/delView", this.$route);
      this.$router.go(-1);
    },
    /** 提交保存按钮 */
    submitForm: debounce(function(data) {
    submitForm: debounce(function (data) {
      // 2026-10-15:保存前附件文件名规范校验(仅新增单据;老单据的历史附件由后端按"只校验本次变更"放行)
      if (!this.checkDetailFileNames()) {
        return;
      }
      this.$refs["form"].validate(valid => {
        if (valid) {
          //票据文件处理
          const addnumber = new Decimal(this.rbPayees.reduce(
            (amount, item) => amount + Number(item.amount),
            0
          ));
          console.log(this.form.amountrequested,addnumber);
          //校验请款金额合计是否等于报销单金额
          if (this.form.amountrequested != addnumber) {
          // const addnumber = new Decimal(this.rbPayees.reduce((amount, item) => amount + Number(item.amount), 0 ));
          // console.log(this.form.amountrequested,addnumber);
          // //校验请款金额合计是否等于报销单金额
          // if (this.form.amountrequested != addnumber) {
          //   this.$message({
          //     message:
          //       "报销请款表中合计金额不等于报销单的报销金额,请更正后再保存!!",
          //     type: "warning"
          //   });
          //   return;
          // }
          // 1. 在 reduce 累加时,直接传入字符串给 Decimal,并使用 .plus() 方法进行累加
          // 初始值设为 new Decimal(0),确保全程高精度运算
          const addnumber = this.rbPayees.reduce((amount, item) => {
            return amount.plus(new Decimal(item.amount.toString()));
          }, new Decimal(0));
          console.log(this.form.amountrequested, addnumber.toString());
          // 2. 使用 Decimal 的 .eq() 方法进行严格相等比较
          // 这样既解决了精度问题,也解决了类型转换比较的问题
          if (!addnumber.eq(this.form.amountrequested)) {
            this.$message({
              message:
                "报销请款表中合计金额不等于报销单的报销金额,请更正后再保存!!",
              message: "报销请款表中合计金额不等于报销单的报销金额,请更正后再保存!!",
              type: "warning"
            });
            return;
          }
          const rbDetails = [...this.rbDetails];
          const rbPayees = [...this.rbPayees];
@@ -2673,8 +2842,8 @@
            if (!tempDetail.persontype) {
              this.$modal.msgWarning(
                "明细表中,第" +
                  (k + 1).toString() +
                  "行的人员类别未选择,请先选择人员类别后再提交保存!"
                (k + 1).toString() +
                "行的人员类别未选择,请先选择人员类别后再提交保存!"
              );
              return;
            }
@@ -2682,8 +2851,8 @@
            if (!tempDetail.personname) {
              this.$modal.msgWarning(
                "明细表中,第" +
                  (k + 1).toString() +
                  "行的费用人员未选择,请选择费用人员后再提交保存!"
                (k + 1).toString() +
                "行的费用人员未选择,请选择费用人员后再提交保存!"
              );
              return;
            }
@@ -2691,8 +2860,8 @@
            if (!tempDetail.starttime) {
              this.$modal.msgWarning(
                "明细表中,第" +
                  (k + 1).toString() +
                  "行的开始日期未选择,请选择开始日期后再提交保存!"
                (k + 1).toString() +
                "行的开始日期未选择,请选择开始日期后再提交保存!"
              );
              return;
            }
@@ -2700,8 +2869,8 @@
            if (!tempDetail.endtime) {
              this.$modal.msgWarning(
                "明细表中,第" +
                  (k + 1).toString() +
                  "行的结束日期姓名为选择,请选择结束日期后再提交保存!"
                (k + 1).toString() +
                "行的结束日期姓名为选择,请选择结束日期后再提交保存!"
              );
              return;
            }
@@ -2713,12 +2882,12 @@
            //保存明细
            for (let i = 0; i < rbDetails.length; i++) {
              if (rbDetails[i].rbid != null) {
                if (rbDetails[i].persontype == "家属") {
                if (rbDetails[i].persontype == "家属"||rbDetails[i].persontype == "专家") {
                  if (this.form.infoid) {
                    updateReimbursementdetail(rbDetails[i]);
                  } else {
                    return this.$message.error(
                      `因家属分配要求,请选择捐献者信息`
                      "因财务核算的要求,家属或专家的报销,需要选择对应的捐献者!"
                    );
                  }
                } else {
@@ -2732,7 +2901,7 @@
                    addReimbursementdetail(rbDetails[i]);
                  } else {
                    return this.$message.error(
                      `因家属分配要求,请选择捐献者信息`
                      "因财务核算的要求,家属或专家的报销,需要选择对应的捐献者!"
                    );
                  }
                } else {
@@ -2819,7 +2988,7 @@
      const ids = row.id || this.ids;
      this.$modal
        .confirm("是否确认删除该条记录?")
        .then(function() {
        .then(function () {
          // 删除details内的数据
          return delReimbursement(ids);
        })
@@ -2828,7 +2997,7 @@
          this.getList();
          this.$modal.msgSuccess("删除成功");
        })
        .catch(() => {});
        .catch(() => { });
    },
    /** 导出按钮操作 */
@@ -2844,7 +3013,7 @@
          this.$download.name(response.msg);
          this.exportLoading = false;
        })
        .catch(() => {});
        .catch(() => { });
    },
    // 取消提醒
    unsave() {
@@ -2853,6 +3022,11 @@
    },
    // 接受提醒立刻保存
    Savenow() {
      // 2026-10-15:保存前附件文件名规范校验(仅新增单据;老单据的历史附件由后端按"只校验本次变更"放行)
      if (!this.checkDetailFileNames()) {
        return;
      }
      this.Savereminder = false;
      this.Reminderquantity = 0;
      this.totalquantity = 0;
@@ -3129,110 +3303,73 @@
        });
    },
    //计算一行合计
    //计算当前行报销内容费用合计
    sumRowFee(row) {
      let totalFee = 0;
      if (!isNaN(parseFloat(row.trafficexpense))) {
        totalFee += parseFloat(row.trafficexpense);
    /**
     * 状态类字段转字符串(接口可能返回 null)。
     *
     * 背景:checkstatus、recordstatus 等在库中可空,早期直接调用 .toString()
     * 会抛 TypeError 并中断其后的取数逻辑,表现为“接口已有数据但明细区空白”。
     *
     * @param {*} value 原始状态值
     * @param {string} fallback 为空时的兜底值
     * @returns {string}
     */
    toStatusText(value, fallback) {
      if (value === null || value === undefined || value === "") {
        return fallback;
      }
      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.toFixed(2);
      return String(value);
    },
      /*
      if (!isNaN(parseFloat(this.rbDetails[rowIndex].trafficexpense))) {
        totalFee += parseFloat(this.rbDetails[rowIndex].trafficexpense);
    /**
     * 统一从明细接口响应中取出数组。
     *
     * 正常为 AjaxResult 的 data 数组;若后端改为分页结构(total + rows),
     * res.data 将不是数组,直接绑定到 el-table 会导致“有数据但不显示”。
     *
     * @param {Object} res 接口原始响应
     * @returns {Array} 明细数组(异常时为空数组,不会让表格拿到非数组)
     */
    normalizeDetailList(res) {
      if (!res) {
        return [];
      }
      if (!isNaN(parseFloat(this.rbDetails[rowIndex].cityfee))) {
        totalFee += parseFloat(this.rbDetails[rowIndex].cityfee);
      if (Array.isArray(res.data)) {
        return res.data;
      }
      if (!isNaN(parseFloat(this.rbDetails[rowIndex].hotelexpense))) {
        totalFee += parseFloat(this.rbDetails[rowIndex].hotelexpense);
      if (Array.isArray(res.rows)) {
        return res.rows;
      }
      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]);
      */
      return [];
    },
    //计算一行合计
    //计算当前行报销内容费用合计(金额一律走精确运算)
    sumRowFee(row) {
      const totalFee = moneySum([
        row.trafficexpense,
        row.cityfee,
        row.hotelexpense,
        row.otherexpense,
        row.foodexpenses,
        row.foodallowance,
        row.otherfeeamount
      ]);
      row.total = moneyRound(totalFee).toFixed(2);
      //重新计算整个报销单的合计
      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 {}
      } catch { }
    },
    //金额数字转换成大写