vxe-table 实现表格填写自动计算且限制数值复杂操作
效果
演示

思路
- 输入框设置最大值:max="row.max"
- 输入框调用方法@blur="updateFooterEvent(row, $event)" @input=" if (row[item.field] > row.max) { row[item.field] = row.max; } "
上代码
核心代码
设置最大值
controlrowcell({ row, column }: any) {
      this.setMax(column.title, row);
      return true;
    },
setMax(field: any, row: any) {
      let max = row.detailqty;
      for (const key in row) {
        if (key !== "detailqty" && key !== "deptId" && key !== "spe" && key !== "deptName" && key !== "id" && key !== "_XID" && key !== "partname" && key !== field && key !== "" && key !== "max") {
          console.log(key);
          max -= row[key];
        }
      }
      row.max = max;
      console.log(row.max);
    },
    updateFooterEvent(row: any, event: any) {
      console.log(row);
      console.log(event.value);
      let spe = row.max - event.value;
      let qty = row.detailqty;
      row.spe = qty + "/" + spe;
    },
res.data.map((v: any) => {
			//业务所需自行修改
            if (v.partname.indexOf("机架") !== -1) {
              v.spe = v.detailqty + "/0";
            } else {
              let spe = v.detailqty;
              for (const key in v) {
                if (key !== "detailqty" && key !== "deptId" && key !== "spe" && key !== "deptName" && key !== "id" && key !== "_XID" && key !== "partname" && key !== "" && key !== "max") {
                  spe -= v[key];
                }
              }
              v.spe = v.detailqty + "/" + spe;
              v.max = spe;
            }
          });
输入框设置
在这里插入代码片<vxe-column v-for="item in columnList" :key="item.field" :field="item.field" :title="item.title" :edit-render="{}" min-width="100">
          <template #edit="{ row }">
            <vxe-input
              v-model="row[item.field]"
              type="number"
              :max="row.max"
              placeholder="请输入"
              @blur="updateFooterEvent(row, $event)"
              @input="
                if (row[item.field] > row.max) {
                  row[item.field] = row.max;
                }
              "
            ></vxe-input>
          </template>
        </vxe-column>
完整代码
template部分
<!-- 表格 -->
      <vxe-toolbar>
        <template #buttons>
          <vxe-button @click="insertEvent(0)">新增</vxe-button>
          <vxe-button @click="deleteSelect">删除</vxe-button>
        </template>
      </vxe-toolbar>
      <vxe-table
        ref="xTable"
        border
        show-footer
        show-overflow
        :loading="loading"
        :data="partData"
        :column-config="{ resizable: false }"
        :edit-config="{ showIcon: false, trigger: 'click', mode: 'cell', activeMethod: controlrowcell }"
        :footer-method="footerMethod"
        :row-config="{ isHover: true }"
        :export-config="{}"
        class="editable-footer"
      >
        <vxe-column type="checkbox" width="50" fixed="left"></vxe-column>
        <vxe-column type="seq" title="序号" width="50" fixed="left"></vxe-column>
        <vxe-column v-for="item in columnList" :key="item.field" :field="item.field" :title="item.title" :edit-render="{}" min-width="100">
          <template #edit="{ row }">
            <vxe-input
              v-model="row[item.field]"
              type="number"
              :max="row.max"
              placeholder="请输入"
              @blur="updateFooterEvent(row, $event)"
              @input="
                if (row[item.field] > row.max) {
                  row[item.field] = row.max;
                }
              "
            ></vxe-input>
          </template>
        </vxe-column>
      </vxe-table>
script部分
<script lang="ts">
import { defineComponent, reactive } from "vue";
import baseService from "@/service/baseService";
export default defineComponent({
  setup() {
    return reactive({
      visible: false as boolean,
      loading: false as boolean,
      proPlan: {
        id: "",
        dateValue: [] as any
      } as any,
      columnList: [] as any,
      partData: [] as any,
      partList: [] as any,
      allPart: [] as any,
      oldval: 0
    });
  },
  methods: {
    controlrowcell({ row, column, columnIndex }: any) {
      this.setMax(column.title, row);
      return true;
    },
    // 设置当前点击单元格输入框的最大值
    setMax(field: any, row: any) {
      let max = row.detailqty;
      for (const key in row) {
        if (key !== "detailqty" && key !== "deptId" && key !== "spe" && key !== "deptName" && key !== "id" && key !== "_XID" && key !== "partname" && key !== field && key !== "" && key !== "max") {
          console.log(key);
          max -= row[key];
        }
      }
      row.max = max;
      console.log(row.max);
    },
    updateFooterEvent(row: any, event: any) {
      console.log(row);
      console.log(event.value);
      let spe = row.max - event.value;
      let qty = row.detailqty;
      row.spe = qty + "/" + spe;
    },
    deleteSelect() {
      const $table = this.$refs.xTable;
      const selectRecords = $table.getCheckboxRecords();
      if (selectRecords.length === 0) {
        this.$message.error("至少选择一条数据!");
        return false;
      }
      $table.removeCheckboxRow();
    },
    async insertEvent(row: any) {
      const $table = this.$refs.xTable;
      const record = {
        type: "add",
        partname: "",
        deptName: "",
        deptId: ""
      };
      const { row: newRow } = await $table.insertAt(record, row);
      await $table.setActiveCell(newRow, "partname");
    },
    changeDept(e: any) {
      for (let i = 0; i < this.deptList.length; i++) {
        if (e === this.deptList[i].id) {
          this.handDepData(e, this.deptList[i].name);
        }
      }
    },
    handDepData(id: any, name: any) {
      if (this.partData.length === 0) {
        return;
      }
      for (let i = 0; i < this.partData.length; i++) {
        if (this.partData[i].deptName == null || !this.partData[i].deptName) {
          this.partData[i].deptName = name;
          this.partData[i].deptId = id;
          this.$refs.xTable.isUpdateByRow(this.partData[i]);
        }
      }
    },
    selectPart(row: any) {
      for (let i = 0; i < this.partList.length; i++) {
        if (this.partList[i].id === row.id) {
          row.partname = this.partList[i].partname;
          row.detailqty = this.partList[i].detailqty;
        }
      }
    },
    selectDept(row: any) {
      console.log(row);
      for (let i = 0; i < this.deptList.length; i++) {
        if (this.deptList[i].id === row.id) {
          row.deptName = this.deptList[i].name;
          row.deptId = this.deptList[i].id;
        }
      }
    },
    footerMethod({ columns, data }: any) {
      return [
        columns.map((column: { property: string }, columnIndex: number) => {
          if (columnIndex === 0) {
            return "";
          }
          if (columnIndex === 1) {
            return "汇总";
          }
          if (!["partname", "deptId"].includes(column.property)) {
            if (column.property === "spe") {
              return this.sumNum(data, "detailqty");
            }
            return this.sumNum(data, column.property);
          }
          return null;
        }),
        columns.map((column: { property: string }, columnIndex: number) => {
          if (columnIndex === 0) {
            return "";
          }
          if (columnIndex === 1) {
            return "人数";
          }
          if (!["partname", "deptId"].includes(column.property)) {
            if (this.capDate.length > 0) {
              for (let i = 0; i < this.capDate.length; i++) {
                if (this.capDate[i].date.includes(column.property)) {
                  return this.sumPerson(data, column.property, Number(this.capDate[i].number));
                }
              }
            }
          }
          return null;
        })
      ];
    },
    sumNum(list: { [x: string]: any }[], field: string | number) {
      let count = 0;
      list.forEach((item: { [x: string]: any }) => {
        if (item[field]) {
          count += Number(item[field]);
        }
      });
      return count;
    },
    sumPerson(list: { [x: string]: any }[], field: string | number, num: number) {
      let count = 0;
      list.forEach((item: { [x: string]: any }) => {
        if (item[field]) {
          count += Number(item[field]);
        }
      });
      return Math.ceil(count / num);
    },
    /**
     * 获取计划明细信息
     */
    getInfo() {
      if (this.plan.id) {
        this.loading = true;
        this.proPlan = this.plan;
        this.proPlan.dateValue = [];
        if (this.plan.startdate || this.plan.enddate) {
          this.proPlan.dateValue.push(this.plan.startdate);
          this.proPlan.dateValue.push(this.plan.enddate);
        }
        this.changeDate(this.proPlan.dateValue);
        baseService.get("xxxx", { planId: this.plan.id }).then((res) => {
          if (res.code !== 0) {
            return this.$message.error(res.msg);
          }
          console.log(res.data);
          res.data.map((v: any) => {
            if (v.partname.indexOf("机架") !== -1) {
              v.spe = v.detailqty + "/0";
            } else {
              let spe = v.detailqty;
              for (const key in v) {
                if (key !== "detailqty" && key !== "deptId" && key !== "spe" && key !== "deptName" && key !== "id" && key !== "_XID" && key !== "partname" && key !== "" && key !== "max") {
                  spe -= v[key];
                }
              }
              v.spe = v.detailqty + "/" + spe;
              v.max = spe;
            }
          });
          this.partData = res.data;
          this.getPart(this.plan.bdEquipId, res.data);
          this.loading = false;
        });
      }
    },
    /**
     * 根据时间加载列
     * @param val
     */
    changeDate(val: any) {
      console.log(val.length > 0);
      if (val.length > 0) {
        this.getCapDate(val);
      }
    },
    InitColumns(val: any) {
      let all = this.getAll(val[0], val[1]);
      this.columnList = reactive([]);
      for (let i = 0; i < all.length; i++) {
        let column = reactive({
          field: all[i],
          title: all[i]
        });
        this.columnList.push(column);
      }
      //排序
      this.columnList.sort(function (A: number, B: number) {
        return A - B;
      });
    },
    /**
     * 根据时间加载 每一天时间
     * @param start 开始时间
     * @param end 结束时间
     */
    getAll(start: any, end: any) {
      let dateList = [];
      let startTime = this.getDate(start);
      let endTime = this.getDate(end);
      while (endTime.getTime() - startTime.getTime() >= 0) {
        let year = startTime.getFullYear();
        let month = startTime.getMonth() + 1 < 10 ? "0" + (startTime.getMonth() + 1) : startTime.getMonth() + 1;
        let day = startTime.getDate().toString().length == 1 ? "0" + startTime.getDate() : startTime.getDate();
        dateList.push(year + "-" + month + "-" + day);
        startTime.setDate(startTime.getDate() + 1);
      }
      return dateList;
    },
    /**
     * 时间格式处理 2022-11-11
     * @param datestr 传入的时间
     */
    getDate(datestr: any) {
      let temp = datestr.split("-");
      return new Date(temp[0], temp[1] - 1, temp[2]);
    }
});
</script>









![[Linux]----初始网络](https://img-blog.csdnimg.cn/d49ccfeec65549568fa7757e467251a3.png)

![[附源码]Python计算机毕业设计SSM基于Web学术会议投稿管理系统(程序+LW)](https://img-blog.csdnimg.cn/9fac82200f684b75803cb756148c4fe9.png)







