Eight, Vben framework dynamically generates editable Table

        During the development process, the product manager put forward some strange requirements, which made people very confused. When asked, the customer's needs were like this, so we could only think of various methods for development.

        Recently, two requirements have been raised,

        The first one is to add the date between the two times to the bottom table according to the time selection when selecting the date, and the bottom is the effect after realization.

        The second is the dynamic adding process module, which includes not only tabs, tables, but also components such as forms, and operations such as adding rows and deleting rows. This operation is quite annoying and very difficult to implement.

        Well, there is a saying, "The unburned bird is the phoenix". Only by going forward fearlessly can we be reborn from Nirvana, and finally it is realized. Let me explain it to you in detail.

        First look at the composition of the file, the update.vue file is the main page, and the updateSon.vue file is the underlying process file as its sub-page.

The first requirement realization plan:

1. First, analyze and obtain his time interval

//当时间改变的时候触发handleChangeDate方法
<template #date="{ model, field }">
          <RangePicker
            v-model:value="model[field]"
            valueFormat="YYYY-MM-DD"
            format="YYYY-MM-DD"
            style="
               {
                width: '100%';
              }
            "
            @change="handleChangeDate"
          />
 </template>


//在script里写方法,使用provide依赖注入一下,方便子组件无限级使用。
  // 选择周期
  const dateList = ref([]);
  function handleChangeDate(e) {
    setFieldsValue({ demandPlanningCycleStart: e[0], demandPlanningCycleEnd: e[1] });
    dateList.value = enumerateDaysBetweenDates(e[0], e[1]);
  }
  provide('dateList', dateList);

//处理时间函数,return时间区间
  function enumerateDaysBetweenDates(startDate, endDate) {
    // 假定你已经保证了startDate 小于endDate,且二者不相等
    let daysList = [];
    let SDate = moment(startDate);
    let EDate = moment(endDate);
    daysList.push(SDate.format('MM-DD'));
    while (SDate.add(1, 'days').isBefore(EDate)) {
      // 注意这里add方法处理后SDate对象已经改变。
      daysList.push(SDate.format('MM-DD'));
    }
    daysList.push(EDate.format('MM-DD'));
    return daysList;
  }

2. Get the dateList in the updateSon.vue page and add it to the columns of the Table.

//在BasicTable里面循环增加tamplate
//ifDetail是在详情展示的时候是他不被编辑


 <template #[`planDay${idx+1}`]="{ record }" v-for="(val, idx) in dateList" :key="idx">
      <InputNumber
      :precision="2"
      @blur="handleDataInsert"
      placeholder="请输入"
      :disabled="ifDetail"
      v-model:value="record[`planDay${idx + 1}`]"
      />
</template>


//获取到dateList的值
  const dateList: any = inject('dateList');

//在watch监听的时候监听这个值,然后将新出现的日期插入columns里面
//item.demandPlanDetailList.tableMethods.getColumns()获取到了最新的columns
//columns为

  watch(
    dateList,
    (newVal, oldVal) => {
      purchasePlan.value.forEach((item) => {
        const columns1: any = [];
        const tableColumns = item.demandPlanDetailList.tableMethods.getColumns();
        if (newVal.length) {
          newVal.forEach((date, index) => {
            columns1.push({
              title: date,
              width: 140,
              slots: { customRender: `planDay${index + 1}` },
              dataIndex: `planDay${index + 1}`,
            });
          });
          columns1.push({
            title: '合计',
            width: 140,
            slots: { customRender: 'planDayDemandSum' },
            dataIndex: 'planDayDemandSum',
          });
        }
        if (oldVal.length) {
//删除原先插入的
          tableColumns.splice(11, oldVal.length + 1);
        }
//增加最新的进去
        tableColumns.splice(11, 0, ...columns1);
        item.plannedOutputDetail.tableMethods.setColumns(columns);
        item.demandPlanDetailList.tableMethods.setColumns(tableColumns);
      });
    },
    { deep: true },
  );


The second requirement realization plan

  1. First of all, we should pass a default value to the child component for display
//当然也需要provide依赖注入一下,方便子组件无限级使用。
const purchasePlan = ref([]);
 provide('purchasePlan', purchasePlan);

 //默认新增数据,最重要的是无论schemas和table里面的columns都要使用cloneDeep解除他们的深度绑定,才能重复使用。
  const addData = (datalist) => {
    const [registerForm, formMethods] = useForm({
      baseColProps: {
        span: 8,
      },
      layout: 'vertical',
      labelWidth: 140,
      schemas: cloneDeep(UpdateFormStaticSchema()),
      showActionButtonGroup: false,
    });
    const [registerPlanTable, tablePlanMethods] = useTable({
      ...
    });
    const [registerTable, tableMethods] = useTable({
      ...
    });
    const [registerOtherTable, tableOtherMethods] = useTable({
      ...
    });
    const [registerPriceTable, tablePriceMethods] = useTable({
     ...
    });
    datalist.push({
      activeKey: 0,
      form: {
        form: registerForm,
        formMethods: formMethods,
      },
      plannedOutputDetail: {
        table: registerPlanTable,
        tableMethods: tablePlanMethods,
      },
      demandPlanDetailList: {
        table: registerTable,
        tableMethods: tableMethods,
      },
      otherCostDetailList: {
        table: registerOtherTable,
        tableMethods: tableOtherMethods,
      },
      operation: {
        table: registerPriceTable,
        tableMethods: tablePriceMethods,
      },
    });
  };

2. We must make it clear that when clicking to add a process, the name of the table must not be hard-coded, so it must be assigned a value

//按钮触发方法    
//purchasePlan为原需要展示几个工序,从外面获取,默认是1个
<a-button
 	style="margin-right: 15px"
    type="primary"
    @click="addPurchasePlanListBtn(purchasePlan)"
   >
   添加工序
</a-button>

//获取数据
const purchasePlan: any = inject('purchasePlan');

//最重要的是这步,让他的所有的方法和form和table增加到purchasePlan中
  const addPurchasePlanListBtn = (datalist) => {
    const [registerForm, formMethods] = useForm({
      ...
    });
    const [registerTable, tableMethods] = useTable({
     ...
    });
    const [registerPlanTable, tablePlanMethods] = useTable({
      ...
    });
    const [registerOtherTable, tableOtherMethods] = useTable({
      ...
    });
    const [registerPriceTable, tablePriceMethods] = useTable({
      ...
    });
    datalist.push({
      activeKey: 0,
      form: {
        form: registerForm,
        formMethods: formMethods,
      },
      plannedOutputDetail: {
        table: registerPlanTable,
        tableMethods: tablePlanMethods,
      },
      demandPlanDetailList: {
        table: registerTable,
        tableMethods: tableMethods,
      },
      otherCostDetailList: {
        table: registerOtherTable,
        tableMethods: tableOtherMethods,
      },
      operation: {
        table: registerPriceTable,
        tableMethods: tablePriceMethods,
      },
    });
  };

        Now that this step has been realized, everyone will understand how it is added, and all the above tables and forms will be created every time it is added.

Well, this is the end of today's sharing. If you still don't understand anything, you can leave a message. I will answer them one by one.

Guess you like

Origin blog.csdn.net/qq_43185384/article/details/129161833