@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.
Files changed (67) hide show
  1. package/admin/adminPlugin.ts +47 -0
  2. package/admin/components/filter/src/FilterParam.vue +76 -78
  3. package/admin/components/filter/src/FilterReset.vue +2 -2
  4. package/admin/components/filter/src/useFilterParams.ts +75 -25
  5. package/admin/components/filter/src/useFilterQuery.ts +32 -16
  6. package/admin/components/rich-text/index.ts +2 -0
  7. package/admin/components/rich-text/src/RichText.vue +342 -0
  8. package/admin/components/rich-text/src/imageUploader.ts +34 -0
  9. package/admin/components/rich-text/src/type.d.ts +7 -0
  10. package/admin/components/text/src/Datetime.vue +47 -48
  11. package/admin/components/upload/index.ts +2 -0
  12. package/admin/components/upload/src/PictureCardUpload.vue +143 -0
  13. package/admin/components/upload/src/customRequests.ts +31 -0
  14. package/admin/defines/index.ts +1 -1
  15. package/admin/defines/route/helpers.ts +0 -1
  16. package/admin/defines/startup/defineStartup.ts +8 -1
  17. package/admin/defines/startup/index.ts +1 -1
  18. package/admin/defines/startup/{getStartups.ts → runStartup.ts} +16 -7
  19. package/admin/layout/large/Breadcrumb.vue +68 -69
  20. package/admin/layout/large/Content.vue +23 -24
  21. package/admin/layout/large/Menu.vue +68 -69
  22. package/admin/layout/large/PageTab.vue +70 -71
  23. package/admin/permission/index.ts +2 -4
  24. package/admin/permission/routerGuard.ts +41 -43
  25. package/admin/permission/vuePlugin.ts +46 -30
  26. package/admin/route-guards/collapseMenu.ts +3 -3
  27. package/admin/route-guards/pageTitle.ts +18 -19
  28. package/admin/scripts/deploy.ts +67 -0
  29. package/admin/{hooks/useMenu.ts → stores/createUseMenuStore.ts} +133 -128
  30. package/admin/{hooks/usePage.ts → stores/createUsePageStore.ts} +145 -141
  31. package/admin/stores/createUsePageTabStore.ts +43 -0
  32. package/admin/{permission/usePermission.ts → stores/createUsePermissionStore.ts} +57 -52
  33. package/admin/stores/index.ts +8 -0
  34. package/admin/styles/classCover.scss +8 -0
  35. package/antd/hooks/useAntdForm.helpers.ts +92 -8
  36. package/antd/hooks/useAntdForm.ts +55 -63
  37. package/antd/hooks/useAntdTable.ts +12 -0
  38. package/antd/index.ts +1 -1
  39. package/libs/a-calc.ts +1 -0
  40. package/libs/axios.ts +2 -0
  41. package/libs/bignumber.ts +2 -0
  42. package/libs/dayjs.ts +5 -0
  43. package/libs/echarts.ts +5 -0
  44. package/libs/localstorage-slim.ts +2 -0
  45. package/libs/lodash-es.ts +1 -0
  46. package/libs/pinia.ts +1 -0
  47. package/libs/vue-query.ts +1 -0
  48. package/libs/vueuse.ts +3 -0
  49. package/package.json +97 -53
  50. package/request/helpers.ts +20 -1
  51. package/request/interceptors/checkCode.ts +3 -3
  52. package/request/interceptors/returnResultType.ts +2 -2
  53. package/request/queryClient.ts +34 -21
  54. package/utils/upload/AwsS3.ts +76 -0
  55. package/utils/upload/fileHandlers.ts +27 -0
  56. package/utils/upload/index.ts +2 -0
  57. package/vite/index.d.ts +1 -0
  58. package/vite/index.mjs +27 -0
  59. package/vue/components/echarts/index.ts +1 -0
  60. package/vue/components/echarts/src/ECharts.vue +48 -0
  61. package/vue/components/index.ts +1 -0
  62. package/vue/components/infinite-query/src/InfiniteQuery.vue +2 -8
  63. package/vue/components/test/KitTest.vue +9 -0
  64. package/vue/components/test/testStore.ts +11 -0
  65. package/admin/hooks/index.ts +0 -5
  66. package/admin/hooks/usePageTab.ts +0 -35
  67. 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 { getDependencies } from '../../../../kitDependencies';
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
- const { dayjs } = getDependencies();
28
-
29
- if (!range?.every(v => dayjs(v).isValid()))
30
- return '';
31
-
32
- return `${dayjs(range[0]).format(template)} ~ ${dayjs(range[1]).format(template)}`;
33
- }
34
-
35
- function options(
36
- value?: string | number | Array<string | number>,
37
- options?: Array<{ value: string | number, label: any }>,
38
- ) {
39
- if (isNil(value) || isNil(options))
40
- return;
41
- if (value === '')
42
- return;
43
-
44
- const _value = Array.isArray(value) ? value : [value];
45
-
46
- return options
47
- .filter(o => _value.includes(o.value))
48
- .map(o => o.label)
49
- .join(', ');
50
- }
51
- </script>
52
-
53
- <script setup lang="ts">
54
- const props = defineProps<{
55
- label: string
56
- content?: any
57
- }>();
58
- </script>
59
-
60
- <template>
61
- <div v-if="props.content" class="item-param">
62
- <span class="label">{{ props.label }}</span>
63
- <span class="content">{{ props.content }}</span>
64
- </div>
65
- </template>
66
-
67
- <style lang="scss" scoped>
68
- .label {
69
- display: inline-block;
70
- margin-right: 0.3em;
71
- color: theme('colors.gray.DEFAULT');
72
- }
73
-
74
- .content {
75
- color: theme('colors.primary.DEFAULT');
76
- word-break: break-all;
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?.({ page: 1 });
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?.({ page: 1 });
38
+ props.filterParams?.update?.(true);
39
39
  emits('reset');
40
40
  }
41
41
  </script>
@@ -1,28 +1,78 @@
1
- import { extendRef } from '@vueuse/core';
2
- import { reactive } from 'vue';
3
-
4
- interface PageParams { page?: string | number, page_size?: string | number };
5
- const defaultPageParams: PageParams = { page: 1, page_size: 10 };
6
-
7
- /**
8
- * 用于管理筛选参数
9
- *
10
- * @param _api - API 函数。
11
- * @param buildParams - 构建参数的函数。
12
- * @param pageParams - 默认的页面参数。
13
- *
14
- * @returns 包含筛选参数和更新函数的对象。
15
- */
16
- export function useFilterParams<R extends Api.Request, AP extends Api.GetParam<R>, BP extends AP>(
17
- _api: R,
18
- buildParams: () => BP,
19
- pageParams = defaultPageParams,
20
- ) {
21
- type FinalParams = AP & BP & PageParams;
22
- const params = reactive({ ...pageParams, ...buildParams() } as FinalParams);
23
- const update = (newParams?: Partial<FinalParams>) => {
24
- Object.assign(params, { ...buildParams(), ...newParams, __t: Date.now() });
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 extendRef(params, { update });
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 { useFilterParams } from './useFilterParams';
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<Api extends Api.Request, P extends Api.GetParam<Api>>(apiFn: Api, paramsFn: () => P) {
8
- type Data = Api.GetData<Api>;
9
-
10
- const filterParams = useFilterParams(apiFn, paramsFn);
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
- keepPreviousData: true,
13
- queryKey: [apiFn.id, 'pagination', filterParams],
14
- queryFn: () => (apiFn(filterParams) as Promise<Data>),
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
- export function useFilterInfiniteQuery<Api extends Api.Request, P extends Api.GetParam<Api>>(apiFn: Api, paramsFn: () => P) {
21
- type Data = Api.GetData<Api>;
22
-
23
- const filterParams = useFilterParams(apiFn, paramsFn);
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
- keepPreviousData: true,
26
- queryKey: [apiFn.id, 'infinite', filterParams],
27
- queryFn: ctx => (apiFn({ ...filterParams, ...ctx.pageParam }) as Promise<Data>),
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;
@@ -0,0 +1,2 @@
1
+ export { default as RichText } from './src/RichText.vue';
2
+ export { createImageUploaderForAws3 } from './src/imageUploader';