@peng_kai/kit 0.1.16 → 0.2.0-beta.0
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 +47 -0
- package/admin/components/filter/src/FilterParam.vue +76 -78
- package/admin/components/filter/src/FilterReset.vue +2 -2
- package/admin/components/filter/src/useFilterParams.ts +75 -25
- package/admin/components/filter/src/useFilterQuery.ts +32 -16
- package/admin/components/rich-text/index.ts +2 -0
- package/admin/components/rich-text/src/RichText.vue +342 -0
- package/admin/components/rich-text/src/imageUploader.ts +34 -0
- package/admin/components/rich-text/src/type.d.ts +7 -0
- package/admin/components/text/src/Datetime.vue +47 -48
- package/admin/components/upload/index.ts +2 -0
- package/admin/components/upload/src/PictureCardUpload.vue +143 -0
- package/admin/components/upload/src/customRequests.ts +31 -0
- package/admin/defines/index.ts +1 -1
- package/admin/defines/route/helpers.ts +0 -1
- package/admin/defines/startup/defineStartup.ts +8 -1
- package/admin/defines/startup/index.ts +1 -1
- package/admin/defines/startup/{getStartups.ts → runStartup.ts} +16 -7
- package/admin/layout/large/Breadcrumb.vue +68 -69
- package/admin/layout/large/Content.vue +23 -24
- package/admin/layout/large/Menu.vue +68 -69
- package/admin/layout/large/PageTab.vue +70 -71
- package/admin/permission/index.ts +2 -4
- package/admin/permission/routerGuard.ts +41 -43
- package/admin/permission/vuePlugin.ts +46 -30
- package/admin/route-guards/collapseMenu.ts +3 -3
- package/admin/route-guards/pageTitle.ts +18 -19
- package/admin/scripts/deploy.ts +67 -0
- package/admin/{hooks/useMenu.ts → stores/createUseMenuStore.ts} +133 -128
- package/admin/{hooks/usePage.ts → stores/createUsePageStore.ts} +145 -141
- package/admin/stores/createUsePageTabStore.ts +43 -0
- package/admin/{permission/usePermission.ts → stores/createUsePermissionStore.ts} +57 -52
- package/admin/stores/index.ts +8 -0
- package/admin/styles/classCover.scss +8 -0
- package/antd/hooks/useAntdForm.helpers.ts +92 -8
- package/antd/hooks/useAntdForm.ts +55 -63
- package/antd/hooks/useAntdTable.ts +12 -0
- package/antd/index.ts +1 -1
- package/libs/a-calc.ts +1 -0
- package/libs/axios.ts +2 -0
- package/libs/bignumber.ts +2 -0
- package/libs/dayjs.ts +5 -0
- package/libs/echarts.ts +5 -0
- package/libs/localstorage-slim.ts +2 -0
- package/libs/lodash-es.ts +1 -0
- package/libs/pinia.ts +1 -0
- package/libs/vue-query.ts +1 -0
- package/libs/vueuse.ts +3 -0
- package/package.json +97 -53
- package/request/helpers.ts +20 -1
- package/request/interceptors/checkCode.ts +3 -3
- package/request/interceptors/returnResultType.ts +2 -2
- package/request/queryClient.ts +34 -21
- package/utils/upload/AwsS3.ts +76 -0
- package/utils/upload/fileHandlers.ts +27 -0
- package/utils/upload/index.ts +2 -0
- package/vite/index.d.ts +1 -0
- package/vite/index.mjs +27 -0
- package/vue/components/echarts/index.ts +1 -0
- package/vue/components/echarts/src/ECharts.vue +48 -0
- package/vue/components/index.ts +1 -0
- package/vue/components/infinite-query/src/InfiniteQuery.vue +2 -8
- package/vue/components/test/KitTest.vue +9 -0
- package/vue/components/test/testStore.ts +11 -0
- package/admin/hooks/index.ts +0 -5
- package/admin/hooks/usePageTab.ts +0 -35
- package/kitDependencies.ts +0 -43
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type { App } from 'vue';
|
|
2
|
+
import type { Router } from 'vue-router';
|
|
3
|
+
import type { TUseMenuStore } from './stores/createUseMenuStore';
|
|
4
|
+
import type { TUsePageStore } from './stores/createUsePageStore';
|
|
5
|
+
import type { TUsePageTabStore } from './stores/createUsePageTabStore';
|
|
6
|
+
import type { TRole, TUsePermissionStore } from './stores/createUsePermissionStore';
|
|
7
|
+
|
|
8
|
+
interface IOtions {
|
|
9
|
+
meta: {
|
|
10
|
+
appId: string
|
|
11
|
+
appName: string
|
|
12
|
+
}
|
|
13
|
+
deps: {
|
|
14
|
+
router: Router
|
|
15
|
+
roles: Record<string, TRole>
|
|
16
|
+
useMenuStore: TUseMenuStore
|
|
17
|
+
usePageStore: TUsePageStore
|
|
18
|
+
usePageTabStore: TUsePageTabStore
|
|
19
|
+
usePermissionStore: TUsePermissionStore
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
let _meta: IOtions['meta'];
|
|
24
|
+
let _deps: IOtions['deps'];
|
|
25
|
+
|
|
26
|
+
export const adminPlugin = {
|
|
27
|
+
install(_app: App, options: IOtions) {
|
|
28
|
+
_meta = options.meta;
|
|
29
|
+
_deps = options.deps;
|
|
30
|
+
},
|
|
31
|
+
meta: new Proxy({} as IOtions['meta'], {
|
|
32
|
+
get(_, p) {
|
|
33
|
+
return _meta?.[p];
|
|
34
|
+
},
|
|
35
|
+
}),
|
|
36
|
+
deps: new Proxy({} as IOtions['deps'], {
|
|
37
|
+
get(_, p) {
|
|
38
|
+
const _p = String(p);
|
|
39
|
+
const _dep = _deps?.[p];
|
|
40
|
+
|
|
41
|
+
if (!_dep)
|
|
42
|
+
throw new Error(`${_p} 不在 kit 依赖中,请通过 kitPlugin 传入 ${_p}`);
|
|
43
|
+
|
|
44
|
+
return _dep;
|
|
45
|
+
},
|
|
46
|
+
}),
|
|
47
|
+
};
|
|
@@ -1,78 +1,76 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
import isNil from 'lodash-es/isNil';
|
|
3
|
-
import isFinite from 'lodash-es/isFinite';
|
|
4
|
-
import bignumber from 'bignumber.js';
|
|
5
|
-
import {
|
|
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?: [any, any], template = 'YYYY-MM-DD') {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
if (
|
|
40
|
-
return;
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
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
|
-
</style>
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import isNil from 'lodash-es/isNil';
|
|
3
|
+
import isFinite from 'lodash-es/isFinite';
|
|
4
|
+
import bignumber from 'bignumber.js';
|
|
5
|
+
import { dayjs } from '../../../../utils/date';
|
|
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?: [any, any], 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>
|
|
@@ -29,13 +29,13 @@ const loading = computed(() => {
|
|
|
29
29
|
});
|
|
30
30
|
|
|
31
31
|
function filter() {
|
|
32
|
-
props.filterParams?.update?.(
|
|
32
|
+
props.filterParams?.update?.(true);
|
|
33
33
|
emits('filter');
|
|
34
34
|
}
|
|
35
35
|
|
|
36
36
|
function reset() {
|
|
37
37
|
props.filterForm?.$form.resetFields?.();
|
|
38
|
-
props.filterParams?.update?.(
|
|
38
|
+
props.filterParams?.update?.(true);
|
|
39
39
|
emits('reset');
|
|
40
40
|
}
|
|
41
41
|
</script>
|
|
@@ -1,28 +1,78 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { reactive } from 'vue';
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
1
|
+
import { cloneDeep, eq, mapValues } from 'lodash-es';
|
|
2
|
+
import { type DeepReadonly, type MaybeRefOrGetter, reactive, toRef, watch } from 'vue';
|
|
3
|
+
|
|
4
|
+
export type ShcemeConfig<T> = {
|
|
5
|
+
[P in keyof T]: {
|
|
6
|
+
/**
|
|
7
|
+
* 属性值。可以传入 普通值、Ref对象、一个函数(get函数,只读)
|
|
8
|
+
*/
|
|
9
|
+
value: MaybeRefOrGetter<T[P]>
|
|
10
|
+
/**
|
|
11
|
+
* 是否是响应式,默认 `false`
|
|
12
|
+
* - `true`: 值的变化立即生效到 `$params`
|
|
13
|
+
* - `false`: 值不会立即生效到 `$params`,需要调用 `update`
|
|
14
|
+
*/
|
|
15
|
+
responsive?: boolean
|
|
16
|
+
/**
|
|
17
|
+
* 当值变化时是否重置 `page`,默认 `true`
|
|
18
|
+
*/
|
|
19
|
+
resetPage?: boolean
|
|
20
|
+
/**
|
|
21
|
+
* 在值变化后,生效到 `$params`前,触发 `before` 钩子
|
|
22
|
+
* @param bp 所有在 `before` 函数中被修改的属性组成的对象
|
|
23
|
+
* @param np 触发 `before` 函数时的 params 对象
|
|
24
|
+
*/
|
|
25
|
+
before?(bp: T, np: DeepReadonly<T>): void
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
export function useFilterParams<T extends Record<string, any>>(shcemes: ShcemeConfig<T>) {
|
|
30
|
+
// 设置默认值
|
|
31
|
+
Object.values(shcemes).forEach((s) => {
|
|
32
|
+
s.resetPage ??= true;
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
// 好像不需要 resetPage,因为参数一旦变化肯定要重置分页的
|
|
36
|
+
(shcemes as any).page ??= { value: 1, responsive: true, resetPage: false };
|
|
37
|
+
(shcemes as any).page_size ??= { value: 10, responsive: true, resetPage: true };
|
|
38
|
+
|
|
39
|
+
const modifiableParams = reactive(mapValues(shcemes, o => toRef(o.value))) as T;
|
|
40
|
+
const pesponsiveParams = Object.keys(modifiableParams).filter(k => !!shcemes[k]?.responsive).map(k => toRef(modifiableParams, k));
|
|
41
|
+
const readonlyParams = reactive(cloneDeep(modifiableParams));
|
|
42
|
+
|
|
43
|
+
const update = (force?: boolean) => {
|
|
44
|
+
const prevParams = Object.freeze({ ...modifiableParams });
|
|
45
|
+
const beforeParams = {};
|
|
46
|
+
const modifiedParamKeys = Object.keys(readonlyParams).filter(pk => !eq(modifiableParams[pk], readonlyParams[pk]));
|
|
47
|
+
const beforeFuns = Object.entries(shcemes).filter(([k, s]) => modifiedParamKeys.includes(k) && !!s.effect).map(([_, s]) => s.effect!);
|
|
48
|
+
const needResetPage = modifiedParamKeys.some(k => !!shcemes[k]?.resetPage);
|
|
49
|
+
const pageParams = needResetPage || !!force ? { page: 1 } : {};
|
|
50
|
+
|
|
51
|
+
beforeFuns.forEach(fun => fun(beforeParams, prevParams));
|
|
52
|
+
Object.assign(readonlyParams, prevParams, pageParams, beforeParams);
|
|
53
|
+
|
|
54
|
+
for (const k in readonlyParams) {
|
|
55
|
+
// 为了拦截“只读属性赋值”的报错,因为无法判断哪些属性是只读的
|
|
56
|
+
try {
|
|
57
|
+
// @ts-expect-error 类型错误,暂时不理会
|
|
58
|
+
modifiableParams[k] = readonlyParams[k];
|
|
59
|
+
}
|
|
60
|
+
catch {}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
if (force)
|
|
64
|
+
Reflect.set(readonlyParams, '__t', Date.now());
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
watch(pesponsiveParams, () => update(), { deep: true });
|
|
68
|
+
|
|
69
|
+
const extra = {
|
|
70
|
+
/** 给查询器使用 */
|
|
71
|
+
$params: readonlyParams,
|
|
72
|
+
/** 更新值 */
|
|
73
|
+
update,
|
|
25
74
|
};
|
|
75
|
+
Object.setPrototypeOf(modifiableParams, extra);
|
|
26
76
|
|
|
27
|
-
return
|
|
77
|
+
return modifiableParams as typeof modifiableParams & typeof extra;
|
|
28
78
|
}
|
|
@@ -1,30 +1,46 @@
|
|
|
1
1
|
import { useInfiniteQuery, useQuery } from '@tanstack/vue-query';
|
|
2
|
-
import {
|
|
2
|
+
import { getNextPageParam, keepPreviousData } from '../../../../request/queryClient';
|
|
3
|
+
import { type ShcemeConfig, useFilterParams } from './useFilterParams';
|
|
3
4
|
|
|
4
5
|
/**
|
|
5
|
-
|
|
6
|
+
* 函数用于创建一个带有过滤参数的分页查询。
|
|
7
|
+
*
|
|
8
|
+
* @param apiFn - API函数
|
|
9
|
+
* @param params - 过滤参数的配置
|
|
10
|
+
* @returns 返回一个元组,包含查询对象和过滤参数
|
|
6
11
|
*/
|
|
7
|
-
export function useFilterPaginationQuery<
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
12
|
+
export function useFilterPaginationQuery<
|
|
13
|
+
Api extends Api.Request,
|
|
14
|
+
P extends Api.GetParam<Api>,
|
|
15
|
+
>(apiFn: Api, params: ShcemeConfig<P>) {
|
|
16
|
+
const filterParams = useFilterParams<Api.GetParam<Api>>(params);
|
|
11
17
|
const filterQuery = useQuery({
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
18
|
+
queryKey: [apiFn.id, 'pagination', filterParams.$params],
|
|
19
|
+
queryFn: () => apiFn(filterParams.$params) as Promise<Api.GetData<Api>>,
|
|
20
|
+
placeholderData: keepPreviousData,
|
|
15
21
|
});
|
|
16
22
|
|
|
17
23
|
return [filterQuery, filterParams] as const;
|
|
18
24
|
}
|
|
19
25
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
26
|
+
/**
|
|
27
|
+
* 函数用于创建一个带有过滤参数的无限滚动查询。
|
|
28
|
+
*
|
|
29
|
+
* @param apiFn - API函数
|
|
30
|
+
* @param params - 过滤参数的配置
|
|
31
|
+
* @returns 返回一个数组,包含查询对象和过滤参数
|
|
32
|
+
*/
|
|
33
|
+
export function useFilterInfiniteQuery<
|
|
34
|
+
Api extends Api.Request,
|
|
35
|
+
P extends Api.GetParam<Api>,
|
|
36
|
+
>(apiFn: Api, params: ShcemeConfig<P>) {
|
|
37
|
+
const filterParams = useFilterParams<Api.GetParam<Api>>(params);
|
|
24
38
|
const filterQuery = useInfiniteQuery({
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
39
|
+
queryKey: [apiFn.id, 'infinite', filterParams.$params],
|
|
40
|
+
queryFn: ctx => (apiFn({ ...filterParams.$params, ...ctx.pageParam }) as Promise<Api.GetData<Api>>),
|
|
41
|
+
initialPageParam: { page: 1, page_size: 10 },
|
|
42
|
+
placeholderData: keepPreviousData,
|
|
43
|
+
getNextPageParam,
|
|
28
44
|
});
|
|
29
45
|
|
|
30
46
|
return [filterQuery, filterParams] as const;
|