@peng_kai/kit 0.0.14 → 0.0.16
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/.vscode/settings.json +41 -0
- package/admin/components/filter/index.ts +5 -0
- package/admin/{filter → components/filter/src}/FilterDrawer.vue +99 -96
- package/admin/{filter → components/filter/src}/FilterParam.vue +76 -76
- package/admin/{filter → components/filter/src}/FilterReset.vue +7 -4
- package/admin/{filter → components/filter/src}/useFilterParams.ts +9 -9
- package/admin/{filter → components/filter/src}/useFilterQuery.ts +11 -11
- 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 +117 -114
- package/admin/components/text/src/Datetime.vue +44 -44
- package/admin/components/text/src/Duration.vue +26 -26
- package/admin/components/text/src/Hash.vue +42 -40
- package/admin/components/text/src/createTagGetter.ts +13 -13
- package/admin/defines/index.ts +4 -5
- package/admin/defines/page/definePage.ts +12 -0
- package/admin/defines/page/index.ts +1 -0
- package/admin/defines/route/defineRoute.ts +14 -0
- package/admin/defines/route/getRoutes.ts +84 -0
- package/admin/defines/route/helpers.ts +49 -0
- package/admin/defines/route/index.ts +73 -0
- package/admin/defines/route-guard/defineRouteGuard.ts +18 -0
- package/admin/defines/route-guard/getRouteGuards.ts +40 -0
- package/admin/defines/route-guard/index.ts +2 -0
- package/admin/defines/startup/defineStartup.ts +11 -0
- package/admin/defines/startup/getStartups.ts +30 -0
- package/admin/defines/startup/index.ts +2 -0
- package/admin/hooks/index.ts +5 -6
- package/admin/hooks/useMenu.ts +128 -128
- package/admin/hooks/usePage.ts +141 -139
- package/admin/hooks/usePageTab.ts +35 -35
- package/admin/layout/large/Breadcrumb.vue +69 -70
- package/admin/layout/large/Content.vue +24 -24
- package/admin/layout/large/Menu.vue +69 -68
- package/admin/layout/large/PageTab.vue +71 -71
- package/admin/layout/large/index.ts +4 -4
- package/admin/permission/index.ts +4 -0
- package/admin/permission/routerGuard.ts +43 -0
- package/admin/permission/usePermission.ts +52 -0
- package/admin/permission/vuePlugin.ts +30 -0
- package/admin/route-guards/index.ts +2 -0
- package/admin/route-guards/pageProgress.ts +16 -0
- package/admin/route-guards/pageTitle.ts +24 -0
- package/admin/styles/globalCover.scss +43 -43
- package/admin/types/assist.ts +10 -0
- package/admin/unocss/index.ts +1 -1
- package/antd/components/InputNumberRange.vue +53 -47
- package/antd/directives/formLabelAlign.ts +36 -31
- package/antd/hooks/createAntdModal.ts +29 -29
- package/antd/hooks/useAntdDrawer.ts +73 -73
- package/antd/hooks/useAntdForm.helpers.ts +18 -18
- package/antd/hooks/useAntdForm.ts +38 -37
- package/antd/hooks/useAntdModal.ts +25 -25
- package/antd/hooks/useAntdTable.ts +70 -70
- package/antd/hooks/useAntdTheme.ts +86 -0
- package/antd/index.ts +8 -7
- package/eslint.config.js +50 -0
- package/kitDependencies.ts +21 -7
- package/package.json +46 -40
- package/pnpm-lock.yaml +2689 -0
- package/request/helpers.ts +49 -32
- package/request/index.ts +2 -2
- package/request/interceptors/checkCode.ts +8 -8
- package/request/interceptors/filterEmptyValue.ts +9 -9
- package/request/interceptors/formatPaging.ts +12 -12
- package/request/interceptors/index.ts +7 -6
- package/request/interceptors/popupMessage.ts +35 -35
- package/request/interceptors/returnResultType.ts +19 -19
- package/request/interceptors/toLogin.ts +13 -0
- package/request/interceptors/unitizeAxiosError.ts +7 -7
- package/request/queryClient.ts +42 -0
- package/request/request.ts +21 -21
- package/request/type.d.ts +89 -89
- package/tsconfig.json +47 -18
- package/utils/index.ts +67 -29
- package/vue/components/index.ts +1 -0
- package/{components → vue/components}/infinite-query/index.ts +1 -1
- package/{components → vue/components}/infinite-query/src/InfiniteQuery.vue +147 -147
- package/{components → vue/components}/infinite-query/src/useCreateTrigger.ts +35 -35
- package/vue/hooks/useComponentRef.ts +12 -12
- package/vue/hooks/useIsMounted.ts +4 -4
- package/vue/hooks/useTeleportTarget.ts +7 -7
- package/vue/index.ts +4 -3
- package/admin/defines/definePage.ts +0 -14
- package/admin/defines/defineRoute.helpers.ts +0 -30
- package/admin/defines/defineRoute.ts +0 -161
- package/admin/defines/defineRouteGuard.ts +0 -56
- package/admin/defines/defineStartup.ts +0 -41
- package/admin/filter/index.ts +0 -5
- package/admin/hooks/usePermission.ts +0 -5
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{
|
|
2
|
+
// Enable the ESlint flat config support
|
|
3
|
+
"eslint.experimental.useFlatConfig": true,
|
|
4
|
+
|
|
5
|
+
// Disable the default formatter, use eslint instead
|
|
6
|
+
"prettier.enable": false,
|
|
7
|
+
"editor.formatOnSave": false,
|
|
8
|
+
|
|
9
|
+
// Auto fix
|
|
10
|
+
"editor.codeActionsOnSave": {
|
|
11
|
+
"source.fixAll.eslint": "explicit",
|
|
12
|
+
"source.organizeImports": "never"
|
|
13
|
+
},
|
|
14
|
+
|
|
15
|
+
// Silent the stylistic rules in you IDE, but still auto fix them
|
|
16
|
+
"eslint.rules.customizations": [
|
|
17
|
+
{ "rule": "style/*", "severity": "off" },
|
|
18
|
+
{ "rule": "*-indent", "severity": "off" },
|
|
19
|
+
{ "rule": "*-spacing", "severity": "off" },
|
|
20
|
+
{ "rule": "*-spaces", "severity": "off" },
|
|
21
|
+
{ "rule": "*-order", "severity": "off" },
|
|
22
|
+
{ "rule": "*-dangle", "severity": "off" },
|
|
23
|
+
{ "rule": "*-newline", "severity": "off" },
|
|
24
|
+
{ "rule": "*quotes", "severity": "off" },
|
|
25
|
+
{ "rule": "*semi", "severity": "off" }
|
|
26
|
+
],
|
|
27
|
+
|
|
28
|
+
// Enable eslint for all supported languages
|
|
29
|
+
"eslint.validate": [
|
|
30
|
+
"javascript",
|
|
31
|
+
"javascriptreact",
|
|
32
|
+
"typescript",
|
|
33
|
+
"typescriptreact",
|
|
34
|
+
"vue",
|
|
35
|
+
"html",
|
|
36
|
+
"markdown",
|
|
37
|
+
"json",
|
|
38
|
+
"jsonc",
|
|
39
|
+
"yaml"
|
|
40
|
+
]
|
|
41
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { default as FilterDrawer } from './src/FilterDrawer.vue';
|
|
2
|
+
export { default as FilterReset } from './src/FilterReset.vue';
|
|
3
|
+
export { default as FilterParam, paramTypes } from './src/FilterParam.vue';
|
|
4
|
+
export { useFilterParams } from './src/useFilterParams';
|
|
5
|
+
export { useFilterInfiniteQuery, useFilterPaginationQuery } from './src/useFilterQuery';
|
|
@@ -1,96 +1,99 @@
|
|
|
1
|
-
<script lang="ts" setup>
|
|
2
|
-
import { ref } from
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
const emits = defineEmits<{
|
|
6
|
-
(e: 'filter'): void
|
|
7
|
-
(e: 'reset', value: number): void
|
|
8
|
-
}>()
|
|
9
|
-
const filterVisible = ref(false)
|
|
10
|
-
|
|
11
|
-
function filter() {
|
|
12
|
-
emits('filter')
|
|
13
|
-
filterVisible.value = false
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
function reset() {
|
|
17
|
-
emits('reset', 1)
|
|
18
|
-
filterVisible.value = false
|
|
19
|
-
}
|
|
20
|
-
</script>
|
|
21
|
-
|
|
22
|
-
<template>
|
|
23
|
-
<div class="p-3 mb-2 bg-white text-14px" @click="filterVisible = true">
|
|
24
|
-
<!-- .filter-params 为空时显示 .filter-params-tips -->
|
|
25
|
-
<div class="filter-params">
|
|
26
|
-
<slot name="params" />
|
|
27
|
-
</div>
|
|
28
|
-
<div class="filter-params-tips">
|
|
29
|
-
条件筛选,点击打开
|
|
30
|
-
</div>
|
|
31
|
-
</div>
|
|
32
|
-
|
|
33
|
-
<ADrawer
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
<AButton class="my--3"
|
|
39
|
-
|
|
40
|
-
</AButton>
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
</template>
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
1
|
+
<script lang="ts" setup>
|
|
2
|
+
import { ref } from 'vue';
|
|
3
|
+
import { Button as AButton, Drawer as ADrawer } from 'ant-design-vue';
|
|
4
|
+
|
|
5
|
+
const emits = defineEmits<{
|
|
6
|
+
(e: 'filter'): void
|
|
7
|
+
(e: 'reset', value: number): void
|
|
8
|
+
}>();
|
|
9
|
+
const filterVisible = ref(false);
|
|
10
|
+
|
|
11
|
+
function filter() {
|
|
12
|
+
emits('filter');
|
|
13
|
+
filterVisible.value = false;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function reset() {
|
|
17
|
+
emits('reset', 1);
|
|
18
|
+
filterVisible.value = false;
|
|
19
|
+
}
|
|
20
|
+
</script>
|
|
21
|
+
|
|
22
|
+
<template>
|
|
23
|
+
<div class="p-3 mb-2 bg-white text-14px" @click="filterVisible = true">
|
|
24
|
+
<!-- .filter-params 为空时显示 .filter-params-tips -->
|
|
25
|
+
<div class="filter-params">
|
|
26
|
+
<slot name="params" />
|
|
27
|
+
</div>
|
|
28
|
+
<div class="filter-params-tips">
|
|
29
|
+
条件筛选,点击打开
|
|
30
|
+
</div>
|
|
31
|
+
</div>
|
|
32
|
+
|
|
33
|
+
<ADrawer
|
|
34
|
+
v-model:open="filterVisible" class="filter-drawer" placement="bottom"
|
|
35
|
+
height="50vh"
|
|
36
|
+
>
|
|
37
|
+
<template #extra>
|
|
38
|
+
<AButton class="mr-3 my--3" @click="reset()">
|
|
39
|
+
重置
|
|
40
|
+
</AButton>
|
|
41
|
+
<AButton class="my--3" type="primary" @click="filter()">
|
|
42
|
+
筛选
|
|
43
|
+
</AButton>
|
|
44
|
+
</template>
|
|
45
|
+
<template #default>
|
|
46
|
+
<slot />
|
|
47
|
+
</template>
|
|
48
|
+
</ADrawer>
|
|
49
|
+
</template>
|
|
50
|
+
|
|
51
|
+
<style scoped lang="scss">
|
|
52
|
+
.filter-params {
|
|
53
|
+
display: flex;
|
|
54
|
+
flex-wrap: wrap;
|
|
55
|
+
justify-content: flex-start;
|
|
56
|
+
gap: 5px 15px;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// .filter-params 为空时显示 .filter-params-tips
|
|
60
|
+
.filter-params-tips {
|
|
61
|
+
display: none;
|
|
62
|
+
color: theme('colors.gray.DEFAULT');
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
.filter-params:empty {
|
|
66
|
+
display: none;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
.filter-params:empty + .filter-params-tips {
|
|
70
|
+
display: block;
|
|
71
|
+
}
|
|
72
|
+
</style>
|
|
73
|
+
|
|
74
|
+
<style lang="scss">
|
|
75
|
+
.filter-drawer {
|
|
76
|
+
.ant-drawer-header {
|
|
77
|
+
padding: 16px;
|
|
78
|
+
|
|
79
|
+
.ant-drawer-close {
|
|
80
|
+
--expand: 5px;
|
|
81
|
+
|
|
82
|
+
padding: var(--expand);
|
|
83
|
+
margin: calc(var(--expand) * -1) var(--expand) calc(var(--expand) * -1) 0;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
.ant-drawer-body {
|
|
88
|
+
padding: 16px;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
.ant-form-item {
|
|
92
|
+
margin-bottom: 0;
|
|
93
|
+
|
|
94
|
+
.ant-form-item-label {
|
|
95
|
+
padding-bottom: 0;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
</style>
|
|
@@ -1,76 +1,76 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
import isNil from 'lodash-es/isNil'
|
|
3
|
-
import isFinite from 'lodash-es/isFinite'
|
|
4
|
-
import dayjs from 'dayjs'
|
|
5
|
-
import bignumber from 'bignumber.js'
|
|
6
|
-
|
|
7
|
-
export const paramTypes = { numberRange, datetimeRange, options }
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* 时间范围格式化
|
|
11
|
-
* @param range 数字范围
|
|
12
|
-
* @param unit 单位
|
|
13
|
-
*/
|
|
14
|
-
function numberRange(range?: [number, number], unit?: string) {
|
|
15
|
-
if (!range?.every(isFinite))
|
|
16
|
-
return ''
|
|
17
|
-
|
|
18
|
-
return `${bignumber(range[0]).toFormat()}~${bignumber(range[1]).toFormat()}${unit}
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* 时间范围格式化
|
|
23
|
-
* @param range 时间范围
|
|
24
|
-
* @param template 格式化模板(文档:https://dayjs.gitee.io/docs/zh-CN/display/format )
|
|
25
|
-
*/
|
|
26
|
-
function datetimeRange(range?: [string | dayjs.Dayjs, string | dayjs.Dayjs], template = 'YYYY-MM-DD') {
|
|
27
|
-
if (!range?.every(v => dayjs(v).isValid()))
|
|
28
|
-
return ''
|
|
29
|
-
|
|
30
|
-
return `${dayjs(range[0]).format(template)} ~ ${dayjs(range[1]).format(template)}
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
function options(
|
|
34
|
-
value?: string | number | Array<string | number>,
|
|
35
|
-
options?: Array<{ value: string | number
|
|
36
|
-
) {
|
|
37
|
-
if (isNil(value) || isNil(options))
|
|
38
|
-
return
|
|
39
|
-
if (value === '')
|
|
40
|
-
return
|
|
41
|
-
|
|
42
|
-
const _value = Array.isArray(value) ? value : [value]
|
|
43
|
-
|
|
44
|
-
return options
|
|
45
|
-
.filter(o => _value.includes(o.value))
|
|
46
|
-
.map(o => o.label)
|
|
47
|
-
.join(', ')
|
|
48
|
-
}
|
|
49
|
-
</script>
|
|
50
|
-
|
|
51
|
-
<script setup lang="ts">
|
|
52
|
-
const props = defineProps<{
|
|
53
|
-
label: string
|
|
54
|
-
content?: any
|
|
55
|
-
}>()
|
|
56
|
-
</script>
|
|
57
|
-
|
|
58
|
-
<template>
|
|
59
|
-
<div v-if="props.content" class="item-param">
|
|
60
|
-
<span class="label">{{ props.label }}</span>
|
|
61
|
-
<span class="content">{{ props.content }}</span>
|
|
62
|
-
</div>
|
|
63
|
-
</template>
|
|
64
|
-
|
|
65
|
-
<style lang="scss" scoped>
|
|
66
|
-
.label {
|
|
67
|
-
display: inline-block;
|
|
68
|
-
margin-right: 0.3em;
|
|
69
|
-
color: theme('colors.gray.DEFAULT');
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
.content {
|
|
73
|
-
color: theme('colors.primary.DEFAULT');
|
|
74
|
-
word-break: break-all;
|
|
75
|
-
}
|
|
76
|
-
</style>
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import isNil from 'lodash-es/isNil';
|
|
3
|
+
import isFinite from 'lodash-es/isFinite';
|
|
4
|
+
import dayjs from 'dayjs';
|
|
5
|
+
import bignumber from 'bignumber.js';
|
|
6
|
+
|
|
7
|
+
export const paramTypes = { numberRange, datetimeRange, options };
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* 时间范围格式化
|
|
11
|
+
* @param range 数字范围
|
|
12
|
+
* @param unit 单位
|
|
13
|
+
*/
|
|
14
|
+
function numberRange(range?: [number, number], unit?: string) {
|
|
15
|
+
if (!range?.every(isFinite))
|
|
16
|
+
return '';
|
|
17
|
+
|
|
18
|
+
return `${bignumber(range[0]).toFormat()}~${bignumber(range[1]).toFormat()}${unit}`;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* 时间范围格式化
|
|
23
|
+
* @param range 时间范围
|
|
24
|
+
* @param template 格式化模板(文档:https://dayjs.gitee.io/docs/zh-CN/display/format )
|
|
25
|
+
*/
|
|
26
|
+
function datetimeRange(range?: [string | dayjs.Dayjs, string | dayjs.Dayjs], template = 'YYYY-MM-DD') {
|
|
27
|
+
if (!range?.every(v => dayjs(v).isValid()))
|
|
28
|
+
return '';
|
|
29
|
+
|
|
30
|
+
return `${dayjs(range[0]).format(template)} ~ ${dayjs(range[1]).format(template)}`;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function options(
|
|
34
|
+
value?: string | number | Array<string | number>,
|
|
35
|
+
options?: Array<{ value: string | number, label: any }>,
|
|
36
|
+
) {
|
|
37
|
+
if (isNil(value) || isNil(options))
|
|
38
|
+
return;
|
|
39
|
+
if (value === '')
|
|
40
|
+
return;
|
|
41
|
+
|
|
42
|
+
const _value = Array.isArray(value) ? value : [value];
|
|
43
|
+
|
|
44
|
+
return options
|
|
45
|
+
.filter(o => _value.includes(o.value))
|
|
46
|
+
.map(o => o.label)
|
|
47
|
+
.join(', ');
|
|
48
|
+
}
|
|
49
|
+
</script>
|
|
50
|
+
|
|
51
|
+
<script setup lang="ts">
|
|
52
|
+
const props = defineProps<{
|
|
53
|
+
label: string
|
|
54
|
+
content?: any
|
|
55
|
+
}>();
|
|
56
|
+
</script>
|
|
57
|
+
|
|
58
|
+
<template>
|
|
59
|
+
<div v-if="props.content" class="item-param">
|
|
60
|
+
<span class="label">{{ props.label }}</span>
|
|
61
|
+
<span class="content">{{ props.content }}</span>
|
|
62
|
+
</div>
|
|
63
|
+
</template>
|
|
64
|
+
|
|
65
|
+
<style lang="scss" scoped>
|
|
66
|
+
.label {
|
|
67
|
+
display: inline-block;
|
|
68
|
+
margin-right: 0.3em;
|
|
69
|
+
color: theme('colors.gray.DEFAULT');
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
.content {
|
|
73
|
+
color: theme('colors.primary.DEFAULT');
|
|
74
|
+
word-break: break-all;
|
|
75
|
+
}
|
|
76
|
+
</style>
|
|
@@ -1,18 +1,21 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
import { Button as AButton } from
|
|
2
|
+
import { Button as AButton } from 'ant-design-vue';
|
|
3
3
|
|
|
4
4
|
const props = defineProps<{
|
|
5
5
|
loading?: boolean
|
|
6
|
-
}>()
|
|
6
|
+
}>();
|
|
7
7
|
const emits = defineEmits<{
|
|
8
8
|
(e: 'filter'): void
|
|
9
9
|
(e: 'reset'): void
|
|
10
|
-
}>()
|
|
10
|
+
}>();
|
|
11
11
|
</script>
|
|
12
12
|
|
|
13
13
|
<template>
|
|
14
14
|
<div class="flex-none flex w-min ml-auto">
|
|
15
|
-
<AButton
|
|
15
|
+
<AButton
|
|
16
|
+
class="mr-2 filter-btn" type="primary" htmlType="submit"
|
|
17
|
+
:loading="props.loading" @click="emits('filter')"
|
|
18
|
+
>
|
|
16
19
|
查询
|
|
17
20
|
</AButton>
|
|
18
21
|
<AButton :disabled="props.loading" @click="emits('reset')">
|
|
@@ -1,19 +1,19 @@
|
|
|
1
|
-
import { extendRef } from '@vueuse/core'
|
|
2
|
-
import { reactive } from
|
|
1
|
+
import { extendRef } from '@vueuse/core';
|
|
2
|
+
import { reactive } from 'vue';
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
const defaultPageParams: PageParams = { page: 1, page_size: 10 }
|
|
4
|
+
interface PageParams { page?: string | number, page_size?: string | number };
|
|
5
|
+
const defaultPageParams: PageParams = { page: 1, page_size: 10 };
|
|
6
6
|
|
|
7
7
|
export function useFilterParams<R extends Api.Request, AP extends Api.GetParam<R>, BP extends AP>(
|
|
8
8
|
_api: R,
|
|
9
9
|
buildParams: () => BP,
|
|
10
10
|
pageParams = defaultPageParams,
|
|
11
11
|
) {
|
|
12
|
-
type FinalParams = AP & BP & PageParams
|
|
13
|
-
const params = reactive({ ...pageParams, ...buildParams() } as FinalParams)
|
|
12
|
+
type FinalParams = AP & BP & PageParams;
|
|
13
|
+
const params = reactive({ ...pageParams, ...buildParams() } as FinalParams);
|
|
14
14
|
const update = (newParams?: Partial<FinalParams>) => {
|
|
15
|
-
Object.assign(params, { ...buildParams(), ...newParams })
|
|
16
|
-
}
|
|
15
|
+
Object.assign(params, { ...buildParams(), ...newParams, __t: Date.now() });
|
|
16
|
+
};
|
|
17
17
|
|
|
18
|
-
return extendRef(params, { update })
|
|
18
|
+
return extendRef(params, { update });
|
|
19
19
|
}
|
|
@@ -1,31 +1,31 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { useInfiniteQuery, useQuery } from '@tanstack/vue-query';
|
|
2
|
+
import { useFilterParams } from './useFilterParams';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
|
-
|
|
5
|
+
|
|
6
6
|
*/
|
|
7
7
|
export function useFilterPaginationQuery<Api extends Api.Request, P extends Api.GetParam<Api>>(apiFn: Api, paramsFn: () => P) {
|
|
8
|
-
type Data = Api.GetData<Api
|
|
8
|
+
type Data = Api.GetData<Api>;
|
|
9
9
|
|
|
10
|
-
const filterParams = useFilterParams(apiFn, paramsFn)
|
|
10
|
+
const filterParams = useFilterParams(apiFn, paramsFn);
|
|
11
11
|
const filterQuery = useQuery({
|
|
12
12
|
keepPreviousData: true,
|
|
13
13
|
queryKey: [apiFn.id, 'pagination', filterParams],
|
|
14
14
|
queryFn: () => (apiFn(filterParams) as Promise<Data>),
|
|
15
|
-
})
|
|
15
|
+
});
|
|
16
16
|
|
|
17
|
-
return [filterQuery, filterParams] as const
|
|
17
|
+
return [filterQuery, filterParams] as const;
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
export function useFilterInfiniteQuery<Api extends Api.Request, P extends Api.GetParam<Api>>(apiFn: Api, paramsFn: () => P) {
|
|
21
|
-
type Data = Api.GetData<Api
|
|
21
|
+
type Data = Api.GetData<Api>;
|
|
22
22
|
|
|
23
|
-
const filterParams = useFilterParams(apiFn, paramsFn)
|
|
23
|
+
const filterParams = useFilterParams(apiFn, paramsFn);
|
|
24
24
|
const filterQuery = useInfiniteQuery({
|
|
25
25
|
keepPreviousData: true,
|
|
26
26
|
queryKey: [apiFn.id, 'infinite', filterParams],
|
|
27
27
|
queryFn: ctx => (apiFn({ ...filterParams, ...ctx.pageParam }) as Promise<Data>),
|
|
28
|
-
})
|
|
28
|
+
});
|
|
29
29
|
|
|
30
|
-
return [filterQuery, filterParams] as const
|
|
30
|
+
return [filterQuery, filterParams] as const;
|
|
31
31
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export { default as ScrollNav } from './src/ScrollNav.vue'
|
|
1
|
+
export { default as ScrollNav } from './src/ScrollNav.vue';
|
|
@@ -1,59 +1,59 @@
|
|
|
1
|
-
<script setup lang="ts">
|
|
2
|
-
import { computed } from
|
|
3
|
-
import { useElementSize } from '@vueuse/core'
|
|
4
|
-
|
|
5
|
-
const props = defineProps<{
|
|
6
|
-
selector: string
|
|
7
|
-
}>()
|
|
8
|
-
|
|
9
|
-
const $content = document.querySelector(props.selector) as HTMLElement
|
|
10
|
-
const $contentParent = $content.parentElement
|
|
11
|
-
const { height: contentParentH } = useElementSize($contentParent)
|
|
12
|
-
const { height: contentH } = useElementSize($content)
|
|
13
|
-
const visible = computed(() => contentParentH.value * 2 < contentH.value)
|
|
14
|
-
|
|
15
|
-
function scrollTo(top: number) {
|
|
16
|
-
$contentParent?.scrollTo({ top })
|
|
17
|
-
}
|
|
18
|
-
</script>
|
|
19
|
-
|
|
20
|
-
<template>
|
|
21
|
-
<div v-if="visible" class="wrapper">
|
|
22
|
-
<div class="btn" @click="scrollTo(0)">
|
|
23
|
-
<i class="i-fluent:arrow-previous-24-filled rotate-90" />
|
|
24
|
-
</div>
|
|
25
|
-
<div class="btn" @click="scrollTo($contentParent?.scrollHeight ?? Infinity)">
|
|
26
|
-
<i class="i-fluent:arrow-previous-24-filled rotate-270" />
|
|
27
|
-
</div>
|
|
28
|
-
<!-- <div v-if="showReturn" class="btn" @click="toLastY()">
|
|
29
|
-
<i class="i-fluent:arrow-hook-down-left-24-filled rotate-270" />
|
|
30
|
-
</div> -->
|
|
31
|
-
</div>
|
|
32
|
-
</template>
|
|
33
|
-
|
|
34
|
-
<style lang="scss" scoped>
|
|
35
|
-
.wrapper {
|
|
36
|
-
font-size: 18px;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
.btn {
|
|
40
|
-
display: flex;
|
|
41
|
-
width: 2em;
|
|
42
|
-
height: 2em;
|
|
43
|
-
align-items: center;
|
|
44
|
-
justify-content: center;
|
|
45
|
-
border-radius: 2px;
|
|
46
|
-
background: #bcbcbc;
|
|
47
|
-
color: #000;
|
|
48
|
-
cursor: pointer;
|
|
49
|
-
opacity: 0.7;
|
|
50
|
-
|
|
51
|
-
&:active {
|
|
52
|
-
transform: scale(0.9);
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
& + & {
|
|
56
|
-
margin-top: 1px;
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
</style>
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { computed } from 'vue';
|
|
3
|
+
import { useElementSize } from '@vueuse/core';
|
|
4
|
+
|
|
5
|
+
const props = defineProps<{
|
|
6
|
+
selector: string
|
|
7
|
+
}>();
|
|
8
|
+
|
|
9
|
+
const $content = document.querySelector(props.selector) as HTMLElement;
|
|
10
|
+
const $contentParent = $content.parentElement;
|
|
11
|
+
const { height: contentParentH } = useElementSize($contentParent);
|
|
12
|
+
const { height: contentH } = useElementSize($content);
|
|
13
|
+
const visible = computed(() => contentParentH.value * 2 < contentH.value);
|
|
14
|
+
|
|
15
|
+
function scrollTo(top: number) {
|
|
16
|
+
$contentParent?.scrollTo({ top });
|
|
17
|
+
}
|
|
18
|
+
</script>
|
|
19
|
+
|
|
20
|
+
<template>
|
|
21
|
+
<div v-if="visible" class="wrapper">
|
|
22
|
+
<div class="btn" @click="scrollTo(0)">
|
|
23
|
+
<i class="i-fluent:arrow-previous-24-filled rotate-90" />
|
|
24
|
+
</div>
|
|
25
|
+
<div class="btn" @click="scrollTo($contentParent?.scrollHeight ?? Infinity)">
|
|
26
|
+
<i class="i-fluent:arrow-previous-24-filled rotate-270" />
|
|
27
|
+
</div>
|
|
28
|
+
<!-- <div v-if="showReturn" class="btn" @click="toLastY()">
|
|
29
|
+
<i class="i-fluent:arrow-hook-down-left-24-filled rotate-270" />
|
|
30
|
+
</div> -->
|
|
31
|
+
</div>
|
|
32
|
+
</template>
|
|
33
|
+
|
|
34
|
+
<style lang="scss" scoped>
|
|
35
|
+
.wrapper {
|
|
36
|
+
font-size: 18px;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
.btn {
|
|
40
|
+
display: flex;
|
|
41
|
+
width: 2em;
|
|
42
|
+
height: 2em;
|
|
43
|
+
align-items: center;
|
|
44
|
+
justify-content: center;
|
|
45
|
+
border-radius: 2px;
|
|
46
|
+
background: #bcbcbc;
|
|
47
|
+
color: #000;
|
|
48
|
+
cursor: pointer;
|
|
49
|
+
opacity: 0.7;
|
|
50
|
+
|
|
51
|
+
&:active {
|
|
52
|
+
transform: scale(0.9);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
& + & {
|
|
56
|
+
margin-top: 1px;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
</style>
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import Hash from './src/Hash.vue'
|
|
2
|
-
import Amount from './src/Amount.vue'
|
|
3
|
-
import Datetime from './src/Datetime.vue'
|
|
4
|
-
import Duration from './src/Duration.vue'
|
|
5
|
-
|
|
6
|
-
export { createTagGetter } from './src/createTagGetter'
|
|
7
|
-
|
|
8
|
-
export const Text = {
|
|
9
|
-
Hash,
|
|
10
|
-
Amount,
|
|
11
|
-
Datetime,
|
|
12
|
-
Duration,
|
|
13
|
-
}
|
|
1
|
+
import Hash from './src/Hash.vue';
|
|
2
|
+
import Amount from './src/Amount.vue';
|
|
3
|
+
import Datetime from './src/Datetime.vue';
|
|
4
|
+
import Duration from './src/Duration.vue';
|
|
5
|
+
|
|
6
|
+
export { createTagGetter } from './src/createTagGetter';
|
|
7
|
+
|
|
8
|
+
export const Text = {
|
|
9
|
+
Hash,
|
|
10
|
+
Amount,
|
|
11
|
+
Datetime,
|
|
12
|
+
Duration,
|
|
13
|
+
};
|