<template>
  <div>
    <vxe-grid ref="refGrid" v-bind="gridOptions" v-on="gridEvents" :footerData="setFooterData">
      <template #select="{ row, column }">
        <vxe-select v-model="row[column.field]" filterable @change="handleCol4Change(row, column, $event)">
          <vxe-option v-for="(opt, optIndex) in column.editRender.options" :key="optIndex" :label="opt" :value="opt"></vxe-option>
        </vxe-select>
      </template>
      <template #select_dynamic="{ row, column }">
        <div style="display: flex; flex-wrap: wrap; gap: 8px; align-items: center">
          <vxe-select v-model="row[column.field]" filterable :disabled="!column.editRender.getOptions?.(row)?.length" style="min-width: 120px">
            <vxe-option v-for="(opt, optIndex) in column.editRender.getOptions?.(row) || []" :key="optIndex" :label="opt" :value="opt" />
          </vxe-select>
        </div>
      </template>
      <template #other_input="{ row, column }">
        <vxe-input
          v-model="row[column.field]"
          placeholder="请输入"
          :disabled="!(row.COL1 === '其他' || row.COL001 === '其他' || row.COL016 === '其他' || row.COL4 === '其他')"
        />
      </template>
      <template #input="{ row, column }">
        <vxe-input
          v-model="row[column.field]"
          placeholder="请输入"
          :disabled="!(row.COL4 === '软件类(银行业)' || row.COL4 === '软件类(保险业)') || row.COL5 !== '其他'"
        />
      </template>
      <template #default_select="{ row, column }">
        <span>{{ row[column.field] }}</span>
      </template>
      <template #default_other="{ row, column }">
        <span v-if="row.COL1 === '其他' || row.COL001 === '其他' || row.COL016 === '其他' || row.COL4 === '其他'"> {{ row[column.field] }}</span>
      </template>
      <template #default_input="{ row, column }">
        <span v-if="(row.COL4 === '软件类(银行业)' || row.COL4 === '软件类(保险业)') && row.COL5 === '其他'"> {{ row[column.field] }}</span>
      </template>

      <template #footer_seq="{ row, column }">
        <span style="color: blue">{{ row[column.field] }}</span>
      </template>

      <template #footer_num="{ row, column }">
        <span style="color: red">{{ row[column.field] }}</span>
      </template>

      <template #action="{ row, rowIndex }">
        <vxe-button mode="text" status="primary" icon="vxe-icon-add" @click="insertRow(row, rowIndex)"></vxe-button>
        <vxe-button mode="text" status="error" icon="vxe-icon-delete" @click="removeRow(row, rowIndex)"></vxe-button>
      </template>
    </vxe-grid>
  </div>
</template>

<script lang="ts" setup>
  import { reactive, computed, ref } from 'vue';
  import type { VxeGridProps, VxeTablePropTypes, VxeGridListeners } from 'vxe-table';
  import type { VxeSelectProps } from 'vxe-pc-ui';

  const props = defineProps({
    title: String,
    data: {
      type: Array as () => any[],
      default: () => [],
    },
    columns: {
      type: Array as () => any[],
      required: true,
    },
    footerData: {
      type: Array as () => any[],
      default: () => [],
    },
    showFooter: {
      type: Boolean,
      default: false,
    },
    height: {
      default: '',
    },
    rowHeight: {
      type: [Number, String],
      default: 40,
    },
  });

  const formData = reactive({});

  const formFooterData = reactive({});

  const handleCol4Change = (row, column, value) => {
    if (column.field === 'COL4') {
      row.COL5 = '';
    }
  };

  const sumNum = (list: any[], field: string) => {
    let count = 0;
    list.forEach((item) => {
      if (item[field]) {
        count += Number(item[field]);
      }
    });
    return count;
  };

  const gridOptions = reactive<VxeGridProps<any> & { editConfig: VxeTablePropTypes.EditConfig<any> }>({
    border: true,
    showOverflow: true,
    showFooter: props.showFooter,
    loading: false,
    editConfig: {
      enabled: true,
      trigger: 'click',
      mode: 'row',
    },
    height: props.height,
    rowConfig: {
      useKey: true,
      resizable: true,
      height: props.rowHeight,
    },
    columnConfig: {
      useKey: true,
      resizable: true,
    },
    toolbarConfig: {
      zoom: true,
      custom: true,
      buttons: [{ name: '添加', mode: 'text', status: 'primary', code: 'myAdd', icon: 'vxe-icon-add' }],
    },
    columns: props.columns,
    data: props.data || [],
    footerData: props.footerData || [],
  });

  const setFooterData = computed(() => {
    if (!props.footerData || !props.footerData.length) return [];

    const footer = [...props.footerData];
    const result = [];

    footer.forEach((item) => {
      // 创建基础行对象
      const row = {
        [item.labelField]: item.labelValue,
      };

      // 计算需要求和的字段
      if (item.tp === 'sum' && gridOptions.data?.length) {
        item.fields.forEach((field) => {
          row[field] = sumNum(gridOptions.data, field);
          formFooterData[item.xmlCode[field]] = row[field];
        });
      }

      // 如果需要计算平均值
      if (item.tp === 'avg' && gridOptions.data?.length) {
        item.fields.forEach((field) => {
          const sum = sumNum(gridOptions.data, field);
          row[field] = sum / gridOptions.data.length;
          formFooterData[item.xmlCode[field]] = row[field];
        });
      }

      result.push(row);
    });

    return result;
  });

  const safeAddNewRecord = async () => {
    try {
      const newRecord: Record<string, any> = {};
      gridOptions.data?.unshift(newRecord);
    } catch (error) {
      console.error('添加记录出错:', error);
    }
  };

  const insertRow = async (row: any, ind: number) => {
    gridOptions.data?.splice(ind + 1, 0, {});
    refGrid.value.setEditRow(gridOptions.data[ind + 1]);
  };

  const removeRow = async (row: any, ind: number) => {
    cancelRow();
    gridOptions.data?.splice(ind, 1);
  };

  const gridEvents: VxeGridListeners = {
    toolbarButtonClick(params) {
      if (params.code == 'myAdd') {
        safeAddNewRecord();
      }
    },
  };

  const refGrid = ref();

  const getFormData = async () => {
    await cancelRow();
    const fieldNames = getAllFields(props.columns);
    const newDatas =
      gridOptions.data?.map((obj) => {
        return fieldNames.reduce((acc, field) => {
          if (field in obj && obj[field] !== undefined && obj[field] !== null) {
            acc[field] = obj[field];
          }
          return acc;
        }, {});
      }) || [];

    return {
      ...formData,
      datas: newDatas,
      footer: formFooterData,
    };
  };

  const setFormData = (dataVale) => {
    gridOptions.data = dataVale;
  };

  const cancelRow = async () => {
    const $grid = refGrid.value;
    if (!$grid) {
      return;
    }
    await $grid.clearEdit();
  };

  function getAllFields(columns: any[]): string[] {
    const fields: string[] = [];

    function traverse(items: any[]) {
      items.forEach((item) => {
        if (item.field) {
          fields.push(item.field);
        }
        if (item.children) {
          traverse(item.children);
        }
      });
    }

    traverse(columns);
    return fields.filter((field) => field);
  }

  defineExpose({
    getFormData,
    setFormData,
  });
</script>
-
