字段配置类型名修改
笑笑 编写于 2023-04-26 22:42:15
NewLife.CubeVue
<script lang="tsx">
import { Method } from 'axios';
import { defineComponent, PropType } from 'vue';
import { NormalTable, TableHandler, TablePagination, TableSearch } from './';
export default defineComponent({
  name: 'AdvancedTable',
  props: {
    // 搜索条件列表
    searchList: {
      type: Array as PropType<any[]>,
      default: [],
    },
    // 操作列表
    tableHandlerList: {
      type: Array as PropType<any[]>,
      default: [],
    },
    // 表格数据
    tableDataList: {
      type: Array as PropType<any[]>,
      default: null,
    },
    // 表格列配置
    columns: {
      type: Array as PropType<any[]>,
      default: [],
    },
    // 表格数据请求地址,如果设置了tableData,url参数将不会生效
    url: {
      type: String as PropType<string>,
      require: true,
      default: '',
    },
    // 显示搜索条件区
    showSearch: {
      type: Boolean as PropType<boolean>,
      default: true,
    },
    // 显示操作区
    showHandler: {
      type: Boolean as PropType<boolean>,
      default: true,
    },
    // 显示分页
    showPagination: {
      type: Boolean as PropType<boolean>,
      default: true,
    },
    // 请求数据前的过滤方法
    beforeGetDataList: {
      type: Function,
      require: false,
    },
    // 请求数据后的过滤方法
    afterGetDataList: {
      type: Function,
      require: false,
    },
    // 当此组件的父级不是整个页面而是某个组件,需要设置父级,以便操作方法能被找到
    tableParent: {
      type: Object,
      require: false,
    },
    /**
     * 请求方法,默认get
     */
    requestMethod: {
      type: String as PropType<string>,
      default: 'get',
    },
  },
  data() {
    return {
      // 组件激活状态,默认true。失活时置为false,被激活时判断该值,
      // 如果为false则更新列表数据,避免第一次创建组件时激活重复获取数据
      activated: true,
      loadingTable: false,
      showTable: true,
      // 批量选中的数据
      selectList: [],
      // 表格数据
      tableData: [] as any[],
      // 分页参数
      page: {
        pageSize: 10,
        pageIndex: 1,
        total: 0,
        totalCount: 0,
        desc: true,
        sort: undefined,
      },
      // 搜索参数
      searchParams: {},
      // 搜索框高度
      tableSearchHeight: 50,
    };
  },
  computed: {
    // 非表格的其它组件高度
    nonTableHeight() {
      const vm = this as any;
      return (
        vm.tableSearchHeight +
        (vm.showHandler ? 50 : 0) +
        (vm.showPagination ? 50 : 0)
      );
    },
    // 表格高度
    normalTableHeight() {
      const vm = this as any;
      return `calc(100% - ${vm.nonTableHeight + 3}px)`;
    },
  },
  watch: {
    tableDataList(val) {
      this.tableData = this.tableDataList;
    },
  },
  mounted() {
    this.getDataList();

    // 手动触发一次
    this.resize();
    window.addEventListener('resize', this.resize);
  },
  beforeDestroy() {
    window.removeEventListener('resize', this.resize);
  },
  activated() {
    if (!this.activated) {
      this.activated = true;
      this.getDataList();
    }
  },
  deactivated() {
    this.activated = false;
  },
  methods: {
    // 获取表格数据
    getDataList() {
      if (this.tableDataList) {
        this.tableData = this.tableDataList;
        return;
      }

      const searchParams = this.searchParams as any;
      const data = {
        // limit: this.page.pageSize,
        // offset: this.page.pageIndex - 1,
        // currentPage: this.page.pageIndex,
        keyWord: searchParams.txtKeywords,
        ...this.page,
        ...searchParams,
      };

      if (this.beforeGetDataList) {
        this.beforeGetDataList(data);
      }

      this.loadingTable = true;
      this.$http(this.url, {
        method: this.requestMethod as Method,
        data: this.requestMethod.toLowerCase() == 'get' ? null : data,
        params: this.requestMethod.toLowerCase() == 'get' ? data : null,
      }).then((res) => {
        this.tableData = res.data.list || res.data.rows || res.data;

        if (res.data.pagerModel) {
          this.page.total = res.data.pagerModel.total;
        } else if ((res as any).page) {
          this.page.total = parseInt((res as any).page.totalCount || 0);
        } else {
          this.page.total = res.data.total || 0;
        }

        if (this.afterGetDataList) {
          this.afterGetDataList(res.data);
        }
        this.loadingTable = false;
      });
    },
    resetSearch() {
      this.page = {
        pageSize: 10,
        pageIndex: 1,
        total: 0,
        totalCount: 0,
        desc: true,
        sort: undefined,
      };
      this.searchParams = {};
      this.getDataList();
    },
    // 子组件调用此方法,再通过参数action调用本组件方法
    handler(option: any, data: any, callback: any) {
      const vm = this as any;
      const handler = option.handler;
      let func;

      // 优先查找指定父级组件方法,高级表格组件独有
      if (this.tableParent) {
        func = (this.tableParent as any)[handler];
      }

      // 再查找当前组件父级组件方法,高级表格组件独有
      if (!func && this.$parent) {
        func = (this.$parent as any)[handler];
      }

      if (!func) {
        func = vm[handler];
      }

      if (!func || typeof func !== 'function') {
        const msg = `未实现的方法:${handler},或请设置属性=>:table-parent="this"`;
        console.error(msg);
        vm.$message.error(msg);
      } else {
        const returnData = (func as Function).call(vm, data);
        if (typeof callback === 'function') {
          callback(returnData);
        }
      }
    },
    // 设置选中的行数
    setSelectList(list: any) {
      this.selectList = list;
    },
    // 设置显示的表头
    setColumns(list: any) {
      //   this.showTable = false
      //   this.$nextTick(() => {
      //     this.showTable = true
      //   })
    },
    resize() {
      const vm = this as any;

      vm.$nextTick(() => {
        const tableSearch = vm.$refs.tableSearch;

        if (tableSearch) {
          // 由于搜索条件个数不确定,可能会换行,因此需要根据实际高度再调整表格高度
          vm.tableSearchHeight = tableSearch.$el.offsetHeight;
          // setTimeout(() => {
          //   tableSearch.doLayout()
          // }, 1000)
        } else {
          vm.tableSearchHeight = 0;
        }
      });
    },
    handlerSortChange({ col, prop, order }: any) {
      console.log(col, prop, order);

      if (order === 'ascending') {
        this.page.desc = false;
        this.page.sort = prop;
      } else if (order === 'descending') {
        this.page.desc = true;
        this.page.sort = prop;
      } else {
        this.page.desc = true;
        this.page.sort = undefined;
      }
      this.getDataList();
    },
  },
  render(ctx: any) {
    return (
      <div style={{ height: '100%' }}>
        {ctx.showSearch ? (
          <TableSearch
            ref="tableSearch"
            v-model={ctx.searchParams}
            columns={ctx.searchList}
            onGetDataList={ctx.getDataList}
            onResetSearch={ctx.resetSearch}
            v-slots={ctx.$slots}
          />
        ) : (
          ''
        )}
        {ctx.showHandler ? (
          <TableHandler
            ref="tableHandler"
            columns={ctx.columns}
            tableHandlerList={ctx.tableHandlerList}
            searchParams={ctx.searchParams}
            onHandlerClick={ctx.handler}
            v-slots={ctx.$slots}
          />
        ) : (
          ''
        )}
        {ctx.showTable ? (
          <NormalTable
            ref="normalTable"
            v-loading={ctx.loadingTable}
            columns={ctx.columns}
            tableData={ctx.tableData}
            normalHeight={ctx.normalTableHeight}
            onSelectionChange={ctx.setSelectList}
            onHandlerClick={ctx.handler}
            onSortChange={ctx.handlerSortChange}
            {...ctx.$attrs}
            v-slots={ctx.$slots}
          ></NormalTable>
        ) : (
          ''
        )}
        {ctx.showPagination ? (
          <TablePagination
            ref="tablePagination"
            onPageChange={ctx.getDataList}
            v-model={ctx.page}
          />
        ) : (
          ''
        )}
      </div>
    );
  },
});
</script>