@peng_kai/kit 0.2.0-beta.0 → 0.2.0-beta.10
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.
- package/admin/adminPlugin.ts +1 -0
- package/admin/components/filter/src/FilterDrawer.vue +153 -153
- package/admin/components/filter/src/FilterParam.vue +1 -1
- package/admin/components/scroll-nav/index.ts +1 -1
- package/admin/components/scroll-nav/src/ScrollNav.vue +59 -59
- package/admin/components/text/index.ts +13 -13
- package/admin/components/text/src/Amount.vue +121 -121
- package/admin/components/text/src/Datetime.vue +1 -1
- package/admin/components/text/src/Duration.vue +26 -26
- package/admin/components/text/src/Hash.vue +51 -51
- package/admin/components/text/src/createTagGetter.ts +13 -13
- package/admin/route-guards/index.ts +3 -3
- package/admin/route-guards/pageProgress.ts +27 -27
- package/admin/styles/globalCover.scss +54 -54
- package/antd/components/InputNumberRange.vue +59 -59
- package/antd/directives/formLabelAlign.ts +36 -36
- package/antd/hooks/useAntdDrawer.ts +73 -73
- package/antd/hooks/useAntdTable.ts +127 -127
- package/libs/dayjs.ts +7 -0
- package/package.json +91 -97
- package/request/helpers.ts +68 -68
- package/request/interceptors/toLogin.ts +26 -26
- package/request/type.d.ts +92 -92
- package/stylelint.config.cjs +7 -7
- package/tsconfig.json +50 -50
- package/utils/date.ts +1 -9
- package/utils/upload/AwsS3.ts +0 -8
- package/vue/components/infinite-query/index.ts +1 -1
- package/vue/components/infinite-query/src/InfiniteQuery.vue +199 -199
- package/vue/components/infinite-query/src/useCreateTrigger.ts +39 -39
package/tsconfig.json
CHANGED
|
@@ -1,50 +1,50 @@
|
|
|
1
|
-
{
|
|
2
|
-
"compilerOptions": {
|
|
3
|
-
"target": "ES2020",
|
|
4
|
-
"jsx": "preserve",
|
|
5
|
-
"jsxFactory": "h",
|
|
6
|
-
"jsxFragmentFactory": "Fragment",
|
|
7
|
-
"lib": [
|
|
8
|
-
"ESNext",
|
|
9
|
-
"DOM",
|
|
10
|
-
"DOM.Iterable"
|
|
11
|
-
],
|
|
12
|
-
"useDefineForClassFields": true,
|
|
13
|
-
"module": "ESNext",
|
|
14
|
-
|
|
15
|
-
/* Bundler mode */
|
|
16
|
-
"moduleResolution": "bundler",
|
|
17
|
-
"resolveJsonModule": true,
|
|
18
|
-
"allowImportingTsExtensions": true,
|
|
19
|
-
|
|
20
|
-
/* Linting */
|
|
21
|
-
"strict": true,
|
|
22
|
-
"noFallthroughCasesInSwitch": true,
|
|
23
|
-
"noImplicitAny": false,
|
|
24
|
-
"noUnusedLocals": true,
|
|
25
|
-
"noUnusedParameters": true,
|
|
26
|
-
"noEmit": true,
|
|
27
|
-
"allowSyntheticDefaultImports": true,
|
|
28
|
-
"esModuleInterop": true,
|
|
29
|
-
"isolatedModules": true,
|
|
30
|
-
"skipLibCheck": true
|
|
31
|
-
},
|
|
32
|
-
"include": [
|
|
33
|
-
"admin/**/*.ts",
|
|
34
|
-
"admin/**/*.d.ts",
|
|
35
|
-
"admin/**/*.tsx",
|
|
36
|
-
"admin/**/*.vue",
|
|
37
|
-
"antd/**/*.ts",
|
|
38
|
-
"antd/**/*.d.ts",
|
|
39
|
-
"antd/**/*.tsx",
|
|
40
|
-
"antd/**/*.vue",
|
|
41
|
-
"request/**/*.ts",
|
|
42
|
-
"request/**/*.d.ts",
|
|
43
|
-
"utils/**/*.ts",
|
|
44
|
-
"utils/**/*.d.ts",
|
|
45
|
-
"vue/**/*.ts",
|
|
46
|
-
"vue/**/*.d.ts",
|
|
47
|
-
"vue/**/*.tsx",
|
|
48
|
-
"vue/**/*.vue"
|
|
49
|
-
]
|
|
50
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2020",
|
|
4
|
+
"jsx": "preserve",
|
|
5
|
+
"jsxFactory": "h",
|
|
6
|
+
"jsxFragmentFactory": "Fragment",
|
|
7
|
+
"lib": [
|
|
8
|
+
"ESNext",
|
|
9
|
+
"DOM",
|
|
10
|
+
"DOM.Iterable"
|
|
11
|
+
],
|
|
12
|
+
"useDefineForClassFields": true,
|
|
13
|
+
"module": "ESNext",
|
|
14
|
+
|
|
15
|
+
/* Bundler mode */
|
|
16
|
+
"moduleResolution": "bundler",
|
|
17
|
+
"resolveJsonModule": true,
|
|
18
|
+
"allowImportingTsExtensions": true,
|
|
19
|
+
|
|
20
|
+
/* Linting */
|
|
21
|
+
"strict": true,
|
|
22
|
+
"noFallthroughCasesInSwitch": true,
|
|
23
|
+
"noImplicitAny": false,
|
|
24
|
+
"noUnusedLocals": true,
|
|
25
|
+
"noUnusedParameters": true,
|
|
26
|
+
"noEmit": true,
|
|
27
|
+
"allowSyntheticDefaultImports": true,
|
|
28
|
+
"esModuleInterop": true,
|
|
29
|
+
"isolatedModules": true,
|
|
30
|
+
"skipLibCheck": true
|
|
31
|
+
},
|
|
32
|
+
"include": [
|
|
33
|
+
"admin/**/*.ts",
|
|
34
|
+
"admin/**/*.d.ts",
|
|
35
|
+
"admin/**/*.tsx",
|
|
36
|
+
"admin/**/*.vue",
|
|
37
|
+
"antd/**/*.ts",
|
|
38
|
+
"antd/**/*.d.ts",
|
|
39
|
+
"antd/**/*.tsx",
|
|
40
|
+
"antd/**/*.vue",
|
|
41
|
+
"request/**/*.ts",
|
|
42
|
+
"request/**/*.d.ts",
|
|
43
|
+
"utils/**/*.ts",
|
|
44
|
+
"utils/**/*.d.ts",
|
|
45
|
+
"vue/**/*.ts",
|
|
46
|
+
"vue/**/*.d.ts",
|
|
47
|
+
"vue/**/*.tsx",
|
|
48
|
+
"vue/**/*.vue"
|
|
49
|
+
]
|
|
50
|
+
}
|
package/utils/date.ts
CHANGED
|
@@ -1,12 +1,4 @@
|
|
|
1
|
-
import dayjs from 'dayjs';
|
|
2
|
-
import relativeTime from 'dayjs/plugin/relativeTime';
|
|
3
|
-
import 'dayjs/locale/zh';
|
|
4
|
-
import 'dayjs/locale/en';
|
|
5
|
-
|
|
6
|
-
export { default as dayjs } from 'dayjs';
|
|
7
|
-
|
|
8
|
-
dayjs.locale('zh');
|
|
9
|
-
dayjs.extend(relativeTime);
|
|
1
|
+
import dayjs from '../libs/dayjs';
|
|
10
2
|
|
|
11
3
|
/**
|
|
12
4
|
* 返回给定日期的一天的开始时间。
|
package/utils/upload/AwsS3.ts
CHANGED
|
@@ -15,9 +15,7 @@ export class AwsS3 {
|
|
|
15
15
|
public domain = '';
|
|
16
16
|
public bucket = '';
|
|
17
17
|
public region = '';
|
|
18
|
-
|
|
19
18
|
private s3Client: S3Client | undefined = undefined;
|
|
20
|
-
private lastRefreshParams = 0;
|
|
21
19
|
|
|
22
20
|
public constructor(private getParams: TGetParams, private fileHandler?: FileHandler) {
|
|
23
21
|
}
|
|
@@ -52,11 +50,6 @@ export class AwsS3 {
|
|
|
52
50
|
}
|
|
53
51
|
|
|
54
52
|
private async refreshClient() {
|
|
55
|
-
const needRefresh = (Date.now() - this.lastRefreshParams) > 5 * 60 * 1000;
|
|
56
|
-
|
|
57
|
-
if (!needRefresh)
|
|
58
|
-
return this.s3Client;
|
|
59
|
-
|
|
60
53
|
const params = await this.getParams();
|
|
61
54
|
this.domain = params.domain;
|
|
62
55
|
this.bucket = params.bucket;
|
|
@@ -69,7 +62,6 @@ export class AwsS3 {
|
|
|
69
62
|
sessionToken: params.sessionToken,
|
|
70
63
|
},
|
|
71
64
|
});
|
|
72
|
-
this.lastRefreshParams = Date.now();
|
|
73
65
|
|
|
74
66
|
return this.s3Client;
|
|
75
67
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export { default as InfiniteQuery } from './src/InfiniteQuery.vue';
|
|
1
|
+
export { default as InfiniteQuery } from './src/InfiniteQuery.vue';
|
|
@@ -1,199 +1,199 @@
|
|
|
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
|
-
|
|
6
|
-
export type { ISlotProvide };
|
|
7
|
-
|
|
8
|
-
interface ISlotProvide {
|
|
9
|
-
isInitialLoading: boolean
|
|
10
|
-
isInitialLoadingError: boolean
|
|
11
|
-
isEmpty: boolean
|
|
12
|
-
isMoreLoading: boolean
|
|
13
|
-
isMoreLoadingError: boolean
|
|
14
|
-
isNoMore: boolean
|
|
15
|
-
refetch: () => void
|
|
16
|
-
}
|
|
17
|
-
</script>
|
|
18
|
-
|
|
19
|
-
<script setup lang="ts" generic="T extends UseInfiniteQueryReturnType<any, any>">
|
|
20
|
-
type TPage = T extends UseInfiniteQueryReturnType<infer P, any> ? NonNullable<P> : any;
|
|
21
|
-
type TRecord = TPage extends { list: Array<infer I> } ? I : any;
|
|
22
|
-
|
|
23
|
-
const props = withDefaults(defineProps<{
|
|
24
|
-
queryier: T
|
|
25
|
-
distance?: string
|
|
26
|
-
}>(), {
|
|
27
|
-
distance: '50px',
|
|
28
|
-
});
|
|
29
|
-
|
|
30
|
-
const { queryier } = props;
|
|
31
|
-
const pages = computed(() => queryier.data.value?.pages);
|
|
32
|
-
const isInitialLoading = computed(() => queryier.isPending.value);
|
|
33
|
-
const isInitialLoadingError = computed(() => queryier.isLoadingError.value && !isInitialLoading.value);
|
|
34
|
-
const isMoreLoading = computed(
|
|
35
|
-
() => (queryier.isFetchingNextPage.value || queryier.isFetching.value) && !isInitialLoading.value,
|
|
36
|
-
);
|
|
37
|
-
const isEmpty = computed(() => queryier.isSuccess.value && !pages.value?.[0].list?.length);
|
|
38
|
-
const isMoreLoadingError = computed(() => queryier.isRefetchError.value && !isMoreLoading.value);
|
|
39
|
-
const isNoMore = computed(
|
|
40
|
-
() =>
|
|
41
|
-
!queryier.hasNextPage?.value
|
|
42
|
-
&& !isInitialLoading.value
|
|
43
|
-
&& !isInitialLoadingError.value
|
|
44
|
-
&& !isMoreLoading.value
|
|
45
|
-
&& !isMoreLoadingError.value,
|
|
46
|
-
);
|
|
47
|
-
const $container = ref<HTMLElement>();
|
|
48
|
-
const containerCssVars = computed(() => {
|
|
49
|
-
const ctnEle = unref($container);
|
|
50
|
-
|
|
51
|
-
if (!ctnEle)
|
|
52
|
-
return {};
|
|
53
|
-
|
|
54
|
-
const rect = ctnEle.getBoundingClientRect();
|
|
55
|
-
|
|
56
|
-
return {
|
|
57
|
-
'--ctn-height': `${rect.height}px`,
|
|
58
|
-
};
|
|
59
|
-
});
|
|
60
|
-
|
|
61
|
-
function refetchLastPage() {
|
|
62
|
-
queryier.refetch();
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
function fetchNextPage() {
|
|
66
|
-
const { isFetching, isLoading, hasNextPage } = queryier;
|
|
67
|
-
|
|
68
|
-
if (isFetching.value || isLoading.value || !hasNextPage?.value)
|
|
69
|
-
return;
|
|
70
|
-
|
|
71
|
-
queryier.fetchNextPage();
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
function refetch() {
|
|
75
|
-
if (isNoMore.value)
|
|
76
|
-
refetchLastPage();
|
|
77
|
-
else if (isMoreLoadingError.value)
|
|
78
|
-
fetchNextPage();
|
|
79
|
-
else
|
|
80
|
-
queryier.refetch();
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
function triggerFetchNextPage() {
|
|
84
|
-
if (queryier.isError.value)
|
|
85
|
-
return;
|
|
86
|
-
|
|
87
|
-
fetchNextPage();
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
useCreateTrigger($container, triggerFetchNextPage, props.distance);
|
|
91
|
-
|
|
92
|
-
const slotProvide = computed<ISlotProvide>(() => ({
|
|
93
|
-
isInitialLoading: isInitialLoading.value,
|
|
94
|
-
isInitialLoadingError: isInitialLoadingError.value,
|
|
95
|
-
isMoreLoading: isMoreLoading.value,
|
|
96
|
-
isMoreLoadingError: isMoreLoadingError.value,
|
|
97
|
-
isNoMore: isNoMore.value,
|
|
98
|
-
isEmpty: isEmpty.value,
|
|
99
|
-
refetch,
|
|
100
|
-
}));
|
|
101
|
-
</script>
|
|
102
|
-
|
|
103
|
-
<template>
|
|
104
|
-
<div ref="$container" class="infinite-query-wrapper" :style="containerCssVars">
|
|
105
|
-
<div class="list">
|
|
106
|
-
<template v-for="(page) of pages">
|
|
107
|
-
<template v-for="record of page.list">
|
|
108
|
-
<!-- eslint-disable-next-line vue/no-extra-parens -->
|
|
109
|
-
<slot name="default" :record="(record as TRecord)" />
|
|
110
|
-
</template>
|
|
111
|
-
</template>
|
|
112
|
-
</div>
|
|
113
|
-
|
|
114
|
-
<slot
|
|
115
|
-
name="status" v-bind="slotProvide"
|
|
116
|
-
>
|
|
117
|
-
<slot name="initialLoading">
|
|
118
|
-
<div v-if="isInitialLoading" class="initial-loading">
|
|
119
|
-
<i class="i-svg-spinners:180-ring-with-bg loading-icon" />
|
|
120
|
-
</div>
|
|
121
|
-
</slot>
|
|
122
|
-
|
|
123
|
-
<slot name="initialLoadingError">
|
|
124
|
-
<div v-if="isInitialLoadingError" class="initial-loading-error" @click="refetch()">
|
|
125
|
-
<span>加载失败,点击重试</span>
|
|
126
|
-
</div>
|
|
127
|
-
</slot>
|
|
128
|
-
|
|
129
|
-
<slot name="empty">
|
|
130
|
-
<div v-if="isEmpty" class="empty">
|
|
131
|
-
<span>暂无数据</span>
|
|
132
|
-
</div>
|
|
133
|
-
</slot>
|
|
134
|
-
|
|
135
|
-
<slot name="oreLoading">
|
|
136
|
-
<div v-if="isMoreLoading" class="more-loading">
|
|
137
|
-
<i class="i-svg-spinners:180-ring-with-bg loading-icon" />
|
|
138
|
-
<span class="ml-1 text">加载中...</span>
|
|
139
|
-
</div>
|
|
140
|
-
</slot>
|
|
141
|
-
|
|
142
|
-
<slot name="moreLoadingError">
|
|
143
|
-
<div v-if="isMoreLoadingError" class="more-loading-error" @click="refetch()">
|
|
144
|
-
<span class="text">加载失败,点击重试</span>
|
|
145
|
-
</div>
|
|
146
|
-
</slot>
|
|
147
|
-
|
|
148
|
-
<slot name="noMore">
|
|
149
|
-
<div v-if="isNoMore" class="no-more" @click="refetch()">
|
|
150
|
-
<span class="text">暂无更多</span>
|
|
151
|
-
</div>
|
|
152
|
-
</slot>
|
|
153
|
-
</slot>
|
|
154
|
-
</div>
|
|
155
|
-
</template>
|
|
156
|
-
|
|
157
|
-
<style scoped lang="scss">
|
|
158
|
-
.infinite-query-wrapper {
|
|
159
|
-
overflow: auto;
|
|
160
|
-
font-size: 14px;
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
.loading-icon {
|
|
164
|
-
display: block;
|
|
165
|
-
color: var(--antd-colorPrimary);
|
|
166
|
-
font-size: 1.2em;
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
.initial-loading,
|
|
170
|
-
.initial-loading-error,
|
|
171
|
-
.empty,
|
|
172
|
-
.more-loading,
|
|
173
|
-
.more-loading-error,
|
|
174
|
-
.no-more {
|
|
175
|
-
display: flex;
|
|
176
|
-
align-items: center;
|
|
177
|
-
justify-content: center;
|
|
178
|
-
color: var(--antd-colorTextSecondary);
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
.initial-loading,
|
|
182
|
-
.initial-loading-error {
|
|
183
|
-
height: var(--ctn-height, 100px);
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
.initial-loading-error {
|
|
187
|
-
cursor: pointer;
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
.more-loading,
|
|
191
|
-
.more-loading-error,
|
|
192
|
-
.no-more {
|
|
193
|
-
height: 50px;
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
.more-loading-error {
|
|
197
|
-
cursor: pointer;
|
|
198
|
-
}
|
|
199
|
-
</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
|
+
|
|
6
|
+
export type { ISlotProvide };
|
|
7
|
+
|
|
8
|
+
interface ISlotProvide {
|
|
9
|
+
isInitialLoading: boolean
|
|
10
|
+
isInitialLoadingError: boolean
|
|
11
|
+
isEmpty: boolean
|
|
12
|
+
isMoreLoading: boolean
|
|
13
|
+
isMoreLoadingError: boolean
|
|
14
|
+
isNoMore: boolean
|
|
15
|
+
refetch: () => void
|
|
16
|
+
}
|
|
17
|
+
</script>
|
|
18
|
+
|
|
19
|
+
<script setup lang="ts" generic="T extends UseInfiniteQueryReturnType<any, any>">
|
|
20
|
+
type TPage = T extends UseInfiniteQueryReturnType<infer P, any> ? NonNullable<P> : any;
|
|
21
|
+
type TRecord = TPage extends { list: Array<infer I> } ? I : any;
|
|
22
|
+
|
|
23
|
+
const props = withDefaults(defineProps<{
|
|
24
|
+
queryier: T
|
|
25
|
+
distance?: string
|
|
26
|
+
}>(), {
|
|
27
|
+
distance: '50px',
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
const { queryier } = props;
|
|
31
|
+
const pages = computed(() => queryier.data.value?.pages);
|
|
32
|
+
const isInitialLoading = computed(() => queryier.isPending.value);
|
|
33
|
+
const isInitialLoadingError = computed(() => queryier.isLoadingError.value && !isInitialLoading.value);
|
|
34
|
+
const isMoreLoading = computed(
|
|
35
|
+
() => (queryier.isFetchingNextPage.value || queryier.isFetching.value) && !isInitialLoading.value,
|
|
36
|
+
);
|
|
37
|
+
const isEmpty = computed(() => queryier.isSuccess.value && !pages.value?.[0].list?.length);
|
|
38
|
+
const isMoreLoadingError = computed(() => queryier.isRefetchError.value && !isMoreLoading.value);
|
|
39
|
+
const isNoMore = computed(
|
|
40
|
+
() =>
|
|
41
|
+
!queryier.hasNextPage?.value
|
|
42
|
+
&& !isInitialLoading.value
|
|
43
|
+
&& !isInitialLoadingError.value
|
|
44
|
+
&& !isMoreLoading.value
|
|
45
|
+
&& !isMoreLoadingError.value,
|
|
46
|
+
);
|
|
47
|
+
const $container = ref<HTMLElement>();
|
|
48
|
+
const containerCssVars = computed(() => {
|
|
49
|
+
const ctnEle = unref($container);
|
|
50
|
+
|
|
51
|
+
if (!ctnEle)
|
|
52
|
+
return {};
|
|
53
|
+
|
|
54
|
+
const rect = ctnEle.getBoundingClientRect();
|
|
55
|
+
|
|
56
|
+
return {
|
|
57
|
+
'--ctn-height': `${rect.height}px`,
|
|
58
|
+
};
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
function refetchLastPage() {
|
|
62
|
+
queryier.refetch();
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function fetchNextPage() {
|
|
66
|
+
const { isFetching, isLoading, hasNextPage } = queryier;
|
|
67
|
+
|
|
68
|
+
if (isFetching.value || isLoading.value || !hasNextPage?.value)
|
|
69
|
+
return;
|
|
70
|
+
|
|
71
|
+
queryier.fetchNextPage();
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function refetch() {
|
|
75
|
+
if (isNoMore.value)
|
|
76
|
+
refetchLastPage();
|
|
77
|
+
else if (isMoreLoadingError.value)
|
|
78
|
+
fetchNextPage();
|
|
79
|
+
else
|
|
80
|
+
queryier.refetch();
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function triggerFetchNextPage() {
|
|
84
|
+
if (queryier.isError.value)
|
|
85
|
+
return;
|
|
86
|
+
|
|
87
|
+
fetchNextPage();
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
useCreateTrigger($container, triggerFetchNextPage, props.distance);
|
|
91
|
+
|
|
92
|
+
const slotProvide = computed<ISlotProvide>(() => ({
|
|
93
|
+
isInitialLoading: isInitialLoading.value,
|
|
94
|
+
isInitialLoadingError: isInitialLoadingError.value,
|
|
95
|
+
isMoreLoading: isMoreLoading.value,
|
|
96
|
+
isMoreLoadingError: isMoreLoadingError.value,
|
|
97
|
+
isNoMore: isNoMore.value,
|
|
98
|
+
isEmpty: isEmpty.value,
|
|
99
|
+
refetch,
|
|
100
|
+
}));
|
|
101
|
+
</script>
|
|
102
|
+
|
|
103
|
+
<template>
|
|
104
|
+
<div ref="$container" class="infinite-query-wrapper" :style="containerCssVars">
|
|
105
|
+
<div class="list">
|
|
106
|
+
<template v-for="(page) of pages">
|
|
107
|
+
<template v-for="record of page.list">
|
|
108
|
+
<!-- eslint-disable-next-line vue/no-extra-parens -->
|
|
109
|
+
<slot name="default" :record="(record as TRecord)" />
|
|
110
|
+
</template>
|
|
111
|
+
</template>
|
|
112
|
+
</div>
|
|
113
|
+
|
|
114
|
+
<slot
|
|
115
|
+
name="status" v-bind="slotProvide"
|
|
116
|
+
>
|
|
117
|
+
<slot name="initialLoading">
|
|
118
|
+
<div v-if="isInitialLoading" class="initial-loading">
|
|
119
|
+
<i class="i-svg-spinners:180-ring-with-bg loading-icon" />
|
|
120
|
+
</div>
|
|
121
|
+
</slot>
|
|
122
|
+
|
|
123
|
+
<slot name="initialLoadingError">
|
|
124
|
+
<div v-if="isInitialLoadingError" class="initial-loading-error" @click="refetch()">
|
|
125
|
+
<span>加载失败,点击重试</span>
|
|
126
|
+
</div>
|
|
127
|
+
</slot>
|
|
128
|
+
|
|
129
|
+
<slot name="empty">
|
|
130
|
+
<div v-if="isEmpty" class="empty">
|
|
131
|
+
<span>暂无数据</span>
|
|
132
|
+
</div>
|
|
133
|
+
</slot>
|
|
134
|
+
|
|
135
|
+
<slot name="oreLoading">
|
|
136
|
+
<div v-if="isMoreLoading" class="more-loading">
|
|
137
|
+
<i class="i-svg-spinners:180-ring-with-bg loading-icon" />
|
|
138
|
+
<span class="ml-1 text">加载中...</span>
|
|
139
|
+
</div>
|
|
140
|
+
</slot>
|
|
141
|
+
|
|
142
|
+
<slot name="moreLoadingError">
|
|
143
|
+
<div v-if="isMoreLoadingError" class="more-loading-error" @click="refetch()">
|
|
144
|
+
<span class="text">加载失败,点击重试</span>
|
|
145
|
+
</div>
|
|
146
|
+
</slot>
|
|
147
|
+
|
|
148
|
+
<slot name="noMore">
|
|
149
|
+
<div v-if="isNoMore" class="no-more" @click="refetch()">
|
|
150
|
+
<span class="text">暂无更多</span>
|
|
151
|
+
</div>
|
|
152
|
+
</slot>
|
|
153
|
+
</slot>
|
|
154
|
+
</div>
|
|
155
|
+
</template>
|
|
156
|
+
|
|
157
|
+
<style scoped lang="scss">
|
|
158
|
+
.infinite-query-wrapper {
|
|
159
|
+
overflow: auto;
|
|
160
|
+
font-size: 14px;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
.loading-icon {
|
|
164
|
+
display: block;
|
|
165
|
+
color: var(--antd-colorPrimary);
|
|
166
|
+
font-size: 1.2em;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
.initial-loading,
|
|
170
|
+
.initial-loading-error,
|
|
171
|
+
.empty,
|
|
172
|
+
.more-loading,
|
|
173
|
+
.more-loading-error,
|
|
174
|
+
.no-more {
|
|
175
|
+
display: flex;
|
|
176
|
+
align-items: center;
|
|
177
|
+
justify-content: center;
|
|
178
|
+
color: var(--antd-colorTextSecondary);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
.initial-loading,
|
|
182
|
+
.initial-loading-error {
|
|
183
|
+
height: var(--ctn-height, 100px);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
.initial-loading-error {
|
|
187
|
+
cursor: pointer;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
.more-loading,
|
|
191
|
+
.more-loading-error,
|
|
192
|
+
.no-more {
|
|
193
|
+
height: 50px;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
.more-loading-error {
|
|
197
|
+
cursor: pointer;
|
|
198
|
+
}
|
|
199
|
+
</style>
|
|
@@ -1,39 +1,39 @@
|
|
|
1
|
-
import { onUnmounted, watch } from 'vue';
|
|
2
|
-
import type { Ref } from 'vue';
|
|
3
|
-
import { useIntersectionObserver, useIntervalFn } from '@vueuse/core';
|
|
4
|
-
|
|
5
|
-
export function useCreateTrigger(containerEle: Ref<HTMLElement | undefined>, callback: Function, distance: string) {
|
|
6
|
-
const triggerEl = document.createElement('div');
|
|
7
|
-
|
|
8
|
-
Object.assign(triggerEl.style, {
|
|
9
|
-
position: 'relative',
|
|
10
|
-
zIndex: '5',
|
|
11
|
-
marginTop: `-${distance}`,
|
|
12
|
-
marginBottom: distance,
|
|
13
|
-
width: '5px',
|
|
14
|
-
height: '5px',
|
|
15
|
-
// background: 'red',
|
|
16
|
-
} satisfies Partial<CSSStyleDeclaration>);
|
|
17
|
-
|
|
18
|
-
useIntervalFn(() => {
|
|
19
|
-
const { transform } = triggerEl.style;
|
|
20
|
-
|
|
21
|
-
if (transform)
|
|
22
|
-
triggerEl.style.removeProperty('transform');
|
|
23
|
-
else triggerEl.style.setProperty('transform', 'translateX(-200%)');
|
|
24
|
-
}, 500);
|
|
25
|
-
|
|
26
|
-
useIntersectionObserver(triggerEl, ([entry]) => {
|
|
27
|
-
if (entry.isIntersecting)
|
|
28
|
-
callback();
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
watch(containerEle, (ele) => {
|
|
32
|
-
if (ele)
|
|
33
|
-
ele.append(triggerEl);
|
|
34
|
-
});
|
|
35
|
-
|
|
36
|
-
onUnmounted(() => {
|
|
37
|
-
triggerEl.remove();
|
|
38
|
-
});
|
|
39
|
-
}
|
|
1
|
+
import { onUnmounted, watch } from 'vue';
|
|
2
|
+
import type { Ref } from 'vue';
|
|
3
|
+
import { useIntersectionObserver, useIntervalFn } from '@vueuse/core';
|
|
4
|
+
|
|
5
|
+
export function useCreateTrigger(containerEle: Ref<HTMLElement | undefined>, callback: Function, distance: string) {
|
|
6
|
+
const triggerEl = document.createElement('div');
|
|
7
|
+
|
|
8
|
+
Object.assign(triggerEl.style, {
|
|
9
|
+
position: 'relative',
|
|
10
|
+
zIndex: '5',
|
|
11
|
+
marginTop: `-${distance}`,
|
|
12
|
+
marginBottom: distance,
|
|
13
|
+
width: '5px',
|
|
14
|
+
height: '5px',
|
|
15
|
+
// background: 'red',
|
|
16
|
+
} satisfies Partial<CSSStyleDeclaration>);
|
|
17
|
+
|
|
18
|
+
useIntervalFn(() => {
|
|
19
|
+
const { transform } = triggerEl.style;
|
|
20
|
+
|
|
21
|
+
if (transform)
|
|
22
|
+
triggerEl.style.removeProperty('transform');
|
|
23
|
+
else triggerEl.style.setProperty('transform', 'translateX(-200%)');
|
|
24
|
+
}, 500);
|
|
25
|
+
|
|
26
|
+
useIntersectionObserver(triggerEl, ([entry]) => {
|
|
27
|
+
if (entry.isIntersecting)
|
|
28
|
+
callback();
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
watch(containerEle, (ele) => {
|
|
32
|
+
if (ele)
|
|
33
|
+
ele.append(triggerEl);
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
onUnmounted(() => {
|
|
37
|
+
triggerEl.remove();
|
|
38
|
+
});
|
|
39
|
+
}
|