@peng_kai/kit 0.0.13 → 0.0.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. package/admin/components/scroll-nav/src/ScrollNav.vue +59 -59
  2. package/admin/components/text/index.ts +13 -13
  3. package/admin/components/text/src/Amount.vue +114 -114
  4. package/admin/components/text/src/Datetime.vue +44 -44
  5. package/admin/components/text/src/Duration.vue +26 -26
  6. package/admin/components/text/src/Hash.vue +40 -40
  7. package/admin/components/text/src/createTagGetter.ts +13 -13
  8. package/admin/defines/defineRoute.helpers.ts +10 -3
  9. package/admin/filter/FilterDrawer.vue +96 -96
  10. package/admin/filter/FilterParam.vue +76 -76
  11. package/admin/hooks/useMenu.ts +128 -128
  12. package/admin/hooks/usePage.ts +139 -139
  13. package/admin/hooks/usePageTab.ts +35 -35
  14. package/admin/layout/large/Breadcrumb.vue +70 -70
  15. package/admin/layout/large/Content.vue +24 -24
  16. package/admin/layout/large/Menu.vue +68 -68
  17. package/admin/layout/large/PageTab.vue +71 -71
  18. package/admin/styles/globalCover.scss +43 -43
  19. package/antd/components/InputNumberRange.vue +47 -47
  20. package/antd/directives/formLabelAlign.ts +30 -30
  21. package/antd/hooks/useAntdDrawer.ts +73 -73
  22. package/antd/hooks/useAntdTable.ts +70 -70
  23. package/components/infinite-query/index.ts +1 -1
  24. package/components/infinite-query/src/InfiniteQuery.vue +147 -147
  25. package/components/infinite-query/src/useCreateTrigger.ts +35 -35
  26. package/package.json +40 -40
  27. package/pnpm-lock.yaml +598 -0
  28. package/request/helpers.ts +32 -32
  29. package/request/interceptors/popupMessage.ts +2 -2
  30. package/request/interceptors/unitizeAxiosError.ts +2 -2
  31. package/request/type.d.ts +89 -89
  32. package/tsconfig.json +17 -17
  33. package/utils/index.ts +10 -0
@@ -1,71 +1,71 @@
1
- <script setup lang="ts">
2
- import { Tabs as ATabs, TabPane as ATabPane } from "ant-design-vue";
3
- import { getDependencies } from "../../../kitDependencies";
4
-
5
- const { usePageTab } = getDependencies()
6
- const { activeTab, tabList, openTab, closeTab } = usePageTab()
7
- </script>
8
-
9
- <template>
10
- <ATabs
11
- class="app-page-tabs"
12
- :activeKey="activeTab"
13
- type="editable-card"
14
- size="small"
15
- :animated="false"
16
- :hideAdd="true"
17
- :tabBarGutter="4"
18
- @tabClick="(openTab as any)"
19
- @edit="(closeTab as any)"
20
- >
21
- <ATabPane v-for="tab of tabList" :key="tab.key" :tab="tab.title">
22
- <template #closeIcon>
23
- <i class="i-icon-park-outline:close" />
24
- </template>
25
- </ATabPane>
26
- </ATabs>
27
- </template>
28
-
29
- <style scoped lang="scss">
30
- .app-page-tabs {
31
- :deep(.ant-tabs-nav) {
32
- margin: 0;
33
- }
34
-
35
- :deep(.ant-tabs-nav::before) {
36
- display: none;
37
- }
38
-
39
- :deep(.ant-tabs-tab) {
40
- --uno: 'border-rd-3px! text-14px p-[3px_1px_3px_8px]! select-none';
41
- }
42
-
43
- :deep(.ant-tabs-tab .ant-tabs-tab-btn) {
44
- transform: translateX(8px);
45
- }
46
-
47
- :deep(.ant-tabs-tab-active) {
48
- --uno: 'border-[currentColor]!';
49
- }
50
-
51
- :deep(.ant-tabs-tab-remove) {
52
- display: flex;
53
- height: 100%;
54
- align-items: center;
55
- margin: 0;
56
- opacity: 0;
57
- transition: all 150ms;
58
- }
59
-
60
- :deep(.ant-tabs-tab:hover .ant-tabs-tab-btn),
61
- :deep(.ant-tabs-tab-active .ant-tabs-tab-btn) {
62
- transform: translateX(0);
63
- }
64
-
65
- :deep(.ant-tabs-tab:hover .ant-tabs-tab-remove),
66
- :deep(.ant-tabs-tab-active .ant-tabs-tab-remove) {
67
- margin-left: 0;
68
- opacity: 1;
69
- }
70
- }
71
- </style>
1
+ <script setup lang="ts">
2
+ import { Tabs as ATabs, TabPane as ATabPane } from "ant-design-vue";
3
+ import { getDependencies } from "../../../kitDependencies";
4
+
5
+ const { usePageTab } = getDependencies()
6
+ const { activeTab, tabList, openTab, closeTab } = usePageTab()
7
+ </script>
8
+
9
+ <template>
10
+ <ATabs
11
+ class="app-page-tabs"
12
+ :activeKey="activeTab"
13
+ type="editable-card"
14
+ size="small"
15
+ :animated="false"
16
+ :hideAdd="true"
17
+ :tabBarGutter="4"
18
+ @tabClick="(openTab as any)"
19
+ @edit="(closeTab as any)"
20
+ >
21
+ <ATabPane v-for="tab of tabList" :key="tab.key" :tab="tab.title">
22
+ <template #closeIcon>
23
+ <i class="i-icon-park-outline:close" />
24
+ </template>
25
+ </ATabPane>
26
+ </ATabs>
27
+ </template>
28
+
29
+ <style scoped lang="scss">
30
+ .app-page-tabs {
31
+ :deep(.ant-tabs-nav) {
32
+ margin: 0;
33
+ }
34
+
35
+ :deep(.ant-tabs-nav::before) {
36
+ display: none;
37
+ }
38
+
39
+ :deep(.ant-tabs-tab) {
40
+ --uno: 'border-rd-3px! text-14px p-[3px_1px_3px_8px]! select-none';
41
+ }
42
+
43
+ :deep(.ant-tabs-tab .ant-tabs-tab-btn) {
44
+ transform: translateX(8px);
45
+ }
46
+
47
+ :deep(.ant-tabs-tab-active) {
48
+ --uno: 'border-[currentColor]!';
49
+ }
50
+
51
+ :deep(.ant-tabs-tab-remove) {
52
+ display: flex;
53
+ height: 100%;
54
+ align-items: center;
55
+ margin: 0;
56
+ opacity: 0;
57
+ transition: all 150ms;
58
+ }
59
+
60
+ :deep(.ant-tabs-tab:hover .ant-tabs-tab-btn),
61
+ :deep(.ant-tabs-tab-active .ant-tabs-tab-btn) {
62
+ transform: translateX(0);
63
+ }
64
+
65
+ :deep(.ant-tabs-tab:hover .ant-tabs-tab-remove),
66
+ :deep(.ant-tabs-tab-active .ant-tabs-tab-remove) {
67
+ margin-left: 0;
68
+ opacity: 1;
69
+ }
70
+ }
71
+ </style>
@@ -1,43 +1,43 @@
1
- :root {
2
- // table 组件头部圆角设为 0
3
- .ant-table-wrapper {
4
- .ant-table .ant-table-header,
5
- table,
6
- .ant-table-container table > thead > tr:first-child > *:first-child,
7
- .ant-table-container table > thead > tr:first-child > *:last-child {
8
- border-radius: 0;
9
- }
10
-
11
- .ant-pagination {
12
- margin-bottom: 0;
13
- }
14
- }
15
-
16
-
17
- // 隐藏在 sticky 模式下的滚动条
18
- .ant-table-sticky-scroll {
19
- display: none;
20
- }
21
-
22
- // 卡片
23
- .ant-card .ant-card-actions > li > span {
24
- cursor: inherit;
25
- }
26
-
27
- // Tab 溢出出现下列框时
28
- .ant-tabs-dropdown-menu-title-content {
29
- display: flex;
30
- align-items: center;
31
- justify-content: space-between;
32
- }
33
-
34
- // 表格
35
- .ant-table-wrapper {
36
- .ant-table-row-expand-icon-collapsed::before {
37
- height: 1.5px;
38
- }
39
- .ant-table-row-expand-icon-collapsed::after {
40
- width: 1.5px;
41
- }
42
- }
43
- }
1
+ :root {
2
+ // table 组件头部圆角设为 0
3
+ .ant-table-wrapper {
4
+ .ant-table .ant-table-header,
5
+ table,
6
+ .ant-table-container table > thead > tr:first-child > *:first-child,
7
+ .ant-table-container table > thead > tr:first-child > *:last-child {
8
+ border-radius: 0;
9
+ }
10
+
11
+ .ant-pagination {
12
+ margin-bottom: 0;
13
+ }
14
+ }
15
+
16
+
17
+ // 隐藏在 sticky 模式下的滚动条
18
+ .ant-table-sticky-scroll {
19
+ display: none;
20
+ }
21
+
22
+ // 卡片
23
+ .ant-card .ant-card-actions > li > span {
24
+ cursor: inherit;
25
+ }
26
+
27
+ // Tab 溢出出现下列框时
28
+ .ant-tabs-dropdown-menu-title-content {
29
+ display: flex;
30
+ align-items: center;
31
+ justify-content: space-between;
32
+ }
33
+
34
+ // 表格
35
+ .ant-table-wrapper {
36
+ .ant-table-row-expand-icon-collapsed::before {
37
+ height: 1.5px;
38
+ }
39
+ .ant-table-row-expand-icon-collapsed::after {
40
+ width: 1.5px;
41
+ }
42
+ }
43
+ }
@@ -1,47 +1,47 @@
1
- <script setup lang="ts">
2
- import { computed } from "vue";
3
- import { Form, InputNumber as AInputNumber } from 'ant-design-vue'
4
-
5
- const props = withDefaults(
6
- defineProps<{
7
- value: [number, number]
8
- min?: number
9
- max?: number
10
- }>(),
11
- {
12
- min: Number.NEGATIVE_INFINITY,
13
- max: Number.POSITIVE_INFINITY,
14
- },
15
- )
16
- const emits = defineEmits<{
17
- (e: 'update:value', value: [number, number]): void
18
- }>()
19
-
20
- const formItemContext = Form.useInjectFormItemContext()
21
- const minValue = computed({
22
- get() {
23
- return props.value[0]
24
- },
25
- set(value) {
26
- emits('update:value', [value, props.value[1]])
27
- formItemContext.onFieldChange()
28
- },
29
- })
30
- const maxValue = computed({
31
- get() {
32
- return props.value[1]
33
- },
34
- set(value) {
35
- emits('update:value', [props.value[0], value])
36
- formItemContext.onFieldChange()
37
- },
38
- })
39
- </script>
40
-
41
- <template>
42
- <div class="flex items-center">
43
- <AInputNumber v-model:value="minValue" class="w-full" :min="props.min" :max="props.max" />
44
- <span>&nbsp;~&nbsp;</span>
45
- <AInputNumber v-model:value="maxValue" class="w-full" :min="props.min" :max="props.max" />
46
- </div>
47
- </template>
1
+ <script setup lang="ts">
2
+ import { computed } from "vue";
3
+ import { Form, InputNumber as AInputNumber } from 'ant-design-vue'
4
+
5
+ const props = withDefaults(
6
+ defineProps<{
7
+ value: [number, number]
8
+ min?: number
9
+ max?: number
10
+ }>(),
11
+ {
12
+ min: Number.NEGATIVE_INFINITY,
13
+ max: Number.POSITIVE_INFINITY,
14
+ },
15
+ )
16
+ const emits = defineEmits<{
17
+ (e: 'update:value', value: [number, number]): void
18
+ }>()
19
+
20
+ const formItemContext = Form.useInjectFormItemContext()
21
+ const minValue = computed({
22
+ get() {
23
+ return props.value[0]
24
+ },
25
+ set(value) {
26
+ emits('update:value', [value, props.value[1]])
27
+ formItemContext.onFieldChange()
28
+ },
29
+ })
30
+ const maxValue = computed({
31
+ get() {
32
+ return props.value[1]
33
+ },
34
+ set(value) {
35
+ emits('update:value', [props.value[0], value])
36
+ formItemContext.onFieldChange()
37
+ },
38
+ })
39
+ </script>
40
+
41
+ <template>
42
+ <div class="flex items-center">
43
+ <AInputNumber v-model:value="minValue" class="w-full" :min="props.min" :max="props.max" />
44
+ <span>&nbsp;~&nbsp;</span>
45
+ <AInputNumber v-model:value="maxValue" class="w-full" :min="props.min" :max="props.max" />
46
+ </div>
47
+ </template>
@@ -1,31 +1,31 @@
1
- import type { App } from 'vue'
2
-
3
- export function formLabelAlign(app: App) {
4
- const directiveName = 'antd-form-label-align'
5
- const resizeObserverKey = `${directiveName}@resizeObserver`
6
-
7
- app.directive(directiveName, {
8
- mounted(el: HTMLElement) {
9
- const labels = el.querySelectorAll('.ant-form-item .ant-form-item-label')
10
- const resizeObserver = new ResizeObserver((entries) => {
11
- const widths = entries.map(e => e.borderBoxSize?.[0]?.inlineSize ?? 0)
12
- const maxWidth = Math.max(...widths)
13
-
14
- if (maxWidth <= 0)
15
- return
16
-
17
- el.style.setProperty('--max-label-width', `${maxWidth}px`)
18
- entries.forEach((e) => {
19
- const target = e.target as HTMLElement
20
- target.style.setProperty('width', 'var(--max-label-width)')
21
- })
22
- })
23
-
24
- Array.from(labels).forEach(label => resizeObserver.observe(label));
25
- (el as any)[resizeObserverKey] = resizeObserver
26
- },
27
- beforeUnmount(el) {
28
- el[resizeObserverKey]?.disconnect()
29
- },
30
- })
1
+ import type { App } from 'vue'
2
+
3
+ export function formLabelAlign(app: App) {
4
+ const directiveName = 'antd-form-label-align'
5
+ const resizeObserverKey = `${directiveName}@resizeObserver`
6
+
7
+ app.directive(directiveName, {
8
+ mounted(el: HTMLElement) {
9
+ const labels = el.querySelectorAll('.ant-form-item .ant-form-item-label')
10
+ const resizeObserver = new ResizeObserver((entries) => {
11
+ const widths = entries.map(e => e.borderBoxSize?.[0]?.inlineSize ?? 0)
12
+ const maxWidth = Math.max(...widths)
13
+
14
+ if (maxWidth <= 0)
15
+ return
16
+
17
+ el.style.setProperty('--max-label-width', `${maxWidth}px`)
18
+ entries.forEach((e) => {
19
+ const target = e.target as HTMLElement
20
+ target.style.setProperty('width', 'var(--max-label-width)')
21
+ })
22
+ })
23
+
24
+ Array.from(labels).forEach(label => resizeObserver.observe(label));
25
+ (el as any)[resizeObserverKey] = resizeObserver
26
+ },
27
+ beforeUnmount(el) {
28
+ el[resizeObserverKey]?.disconnect()
29
+ },
30
+ })
31
31
  }
@@ -1,73 +1,73 @@
1
- import { Button as AButton, Drawer as ADrawer, Space as ASpace } from 'ant-design-vue'
2
- import { defineComponent, isProxy, reactive, toRefs, toRef, h } from 'vue'
3
- import type { Component } from 'vue'
4
- import type { ButtonProps, DrawerProps } from 'ant-design-vue'
5
- import type { ComponentProps } from 'vue-component-type-helpers'
6
- import type { Writable } from 'type-fest'
7
- import { useComponentRef } from '../../vue'
8
-
9
- const defaultDrawerProps: DrawerProps = { open: false, destroyOnClose: true }
10
-
11
- interface IComponentConfig<Comp extends Component> {
12
- is: Comp
13
- props?: Writable<ComponentProps<Comp>>
14
- }
15
-
16
- export function useAntdDrawer<Comp extends Component>(
17
- comp: IComponentConfig<Comp> | Comp,
18
- drawerProps = defaultDrawerProps,
19
- ) {
20
- const _comp = ({ props: {}, ...((comp as any)?.is ? comp : { is: comp }) }) as Required<IComponentConfig<Comp>>
21
- const compProps = reactive(_comp.props)
22
- const compRef = useComponentRef(_comp.is)
23
- const _drawerProps: DrawerProps = reactive({
24
- ...defaultDrawerProps,
25
- ...isProxy(drawerProps) ? toRefs(drawerProps) : drawerProps,
26
- })
27
-
28
- const open = (newBodyProps?: Partial<typeof compProps>, newAntdModalProps?: Omit<Partial<DrawerProps>, 'open'>) => {
29
- Object.assign(_drawerProps, newAntdModalProps)
30
- Object.assign(compProps, newBodyProps)
31
- _drawerProps.open = true
32
- }
33
- const close = () => {
34
- _drawerProps.open = false
35
- }
36
-
37
- const DrawerExtra = defineComponent({
38
- setup() {
39
- const cancelBtnProps: ButtonProps = reactive({ onClick: close })
40
- const confirmBtnProps: ButtonProps = reactive({
41
- type: 'primary',
42
- loading: toRef(() => (compRef as any)?.loading),
43
- onClick: () => (compRef as any)?.confirm?.(),
44
- })
45
-
46
- return { cancelBtnProps, confirmBtnProps }
47
- },
48
- render() {
49
- const { cancelBtnProps, confirmBtnProps } = this
50
-
51
- return h(ASpace, {}, () => [
52
- h(AButton, cancelBtnProps, () => '取消'),
53
- h(AButton, confirmBtnProps, () => '确定'),
54
- ])
55
- },
56
- })
57
- const PresetComponent = defineComponent({
58
- render() {
59
- return h(ADrawer, _drawerProps, {
60
- default: () => h(_comp.is, compProps as any),
61
- })
62
- },
63
- })
64
-
65
- _drawerProps.extra = _drawerProps.extra === undefined ? h(DrawerExtra) : _drawerProps.extra
66
- _drawerProps['onUpdate:open'] = (visiable) => {
67
- _drawerProps.open = visiable
68
- }
69
- (compProps as any).ref = compRef;
70
- (compProps as any).onClose = close
71
-
72
- return { PresetComponent, drawerProps: _drawerProps, open, close }
73
- }
1
+ import { Button as AButton, Drawer as ADrawer, Space as ASpace } from 'ant-design-vue'
2
+ import { defineComponent, isProxy, reactive, toRefs, toRef, h } from 'vue'
3
+ import type { Component } from 'vue'
4
+ import type { ButtonProps, DrawerProps } from 'ant-design-vue'
5
+ import type { ComponentProps } from 'vue-component-type-helpers'
6
+ import type { Writable } from 'type-fest'
7
+ import { useComponentRef } from '../../vue'
8
+
9
+ const defaultDrawerProps: DrawerProps = { open: false, destroyOnClose: true }
10
+
11
+ interface IComponentConfig<Comp extends Component> {
12
+ is: Comp
13
+ props?: Writable<ComponentProps<Comp>>
14
+ }
15
+
16
+ export function useAntdDrawer<Comp extends Component>(
17
+ comp: IComponentConfig<Comp> | Comp,
18
+ drawerProps = defaultDrawerProps,
19
+ ) {
20
+ const _comp = ({ props: {}, ...((comp as any)?.is ? comp : { is: comp }) }) as Required<IComponentConfig<Comp>>
21
+ const compProps = reactive(_comp.props)
22
+ const compRef = useComponentRef(_comp.is)
23
+ const _drawerProps: DrawerProps = reactive({
24
+ ...defaultDrawerProps,
25
+ ...isProxy(drawerProps) ? toRefs(drawerProps) : drawerProps,
26
+ })
27
+
28
+ const open = (newBodyProps?: Partial<typeof compProps>, newAntdModalProps?: Omit<Partial<DrawerProps>, 'open'>) => {
29
+ Object.assign(_drawerProps, newAntdModalProps)
30
+ Object.assign(compProps, newBodyProps)
31
+ _drawerProps.open = true
32
+ }
33
+ const close = () => {
34
+ _drawerProps.open = false
35
+ }
36
+
37
+ const DrawerExtra = defineComponent({
38
+ setup() {
39
+ const cancelBtnProps: ButtonProps = reactive({ onClick: close })
40
+ const confirmBtnProps: ButtonProps = reactive({
41
+ type: 'primary',
42
+ loading: toRef(() => (compRef as any)?.loading),
43
+ onClick: () => (compRef as any)?.confirm?.(),
44
+ })
45
+
46
+ return { cancelBtnProps, confirmBtnProps }
47
+ },
48
+ render() {
49
+ const { cancelBtnProps, confirmBtnProps } = this
50
+
51
+ return h(ASpace, {}, () => [
52
+ h(AButton, cancelBtnProps, () => '取消'),
53
+ h(AButton, confirmBtnProps, () => '确定'),
54
+ ])
55
+ },
56
+ })
57
+ const PresetComponent = defineComponent({
58
+ render() {
59
+ return h(ADrawer, _drawerProps, {
60
+ default: () => h(_comp.is, compProps as any),
61
+ })
62
+ },
63
+ })
64
+
65
+ _drawerProps.extra = _drawerProps.extra === undefined ? h(DrawerExtra) : _drawerProps.extra
66
+ _drawerProps['onUpdate:open'] = (visiable) => {
67
+ _drawerProps.open = visiable
68
+ }
69
+ (compProps as any).ref = compRef;
70
+ (compProps as any).onClose = close
71
+
72
+ return { PresetComponent, drawerProps: _drawerProps, open, close }
73
+ }
@@ -1,70 +1,70 @@
1
- import { computed } from 'vue'
2
- import type { UseQueryReturnType } from '@tanstack/vue-query'
3
- import type { Table, TableProps } from 'ant-design-vue'
4
- import type { ColumnType } from 'ant-design-vue/es/table/interface'
5
- import type { ComponentProps } from 'vue-component-type-helpers'
6
-
7
- export function useAntdTable<
8
- UQRR extends UseQueryReturnType<any, any>,
9
- QP extends Partial<{ page?: string | number; page_size?: string | number }>,
10
- >(uqrt: UQRR, queryParams: QP = ({} as any)) {
11
- type RecordType = GetRecordType<UQRR>
12
- type LocalTableProps = TableProps<RecordType>
13
- type LocalColumnsType = NonNullable<LocalTableProps['columns']>
14
-
15
- const { data, isFetching, isLoading } = uqrt
16
-
17
- const onPaginationChange: ComponentProps<typeof Table>['onChange'] = (pagination) => {
18
- const page = queryParams.page_size !== pagination.pageSize ? 1 : pagination.current
19
- Object.assign(queryParams, { page, page_size: pagination.pageSize ?? 10 })
20
- }
21
- const defineColumns = (columnsFn: () => LocalColumnsType) => computed(columnsFn)
22
-
23
- const tableProps = computed<LocalTableProps>(() => {
24
- const { list, pagination } = data.value ?? {}
25
-
26
- return {
27
- dataSource: list,
28
- pagination: {
29
- disabled: isFetching.value,
30
- current: Number(queryParams.page ?? 1),
31
- pageSize: Number(queryParams.page_size ?? 10),
32
- total: pagination?.total ?? 0,
33
- },
34
- loading: isLoading.value,
35
- scroll: { x: 'max-content' },
36
- sticky: true,
37
- onChange: onPaginationChange as any,
38
- }
39
- })
40
- const dataIndexs = new Proxy({} as Record<keyof RecordType, string>, {
41
- get(_, p) {
42
- return p
43
- },
44
- })
45
- const bodyCellType = {} as {
46
- index: number
47
- text: any
48
- value: any
49
- record: RecordType
50
- column: ColumnType<RecordType>
51
- }
52
-
53
- return {
54
- /** ATable 的预设 Props */
55
- tableProps,
56
- /** 【类型辅助】基于接口数据类型推导出的 dataIndex,供 columns 的 dataIndex 使用 */
57
- dataIndexs,
58
- /** 【类型辅助】bodyCell 插槽数据的精确类型描述 */
59
- bodyCellType,
60
- /** 【类型辅助】用于定义出类型精确的 columns */
61
- defineColumns,
62
- onPaginationChange,
63
- }
64
- }
65
-
66
- type GetRecordType<T> = T extends UseQueryReturnType<infer D, any>
67
- ? D extends Api.PageData
68
- ? NonNullable<D['list']>[0]
69
- : never
70
- : never
1
+ import { computed } from 'vue'
2
+ import type { UseQueryReturnType } from '@tanstack/vue-query'
3
+ import type { Table, TableProps } from 'ant-design-vue'
4
+ import type { ColumnType } from 'ant-design-vue/es/table/interface'
5
+ import type { ComponentProps } from 'vue-component-type-helpers'
6
+
7
+ export function useAntdTable<
8
+ UQRR extends UseQueryReturnType<any, any>,
9
+ QP extends Partial<{ page?: string | number; page_size?: string | number }>,
10
+ >(uqrt: UQRR, queryParams: QP = ({} as any)) {
11
+ type RecordType = GetRecordType<UQRR>
12
+ type LocalTableProps = TableProps<RecordType>
13
+ type LocalColumnsType = NonNullable<LocalTableProps['columns']>
14
+
15
+ const { data, isFetching, isLoading } = uqrt
16
+
17
+ const onPaginationChange: ComponentProps<typeof Table>['onChange'] = (pagination) => {
18
+ const page = queryParams.page_size !== pagination.pageSize ? 1 : pagination.current
19
+ Object.assign(queryParams, { page, page_size: pagination.pageSize ?? 10 })
20
+ }
21
+ const defineColumns = (columnsFn: () => LocalColumnsType) => computed(columnsFn)
22
+
23
+ const tableProps = computed<LocalTableProps>(() => {
24
+ const { list, pagination } = data.value ?? {}
25
+
26
+ return {
27
+ dataSource: list,
28
+ pagination: {
29
+ disabled: isFetching.value,
30
+ current: Number(queryParams.page ?? 1),
31
+ pageSize: Number(queryParams.page_size ?? 10),
32
+ total: pagination?.total ?? 0,
33
+ },
34
+ loading: isLoading.value,
35
+ scroll: { x: 'max-content' },
36
+ sticky: true,
37
+ onChange: onPaginationChange as any,
38
+ }
39
+ })
40
+ const dataIndexs = new Proxy({} as Record<keyof RecordType, string>, {
41
+ get(_, p) {
42
+ return p
43
+ },
44
+ })
45
+ const bodyCellType = {} as {
46
+ index: number
47
+ text: any
48
+ value: any
49
+ record: RecordType
50
+ column: ColumnType<RecordType>
51
+ }
52
+
53
+ return {
54
+ /** ATable 的预设 Props */
55
+ tableProps,
56
+ /** 【类型辅助】基于接口数据类型推导出的 dataIndex,供 columns 的 dataIndex 使用 */
57
+ dataIndexs,
58
+ /** 【类型辅助】bodyCell 插槽数据的精确类型描述 */
59
+ bodyCellType,
60
+ /** 【类型辅助】用于定义出类型精确的 columns */
61
+ defineColumns,
62
+ onPaginationChange,
63
+ }
64
+ }
65
+
66
+ type GetRecordType<T> = T extends UseQueryReturnType<infer D, any>
67
+ ? D extends Api.PageData
68
+ ? NonNullable<D['list']>[0]
69
+ : never
70
+ : never