table.vue 2.96 KB
<script setup lang="ts">
import { computed, ref } from 'vue';
import { Col, Row, Table } from '@arco-design/web-vue';
import { AnyObject, sizeType } from '@/types/global';
import usePagination from '@/hooks/pagination';

type PropType = {
  loading?: boolean;
  rowKey?: string;
  hoverType?: string;
  simplePage?: boolean;
  pageSize?: number;
  size?: sizeType;
  onQuery: (params?: AnyObject) => Promise<any>;
};

defineEmits<{ (e: 'rowSort', dataIndex: string, direction: string): void }>();

const props = withDefaults(defineProps<PropType>(), { loading: false, rowKey: 'id', size: 'small', pageSize: 20 });
const { pagination, setPage, setPageSize, setTotal } = usePagination({
  simple: props.simplePage,
  size: props.size,
  pageSize: props.pageSize,
});
const list = ref<any[]>([]);
const tableRef = ref();

const pageQueryParams = computed(() => {
  return { page: pagination.value.current, pageSize: pagination.value.pageSize };
});

const hoverType = computed(() => props.hoverType || 'default');

const onFetch = () =>
  props.onQuery(pageQueryParams.value).then(({ data, meta }) => {
    list.value = data;
    setPage(meta.current);
    setTotal(meta.total);
    setPageSize(meta.limit);
  });

const onPageChange = (page: number) => {
  setPage(page || 1);
  onFetch();
};

const onSizeChange = (size: number) => {
  setPageSize(size);
  setPage(1);
  onFetch();
};

const onPush = (row: unknown) => {
  list.value.unshift(row);
  // eslint-disable-next-line no-plusplus
  ++pagination.value.total;
};

const onRemove = (index: number) => {
  list.value.splice(index, 1);
  // eslint-disable-next-line no-plusplus
  --pagination.value.total;
};

const resetSort = () => tableRef.value?.clearSorters();

const getCount = () => pagination.value.total;

const formatSortType = (type: string): string => type?.replace('end', '') ?? '';

defineExpose({ onFetch, onPageChange, onSizeChange, resetSort, getCount, onPush, onRemove });
</script>

<template>
  <Row justify="space-between" align="center">
    <Col flex="1" class="table-tool-item" style="text-align: left">
    <slot name="tool" :size="size" />
    </Col>
    <Col flex="auto" class="table-tool-item" style="text-align: right">
    <slot name="tool-right" :size="size" />
    </Col>
  </Row>
  <Table ref="tableRef" v-bind="$attrs" :row-key="rowKey as string" :loading="loading as boolean" :size="size as sizeType"
    :data="list" :pagination="pagination" :bordered="false" :table-layout-fixed="true" @page-change="onPageChange"
    @page-size-change="onSizeChange"
    @sorter-change="(dataIndex, direction) => $emit('rowSort', dataIndex, formatSortType(direction))">
    <template #columns>
      <slot />
    </template>
  </Table>
</template>

<style lang="less" scoped>
:deep(.arco-table-cell) {
  padding: 5px 8px !important;

  :hover {
    cursor: v-bind(hoverType);
  }

  &>.arco-table-td-content .arco-btn-size-small {
    padding: 5px !important;
  }
}

:deep(.table-tool-item) {
  >* {
    margin-bottom: 12px !important;
  }
}
</style>