Commit 732bfe1da06d7367b27f4a8a3d3191e6e24e78c7

Authored by ww
1 parent 632f3eab

wip: 开发list组件

1 1 <script lang="ts" setup>
2 2 import { ReloadOutlined } from '@ant-design/icons-vue';
3   - import { Button, List, Tooltip } from 'ant-design-vue';
  3 + import { Button, List, Space, Tooltip } from 'ant-design-vue';
4 4 import { reactive } from 'vue';
5 5 import { ref } from 'vue';
  6 + import { BasicForm, useForm } from '../../Form';
  7 + import { basicListProps } from './props';
  8 + import { ExtractPropTypes } from 'vue';
  9 + defineProps<ExtractPropTypes<typeof basicListProps>>();
  10 +
  11 + const [registerForm] = useForm({
  12 + schemas: [
  13 + {
  14 + field: '123',
  15 + label: 'test',
  16 + component: 'Input',
  17 + },
  18 + ],
  19 + labelWidth: 100,
  20 + layout: 'inline',
  21 + baseColProps: { span: 8 },
  22 + showAdvancedButton: true,
  23 + compact: true,
  24 + });
6 25
7 26 const listElRef = ref<Nullable<ComponentElRef>>(null);
8 27
9   - const pagination = reactive({});
  28 + const pagination = reactive({ size: 'small' });
10 29
11 30 const loading = ref(false);
12 31
... ... @@ -16,31 +35,48 @@
16 35 </script>
17 36
18 37 <template>
19   - <section class="bg-light-50 my-4 p-4 x dark:text-gray-300 dark:bg-dark-900">
20   - <List
21   - ref="listElRef"
22   - :dataSource="dataSource"
23   - :pagination="pagination"
24   - :grid="{ gutter: 16, xs: 1, sm: 1, md: 1, lg: 2, xl: 2, xxl: 3, column: 3 }"
25   - :loading="loading"
26   - >
27   - <template #header>
28   - <section class="flex justify-between gap-4 min-h-12 items-center">
29   - <div class="text-lg font-semibold">
30   - <span>任务列表</span>
31   - </div>
32   - <Tooltip title="刷新">
33   - <Button type="primary" @click="getDataSource">
34   - <ReloadOutlined :spin="loading" />
35   - </Button>
36   - </Tooltip>
37   - </section>
38   - </template>
39   - <template #renderItem="{ item }">
40   - <List.Item :key="item.id">
41   - <slot name="item" :item="item"></slot>
42   - </List.Item>
43   - </template>
44   - </List>
  38 + <section class="basic-list-container">
  39 + <section class="mb-4 bg-light-50 p-2 x dark:text-gray-300 dark:bg-dark-900">
  40 + <BasicForm @register="registerForm" />
  41 + </section>
  42 + <section class="bg-light-50 p-2 x dark:text-gray-300 dark:bg-dark-900">
  43 + <List
  44 + ref="listElRef"
  45 + :dataSource="dataSource"
  46 + :pagination="pagination"
  47 + :grid="{ gutter: 16, xs: 1, sm: 1, md: 1, lg: 2, xl: 2, xxl: 3, column: 3 }"
  48 + :loading="loading"
  49 + >
  50 + <template #header>
  51 + <section class="flex px-5 justify-between gap-4 min-h-12 items-center">
  52 + <div class="text-lg font-semibold">
  53 + <span>任务列表</span>
  54 + </div>
  55 + <Space>
  56 + <slot name="toolbar"></slot>
  57 + <Tooltip title="刷新">
  58 + <Button type="primary" @click="getDataSource">
  59 + <ReloadOutlined :spin="loading" />
  60 + </Button>
  61 + </Tooltip>
  62 + </Space>
  63 + </section>
  64 + </template>
  65 + <template #renderItem="{ item }">
  66 + <List.Item :key="item.id">
  67 + <slot name="item" :item="item"></slot>
  68 + </List.Item>
  69 + </template>
  70 + </List>
  71 + </section>
45 72 </section>
46 73 </template>
  74 +
  75 +<style lang="less" scoped>
  76 + .basic-list-container {
  77 + :deep(.ant-list-header) {
  78 + padding-top: 0;
  79 + padding-bottom: 8px;
  80 + }
  81 + }
  82 +</style>
... ...
  1 +import type { ComputedRef, Slots } from 'vue';
  2 +import type { BasicTableProps, FetchParams } from '../types/table';
  3 +import { unref, computed } from 'vue';
  4 +import type { FormProps } from '/@/components/Form';
  5 +import { isFunction } from '/@/utils/is';
  6 +
  7 +export function useTableForm(
  8 + propsRef: ComputedRef<BasicTableProps>,
  9 + slots: Slots,
  10 + fetch: (opt?: FetchParams | undefined) => Promise<void>,
  11 + getLoading: ComputedRef<boolean | undefined>
  12 +) {
  13 + const getFormProps = computed((): Partial<FormProps> => {
  14 + const { formConfig } = unref(propsRef);
  15 + const { submitButtonOptions } = formConfig || {};
  16 + return {
  17 + showAdvancedButton: true,
  18 + ...formConfig,
  19 + submitButtonOptions: { loading: unref(getLoading), ...submitButtonOptions },
  20 + compact: true,
  21 + };
  22 + });
  23 +
  24 + const getFormSlotKeys: ComputedRef<string[]> = computed(() => {
  25 + const keys = Object.keys(slots);
  26 + return keys
  27 + .map((item) => (item.startsWith('form-') ? item : null))
  28 + .filter((item) => !!item) as string[];
  29 + });
  30 +
  31 + function replaceFormSlotKey(key: string) {
  32 + if (!key) return '';
  33 + return key?.replace?.(/form\-/, '') ?? '';
  34 + }
  35 +
  36 + function handleSearchInfoChange(info: Recordable) {
  37 + const { handleSearchInfoFn } = unref(propsRef);
  38 + if (handleSearchInfoFn && isFunction(handleSearchInfoFn)) {
  39 + info = handleSearchInfoFn(info) || info;
  40 + }
  41 + fetch({ searchInfo: info, page: 1 });
  42 + }
  43 +
  44 + return {
  45 + getFormProps,
  46 + replaceFormSlotKey,
  47 + getFormSlotKeys,
  48 + handleSearchInfoChange,
  49 + };
  50 +}
... ...
1   -import { ComponentPropsOptions } from 'vue';
  1 +import { FormProps } from '../../Form';
2 2
3   -export const props = {
  3 +export const basicListProps = {
  4 + immediate: {
  5 + type: Boolean,
  6 + default: true,
  7 + },
  8 + searchInfo: {
  9 + type: Object as PropType<Recordable>,
  10 + },
  11 + formConfig: {
  12 + type: Object as PropType<Partial<FormProps>>,
  13 + default: null,
  14 + },
4 15 title: {
5 16 type: String,
6 17 },
7   -} as ComponentPropsOptions;
  18 + titleHelpMessage: {
  19 + type: [String, Array] as PropType<string | string[]>,
  20 + },
  21 + autoCreateKey: {
  22 + type: Boolean,
  23 + default: true,
  24 + },
  25 + api: {
  26 + type: Function as PropType<Fn<any, Promise<any>>>,
  27 + },
  28 + beforeFetch: {
  29 + type: Function as PropType<Fn>,
  30 + },
  31 + afterFetch: {
  32 + type: Function as PropType<Fn>,
  33 + },
  34 + handleSearchInfoFn: {
  35 + type: Function as PropType<Fn>,
  36 + },
  37 +};
... ...
  1 +import { FormProps } from 'ant-design-vue/es/form/Form';
  2 +
  3 +export interface BasicListProps {
  4 + /**
  5 + * @description 立即执行
  6 + */
  7 + immediate?: boolean;
  8 +
  9 + /**
  10 + * @description 额外的请求参数
  11 + */
  12 + searchInfo?: Recordable;
  13 +
  14 + /**
  15 + * @description 搜索表单
  16 + */
  17 + formConfig?: Partial<FormProps>;
  18 +
  19 + /**
  20 + * @description 列表名
  21 + */
  22 + title?: string;
  23 +
  24 + /**
  25 + * @description 列表标题帮助信息
  26 + */
  27 + titleHelpMessage?: string | string[];
  28 +
  29 + /**
  30 + * @description 自动创建key
  31 + */
  32 + autoCreateKey?: boolean;
  33 +
  34 + /**
  35 + * @description 请求接口
  36 + * @param args
  37 + * @returns
  38 + */
  39 + api?: (...args: any) => Promise<any>;
  40 +
  41 + /**
  42 + * @description 请求前对参数处理
  43 + */
  44 + beforeFetch?: Fn;
  45 +
  46 + /**
  47 + * @description 请求后对结果处理
  48 + */
  49 + afterFetch?: Fn;
  50 +
  51 + /**
  52 + * @description 请求前处理搜索参数
  53 + */
  54 + handleSearchInfoFn?: Fn;
  55 +}
... ...