Showing
4 changed files
with
202 additions
and
31 deletions
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> | ... | ... |
src/components/List/src/hooks/useListForm.ts
0 → 100644
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 | +}; | ... | ... |
src/components/List/src/types/list.ts
0 → 100644
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 | +} | ... | ... |