@peng_kai/kit 0.0.9 → 0.0.11

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 (38) 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 -45
  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/filter/FilterDrawer.vue +96 -96
  9. package/admin/filter/FilterParam.vue +76 -76
  10. package/admin/filter/FilterReset.vue +2 -2
  11. package/admin/filter/index.ts +2 -1
  12. package/admin/filter/useFilterParams.ts +4 -3
  13. package/admin/filter/useFilterQuery.ts +31 -0
  14. package/admin/hooks/useMenu.ts +128 -132
  15. package/admin/hooks/usePage.ts +139 -138
  16. package/admin/hooks/usePageTab.ts +35 -35
  17. package/admin/layout/large/Breadcrumb.vue +70 -68
  18. package/admin/layout/large/Content.vue +24 -23
  19. package/admin/layout/large/Menu.vue +68 -73
  20. package/admin/layout/large/PageTab.vue +71 -70
  21. package/admin/styles/classCover.scss +108 -0
  22. package/admin/styles/globalCover.scss +43 -0
  23. package/admin/styles/index.scss +30 -0
  24. package/admin/unocss/index.ts +6 -0
  25. package/antd/components/InputNumberRange.vue +47 -47
  26. package/antd/hooks/useAntdDrawer.ts +73 -73
  27. package/antd/hooks/useAntdForm.ts +14 -5
  28. package/antd/hooks/useAntdTable.ts +70 -70
  29. package/antd/index.ts +1 -1
  30. package/components/infinite-query/index.ts +1 -1
  31. package/components/infinite-query/src/InfiniteQuery.vue +147 -147
  32. package/components/infinite-query/src/useCreateTrigger.ts +35 -35
  33. package/kitDependencies.ts +26 -6
  34. package/package.json +40 -40
  35. package/request/helpers.ts +32 -32
  36. package/request/type.d.ts +89 -89
  37. package/tsconfig.json +17 -17
  38. package/pnpm-lock.yaml +0 -598
@@ -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
+ }
@@ -5,9 +5,13 @@ import type { ComputedRef, UnwrapRef } from 'vue'
5
5
  import { GROUP_SEP, buildGroupFieldName, getGroupIndex } from './useAntdForm.helpers'
6
6
 
7
7
  export { useAntdForm }
8
- export type { TField }
8
+ export type { TField, RecordToSchemas }
9
9
 
10
- function useAntdForm<F extends Record<string, TField>, S extends GetFormState<F>, STF = S>(
10
+ function useAntdForm<
11
+ F extends Record<string, TField>,
12
+ S extends GetFormState<F>,
13
+ STF = S
14
+ >(
11
15
  schemas: F,
12
16
  _options?: {
13
17
  transform?: (state: S) => STF
@@ -82,10 +86,15 @@ function useAntdForm<F extends Record<string, TField>, S extends GetFormState<F>
82
86
  }
83
87
  }
84
88
 
85
- interface TField {
86
- value: any
89
+ interface TField<V = any> {
90
+ value: V
87
91
  rules?: RuleObject[]
88
92
  }
93
+
94
+ type RecordToSchemas<T extends Record<string, unknown>> = {
95
+ [K in keyof T]: TField<T[K]>
96
+ }
97
+
89
98
  type GetFormState<C extends Record<string, TField>> = {
90
99
  [K in keyof C]: UnwrapRef<C[K]['value']>;
91
- }
100
+ }
@@ -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) {
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
package/antd/index.ts CHANGED
@@ -4,4 +4,4 @@ export { useAntdTable } from './hooks/useAntdTable'
4
4
  export { useAntdForm } from './hooks/useAntdForm'
5
5
  export { createAntdModal } from './hooks/createAntdModal'
6
6
  export { default as InputNumberRange } from './components/InputNumberRange.vue'
7
- export type { TField } from './hooks/useAntdForm.ts'
7
+ export type { TField, RecordToSchemas } from './hooks/useAntdForm.ts'
@@ -1 +1 @@
1
- export { default as InfiniteQuery } from './src/InfiniteQuery.vue'
1
+ export { default as InfiniteQuery } from './src/InfiniteQuery.vue'
@@ -1,147 +1,147 @@
1
- <script lang="ts">
2
- import { computed, ref, unref } from "vue";
3
- import type { UseInfiniteQueryReturnType } from '@tanstack/vue-query'
4
- import { useCreateTrigger } from './useCreateTrigger'
5
- </script>
6
-
7
- <script setup lang="ts" generic="T extends UseInfiniteQueryReturnType<any, any>">
8
- type TPage = T extends UseInfiniteQueryReturnType<infer P, any> ? NonNullable<P> : any
9
- type TRecord = TPage extends { list: Array<infer I> } ? I : any
10
-
11
- const props = defineProps<{
12
- queryier: T
13
- }>()
14
-
15
- const { queryier } = props
16
- const pages = computed(() => queryier.data.value?.pages)
17
- // TODO: 状态之间的互斥仍有问题
18
- const isInitialLoading = computed(() => queryier.isInitialLoading.value)
19
- const isInitialLoadingError = computed(() => queryier.isLoadingError.value && !isInitialLoading.value)
20
- const isMoreLoading = computed(
21
- () => (queryier.isFetchingNextPage.value || queryier.isFetching.value) && !isInitialLoading.value,
22
- )
23
- const isMoreLoadingError = computed(() => queryier.isRefetchError.value && !isMoreLoading.value)
24
- const noMore = computed(
25
- () =>
26
- !queryier.hasNextPage?.value
27
- && !isInitialLoading.value
28
- && !isInitialLoadingError.value
29
- && !isMoreLoading.value
30
- && !isMoreLoadingError.value,
31
- )
32
- const $container = ref<HTMLElement>()
33
- const containerCssVars = computed(() => {
34
- const ctnEle = unref($container)
35
-
36
- if (!ctnEle)
37
- return {}
38
-
39
- const rect = ctnEle.getBoundingClientRect()
40
-
41
- return {
42
- '--ctn-height': `${rect.height}px`,
43
- }
44
- })
45
-
46
- function refetch() {
47
- queryier.refetch()
48
- }
49
-
50
- function refetchLastPage() {
51
- queryier.refetch({
52
- refetchPage(lastPage: any, _index, allPages: any[]) {
53
- const lastIndex = allPages?.length - 1
54
- return lastPage?.pagination?.page === allPages?.[lastIndex]?.pagination?.page
55
- },
56
- })
57
- }
58
-
59
- function fetchNextPage() {
60
- const { isFetching, isLoading, hasNextPage } = queryier
61
-
62
- if (isFetching.value || isLoading.value || !hasNextPage?.value)
63
- return
64
-
65
- queryier.fetchNextPage()
66
- }
67
-
68
- function triggerFetchNextPage() {
69
- if (queryier.isError.value)
70
- return
71
-
72
- fetchNextPage()
73
- }
74
-
75
- useCreateTrigger($container, triggerFetchNextPage)
76
- </script>
77
-
78
- <template>
79
- <div ref="$container" class="infinite-query-wrapper" :style="containerCssVars">
80
- <div v-if="isInitialLoading" class="initial-loading">
81
- <i class="i-svg-spinners:180-ring-with-bg loading-icon" />
82
- </div>
83
- <div v-if="isInitialLoadingError" class="initial-loading-error" @click="refetch()">
84
- <span>加载失败,点击重试</span>
85
- </div>
86
-
87
- <div v-for="(page, i) of pages" :key="i">
88
- <template v-for="record of page.list">
89
- <slot :record="record as TRecord" />
90
- </template>
91
- </div>
92
-
93
- <div v-if="isMoreLoading" class="more-loading">
94
- <i class="i-svg-spinners:180-ring-with-bg loading-icon" />
95
- <span class="ml-1 text">加载中...</span>
96
- </div>
97
- <div v-if="isMoreLoadingError" class="more-loading-error" @click="fetchNextPage()">
98
- <span class="text">加载失败,点击重试</span>
99
- </div>
100
- <div v-if="noMore" class="no-more" @click="refetchLastPage()">
101
- <span class="text">暂无更多</span>
102
- </div>
103
- </div>
104
- </template>
105
-
106
- <style scoped lang="scss">
107
- .infinite-query-wrapper {
108
- overflow: auto;
109
- font-size: 14px;
110
- }
111
-
112
- .loading-icon {
113
- display: block;
114
- color: var(--antd-colorPrimary);
115
- font-size: 1.2em;
116
- }
117
-
118
- .initial-loading,
119
- .initial-loading-error,
120
- .more-loading,
121
- .more-loading-error,
122
- .no-more {
123
- display: flex;
124
- align-items: center;
125
- justify-content: center;
126
- color: var(--antd-colorTextSecondary);
127
- }
128
-
129
- .initial-loading,
130
- .initial-loading-error {
131
- height: var(--ctn-height, 100px);
132
- }
133
-
134
- .initial-loading-error {
135
- cursor: pointer;
136
- }
137
-
138
- .more-loading,
139
- .more-loading-error,
140
- .no-more {
141
- height: 50px;
142
- }
143
-
144
- .more-loading-error {
145
- cursor: pointer;
146
- }
147
- </style>
1
+ <script lang="ts">
2
+ import { computed, ref, unref } from "vue";
3
+ import type { UseInfiniteQueryReturnType } from '@tanstack/vue-query'
4
+ import { useCreateTrigger } from './useCreateTrigger'
5
+ </script>
6
+
7
+ <script setup lang="ts" generic="T extends UseInfiniteQueryReturnType<any, any>">
8
+ type TPage = T extends UseInfiniteQueryReturnType<infer P, any> ? NonNullable<P> : any
9
+ type TRecord = TPage extends { list: Array<infer I> } ? I : any
10
+
11
+ const props = defineProps<{
12
+ queryier: T
13
+ }>()
14
+
15
+ const { queryier } = props
16
+ const pages = computed(() => queryier.data.value?.pages)
17
+ // TODO: 状态之间的互斥仍有问题
18
+ const isInitialLoading = computed(() => queryier.isInitialLoading.value)
19
+ const isInitialLoadingError = computed(() => queryier.isLoadingError.value && !isInitialLoading.value)
20
+ const isMoreLoading = computed(
21
+ () => (queryier.isFetchingNextPage.value || queryier.isFetching.value) && !isInitialLoading.value,
22
+ )
23
+ const isMoreLoadingError = computed(() => queryier.isRefetchError.value && !isMoreLoading.value)
24
+ const noMore = computed(
25
+ () =>
26
+ !queryier.hasNextPage?.value
27
+ && !isInitialLoading.value
28
+ && !isInitialLoadingError.value
29
+ && !isMoreLoading.value
30
+ && !isMoreLoadingError.value,
31
+ )
32
+ const $container = ref<HTMLElement>()
33
+ const containerCssVars = computed(() => {
34
+ const ctnEle = unref($container)
35
+
36
+ if (!ctnEle)
37
+ return {}
38
+
39
+ const rect = ctnEle.getBoundingClientRect()
40
+
41
+ return {
42
+ '--ctn-height': `${rect.height}px`,
43
+ }
44
+ })
45
+
46
+ function refetch() {
47
+ queryier.refetch()
48
+ }
49
+
50
+ function refetchLastPage() {
51
+ queryier.refetch({
52
+ refetchPage(lastPage: any, _index, allPages: any[]) {
53
+ const lastIndex = allPages?.length - 1
54
+ return lastPage?.pagination?.page === allPages?.[lastIndex]?.pagination?.page
55
+ },
56
+ })
57
+ }
58
+
59
+ function fetchNextPage() {
60
+ const { isFetching, isLoading, hasNextPage } = queryier
61
+
62
+ if (isFetching.value || isLoading.value || !hasNextPage?.value)
63
+ return
64
+
65
+ queryier.fetchNextPage()
66
+ }
67
+
68
+ function triggerFetchNextPage() {
69
+ if (queryier.isError.value)
70
+ return
71
+
72
+ fetchNextPage()
73
+ }
74
+
75
+ useCreateTrigger($container, triggerFetchNextPage)
76
+ </script>
77
+
78
+ <template>
79
+ <div ref="$container" class="infinite-query-wrapper" :style="containerCssVars">
80
+ <div v-if="isInitialLoading" class="initial-loading">
81
+ <i class="i-svg-spinners:180-ring-with-bg loading-icon" />
82
+ </div>
83
+ <div v-if="isInitialLoadingError" class="initial-loading-error" @click="refetch()">
84
+ <span>加载失败,点击重试</span>
85
+ </div>
86
+
87
+ <div v-for="(page, i) of pages" :key="i">
88
+ <template v-for="record of page.list">
89
+ <slot :record="record as TRecord" />
90
+ </template>
91
+ </div>
92
+
93
+ <div v-if="isMoreLoading" class="more-loading">
94
+ <i class="i-svg-spinners:180-ring-with-bg loading-icon" />
95
+ <span class="ml-1 text">加载中...</span>
96
+ </div>
97
+ <div v-if="isMoreLoadingError" class="more-loading-error" @click="fetchNextPage()">
98
+ <span class="text">加载失败,点击重试</span>
99
+ </div>
100
+ <div v-if="noMore" class="no-more" @click="refetchLastPage()">
101
+ <span class="text">暂无更多</span>
102
+ </div>
103
+ </div>
104
+ </template>
105
+
106
+ <style scoped lang="scss">
107
+ .infinite-query-wrapper {
108
+ overflow: auto;
109
+ font-size: 14px;
110
+ }
111
+
112
+ .loading-icon {
113
+ display: block;
114
+ color: var(--antd-colorPrimary);
115
+ font-size: 1.2em;
116
+ }
117
+
118
+ .initial-loading,
119
+ .initial-loading-error,
120
+ .more-loading,
121
+ .more-loading-error,
122
+ .no-more {
123
+ display: flex;
124
+ align-items: center;
125
+ justify-content: center;
126
+ color: var(--antd-colorTextSecondary);
127
+ }
128
+
129
+ .initial-loading,
130
+ .initial-loading-error {
131
+ height: var(--ctn-height, 100px);
132
+ }
133
+
134
+ .initial-loading-error {
135
+ cursor: pointer;
136
+ }
137
+
138
+ .more-loading,
139
+ .more-loading-error,
140
+ .no-more {
141
+ height: 50px;
142
+ }
143
+
144
+ .more-loading-error {
145
+ cursor: pointer;
146
+ }
147
+ </style>