@peng_kai/kit 0.3.0-beta.12 → 0.3.0-beta.14

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.
@@ -3,6 +3,10 @@ import { tryOnScopeDispose } from '@vueuse/core';
3
3
  import { computed, reactive, watch, ref, type Ref } from 'vue';
4
4
  import type { Simplify } from 'type-fest';
5
5
 
6
+ /**
7
+ * 获取应用的时区,默认使用浏览器的时区
8
+ * @returns 返回一个响应式的时区字符串
9
+ */
6
10
  export function getTtaTimeZone() {
7
11
  const win = window as any;
8
12
  const key = '__APP_TZ__';
@@ -10,6 +14,9 @@ export function getTtaTimeZone() {
10
14
  return (win[key] || (win[key] = ref(dayjs.tz.guess()))) as Ref<string>;
11
15
  }
12
16
 
17
+ /**
18
+ * 监听应用的时区变化的函数
19
+ */
13
20
  export const onTtaTimeZone = (() => {
14
21
  const ttaTz = getTtaTimeZone();
15
22
  const cbList: any[] = [];
@@ -34,47 +41,95 @@ export const onTtaTimeZone = (() => {
34
41
  }
35
42
  })();
36
43
 
37
- type OfDayType = Dayjs | undefined | null;
44
+ type OfDayType = dayjs.Dayjs | undefined | null;
38
45
  type UnitType = dayjs.QUnitType | dayjs.OpUnitType;
39
- export const dayOf = {
40
- rangeTs<KS extends readonly [string, string] = ['start_time', 'end_time']>(
41
- unit: UnitType,
42
- day: Array<OfDayType> | undefined | null,
46
+ export const datetime = {
47
+ /**
48
+ * 将日期范围转换为 API 参数格式的时间戳范围
49
+ * @param days 时间范围元组,包含开始和结束时间
50
+ * @param unit 时间单位,默认为 'day'
51
+ * @param useAppTz 是否使用时区,默认为 true
52
+ * @param keys 可选的键名元组,默认为 ['start_time', 'end_time']
53
+ * @returns 返回一个对象,包含开始和结束时间的时间戳
54
+ */
55
+ toRangeForApiParams<KS extends readonly [string, string] = ['start_time', 'end_time']>(
56
+ days: Array<OfDayType | undefined | null> | undefined | null,
57
+ unit: UnitType = 'day',
58
+ useAppTz: boolean = true,
43
59
  keys?: KS
44
- ): KS extends readonly [string, string]
45
- ? Simplify<{ [K in KS[0]]: number } & { [K in KS[1]]: number }>
46
- : { start_time: number; end_time: number } {
47
- if (!day || !day[0] || !day[1])
48
- return undefined as any;
60
+ ) {
61
+ if (!days || !days[0] || !days[1])
62
+ return undefined;
49
63
 
50
- const tz = getTtaTimeZone().value;
64
+ const tz = useAppTz ? getTtaTimeZone().value : dayjs.tz.guess();
51
65
  const _keys = (Array.isArray(keys) && keys?.length > 1) ? keys : ['start_time', 'end_time'];
52
66
 
67
+ type RetType = KS extends readonly [string, string]
68
+ ? Simplify<{ [K in KS[0]]: number } & { [K in KS[1]]: number }>
69
+ : { start_time: number; end_time: number };
70
+
53
71
  return {
54
- [_keys[0]]: dayjs(day[0].valueOf()).tz(tz).startOf(unit).valueOf(),
55
- [_keys[1]]: dayjs(day[1].valueOf()).tz(tz).endOf(unit).valueOf(),
56
- } as any;
72
+ [_keys[0]]: dayjs(days[0].valueOf()).tz(tz).startOf(unit).valueOf(),
73
+ [_keys[1]]: dayjs(days[1].valueOf()).tz(tz).endOf(unit).valueOf(),
74
+ } as RetType;
75
+ },
76
+ /**
77
+ * 将日期范围转换为表单使用的时间范围
78
+ * @param days 时间范围元组,包含开始和结束时间
79
+ * @param defaultRangeUnit 默认的时间范围单位,如果未提供,则返回 undefined
80
+ * @return 返回一个包含开始和结束时间的元组,格式为 dayjs 对象
81
+ */
82
+ toRangeForForm(
83
+ days: Array<OfDayType | string | undefined | null>,
84
+ defaultRangeUnit?: UnitType,
85
+ ) {
86
+ const getDefaultRange = () => {
87
+ const now = dayjs();
88
+ return defaultRangeUnit
89
+ ? [now.startOf(defaultRangeUnit), now.endOf(defaultRangeUnit)] as [dayjs.Dayjs, dayjs.Dayjs]
90
+ : undefined;
91
+ }
92
+
93
+ if (!days || !days[0] || !days[1])
94
+ return getDefaultRange();
95
+
96
+ // const sDay = dayjs(typeof days[0] === 'string' ? Number(days[0]) : days[0].valueOf());
97
+ // const eDay = dayjs(typeof days[1] === 'string' ? Number(days[1]) : days[1].valueOf());
98
+ const [sDay, eDay] = days.map(d => dayjs(typeof d === 'string' ? Number(d) : d?.valueOf()));
99
+
100
+ if (!sDay.isValid() || !eDay.isValid())
101
+ return getDefaultRange();
102
+
103
+ return [sDay, eDay] as [dayjs.Dayjs, dayjs.Dayjs];
57
104
  },
58
- start(unit: UnitType, day: OfDayType) {
105
+ /**
106
+ * 获取指定日期的开始时间
107
+ * @param unit 时间单位
108
+ * @param day 日期对象
109
+ * @param useAppTz 是否使用应用时区,默认为 true
110
+ * @returns 返回指定日期的开始时间,格式为 dayjs 对象
111
+ */
112
+ ofStart(unit: UnitType, day: OfDayType, useAppTz = true) {
59
113
  if (!day)
60
114
  return undefined;
61
115
 
62
- const tz = getTtaTimeZone().value;
116
+ const tz = useAppTz ? getTtaTimeZone().value : dayjs.tz.guess();
63
117
  return dayjs(day.valueOf()).tz(tz).startOf(unit);
64
118
  },
65
- startTs(unit: UnitType, day: OfDayType) {
66
- this.start(unit, day);
67
- },
68
- end(unit: UnitType, day: OfDayType) {
119
+ /**
120
+ * 获取指定日期的结束时间
121
+ * @param unit 时间单位
122
+ * @param day 日期对象
123
+ * @param useAppTz 是否使用应用时区,默认为 true
124
+ * @returns 返回指定日期的结束时间,格式为 dayjs 对象
125
+ */
126
+ ofEnd(unit: UnitType, day: OfDayType, useAppTz = true) {
69
127
  if (!day)
70
128
  return undefined;
71
129
 
72
- const tz = getTtaTimeZone().value;
130
+ const tz = useAppTz ? getTtaTimeZone().value : dayjs.tz.guess();
73
131
  return dayjs(day.valueOf()).tz(tz).endOf(unit);
74
132
  },
75
- endTs(unit: UnitType, day: OfDayType) {
76
- this.end(unit, day);
77
- },
78
133
  }
79
134
 
80
135
  /** 为 DatePicker 组件提供响应式时区支持,当时区更新时,自动调整时间戳 */
@@ -156,10 +211,9 @@ export function useRangePickerPropsForTz(
156
211
  const newTzOffset = dayjs().tz(newV).utcOffset();
157
212
  const oldTzOffset = dayjs().tz(oldV).utcOffset();
158
213
  value.value = [
159
- dayjs(v[0]).add((oldTzOffset - newTzOffset) * 60 * 1000),
160
- dayjs(v[1]).add((oldTzOffset - newTzOffset) * 60 * 1000),
214
+ dayjs(v[0].valueOf()).add((oldTzOffset - newTzOffset) * 60 * 1000),
215
+ dayjs(v[1].valueOf()).add((oldTzOffset - newTzOffset) * 60 * 1000),
161
216
  ]
162
- console.log('🤡 / value.value:', value.value[0].valueOf())
163
217
  });
164
218
 
165
219
  return reactive({
@@ -1,4 +1,4 @@
1
1
  export { default as TimeFieldSelectForLabel } from './TimeFieldSelectForLabel.vue';
2
2
  export { default as TtaTimeZone } from './TtaTimeZone.vue';
3
3
  export { default as PeriodPicker } from './PeriodPicker.vue';
4
- export { useDatePickerPropsForTz, useRangePickerPropsForTz, getTtaTimeZone, onTtaTimeZone, dayOf } from './helpers';
4
+ export { useDatePickerPropsForTz, useRangePickerPropsForTz, getTtaTimeZone, onTtaTimeZone, datetime } from './helpers';
@@ -16,6 +16,7 @@ const props = withDefaults(defineProps<{
16
16
  const emits = defineEmits<{
17
17
  (e: 'filter'): void
18
18
  (e: 'reset'): void
19
+ (e: 'setColumnsConfig', columnsConfig: any): void
19
20
  }>();
20
21
 
21
22
  const loading = computed(() => {
@@ -48,7 +49,12 @@ function openTableSettingModal() {
48
49
  title: typeof x.title === 'string' ? x.title : x.dataIndex || '',
49
50
  })) || [];
50
51
 
51
- TableSettingModal.open({ tableColumns });
52
+ TableSettingModal.open({ tableColumns })?.then((res) => {
53
+ TableSettingModal.close();
54
+ if (res) {
55
+ emits('setColumnsConfig', res);
56
+ }
57
+ });
52
58
  }
53
59
 
54
60
  onTtaTimeZone(() => {
@@ -1,8 +1,9 @@
1
1
  <script lang="ts">
2
- import { Button, Switch, Divider, Select, type TableColumnsType } from 'ant-design-vue';
2
+ import { RadioGroup,type TableColumnsType } from 'ant-design-vue';
3
3
  import { reactive, defineAsyncComponent, ref } from 'vue';
4
4
  import { useDragAndDrop } from "fluid-dnd/vue";
5
5
  import { useAntdModal } from '../../../../../antd/hooks/useAntdModal';
6
+ import { type ColumnConfig } from '../../../../../antd/hooks/useAntdTable';
6
7
 
7
8
  export const TableSettingModal = useAntdModal(
8
9
  // eslint-disable-next-line import/no-self-import
@@ -10,17 +11,10 @@ export const TableSettingModal = useAntdModal(
10
11
  {
11
12
  title: '表格设置',
12
13
  width: 500,
13
- // footer: null,
14
14
  centered: true,
15
15
  maskClosable: false,
16
16
  }
17
17
  );
18
-
19
- const showTypeOptions = [
20
- { label: '显示', value: 'show' },
21
- { label: '简略', value: 'simple' },
22
- { label: '隐藏', value: 'hidden' },
23
- ];
24
18
  </script>
25
19
 
26
20
  <script lang="ts" setup>
@@ -31,33 +25,58 @@ const columnsConfig = ref(props.tableColumns.map((col: any) => ({
31
25
  title: col.title as string,
32
26
  dataIndex: col.dataIndex as string,
33
27
  visible: col.visible !== false,
28
+ compact: col.compact === true,
34
29
  })));
30
+ const columnsShowOptions = reactive(Object.fromEntries(props.tableColumns.map((col: any) => {
31
+ const options = [{ label: '显示', value: 'show' }, { label: '隐藏', value: 'hidden' }];
32
+ col.compactable === true && options.unshift({ label: '简略', value: 'compact' });
33
+ return [col.dataIndex, options];
34
+ })) as Record<string, { value: string; options: string }[]>);
35
+ const columnsShowValue = reactive(Object.fromEntries(props.tableColumns.map((col: any) => {
36
+ const value = col.visible === false ? 'hidden' : (col.compact === true && col.compactable === true) ? 'compact' : 'show';
37
+ return [col.dataIndex, value]
38
+ })) as Record<string, string>);
35
39
 
36
40
  const [$ctn] = useDragAndDrop(columnsConfig, {
37
41
  handlerSelector: '.drag-handler',
38
42
  draggingClass: 'op-50',
39
43
  direction: 'vertical',
40
44
  });
45
+
46
+ defineExpose({
47
+ confirm(_: any, resolve: (data: any) => void) {
48
+ const newColumnsConfig = columnsConfig.value.map((col) => ({
49
+ ...col,
50
+ visible: columnsShowValue[col.dataIndex] !== 'hidden',
51
+ compact: columnsShowValue[col.dataIndex] === 'compact',
52
+ })) as ColumnConfig[];
53
+ resolve(newColumnsConfig);
54
+ return true;
55
+ },
56
+ })
41
57
  </script>
42
58
 
43
59
  <template>
44
60
  <div>
45
61
  <div>
46
- <Divider>列设置</Divider>
62
+ <!-- <Divider>列设置</Divider> -->
47
63
  <div ref="$ctn">
48
- <div v-for="(col, i) in columnsConfig" :key="col.dataIndex" :index="i" class="flex items-center gap-2 p-2 select-none">
49
- <div class="drag-handler flex items-center justify-center cursor-move p-1 -m-2">
50
- <i class="i-material-symbols:drag-indicator" />
64
+ <div
65
+ v-for="(col, i) in columnsConfig" :key="col.dataIndex" :index="i"
66
+ class="flex items-center gap-2 p-2 select-none"
67
+ >
68
+ <div class="drag-handler flex items-center justify-center p-1 -m-2 mr-auto">
69
+ <i class="i-material-symbols:drag-indicator" />&nbsp;
70
+ <span >{{ col.title }}</span>
51
71
  </div>
52
- <span class="mr-auto">{{ col.title }}</span>
53
- <Select value="show" :options="showTypeOptions" />
54
- <!-- <Switch checked-children="简略" un-checked-children="简略" />
55
- <Switch checked-children="显示" un-checked-children="显示" />
56
- <Button>上</Button>
57
- <Button>下</Button> -->
72
+ <RadioGroup
73
+ v-model:value="columnsShowValue[col.dataIndex]"
74
+ :options="columnsShowOptions[col.dataIndex]"
75
+ optionType="button" buttonStyle="solid" size="small"
76
+ />
77
+ <!-- <Select v-model:value="columnsShowValue[col.dataIndex]" :options="columnsShowOptions[col.dataIndex]" /> -->
58
78
  </div>
59
79
  </div>
60
-
61
80
  </div>
62
81
  </div>
63
82
  </template>
@@ -5,7 +5,7 @@ import { type UseQueryReturnType } from '@tanstack/vue-query'
5
5
  import { watch, ref, computed } from 'vue'
6
6
  import dayjs from '../../../libs/dayjs';
7
7
  import { useRouter } from 'vue-router';
8
- import audioURL from './y682.mp3';
8
+ import audioURL from './y682.mp3?url';
9
9
 
10
10
  const noticeAudio = new Audio(audioURL);
11
11
  noticeAudio.src = audioURL;
@@ -88,7 +88,7 @@ useIntervalFn(() => {
88
88
  <i class="i-ri:notification-4-line block text-5" :class="{ shake: !!noticeNum }" />
89
89
  </div>
90
90
  <template #overlay>
91
- <Menu v-if="noticeNum" @click="visible = false">
91
+ <Menu v-if="noticeNum" @click="visible = false" class="max-h-100 overflow-y-auto">
92
92
  <MenuItem v-for="(item, i) of noticesQry.data.value" :key="i" @click="operate(item)">
93
93
  <div class="min-w-50">
94
94
  <div>{{ item.title }}</div>
@@ -53,8 +53,10 @@ export function useAntdModal<Comp extends Component>(
53
53
  ...defaultModalProps,
54
54
  ...isProxy(modalProps) ? toRefs(modalProps) : modalProps,
55
55
  confirmLoading: toRef(() => (refs.comp as any)?.loading),
56
- onOk: (e: MouseEvent) => {
57
- (refs.comp as any)?.confirm?.(e);
56
+ onOk: async (e: MouseEvent) => {
57
+ const comp = refs.comp as any;
58
+ const isClosed = await comp?.confirm?.(e, (data: any) => promiseResolvers?.resolve(data));
59
+ // isClosed === true && (_modalProps.open = false);
58
60
  modalProps.onOk?.(e);
59
61
  },
60
62
  });
@@ -96,11 +98,11 @@ export function useAntdModal<Comp extends Component>(
96
98
 
97
99
  return promiseResolvers.promise;
98
100
  };
99
- const confirm = (ev: any) => {
101
+ const onConfirm = (ev: any) => {
100
102
  _modalProps.open = false;
101
103
  promiseResolvers.resolve(ev);
102
104
  };
103
- const close = (reason?: any) => {
105
+ const onClose = (reason?: any) => {
104
106
  _modalProps.open = false;
105
107
  _onClose(reason);
106
108
  };
@@ -122,8 +124,8 @@ export function useAntdModal<Comp extends Component>(
122
124
  !visiable && _onClose();
123
125
  };
124
126
  (compProps as any).ref = setRefs.comp;
125
- (compProps as any).onClose = close;
126
- (compProps as any).onConfirm = confirm;
127
+ (compProps as any).onClose = onClose;
128
+ (compProps as any).onConfirm = onConfirm;
127
129
 
128
130
  tryOnBeforeUnmount(_onClose);
129
131
  onDeactivated(_onClose);
@@ -136,6 +138,6 @@ export function useAntdModal<Comp extends Component>(
136
138
  return refs.comp;
137
139
  },
138
140
  open,
139
- close,
141
+ close: onClose,
140
142
  };
141
143
  }
@@ -54,7 +54,7 @@ export function useAntdTable<
54
54
  }
55
55
  }
56
56
  };
57
- const { defineColumns } = useTableColumns<LocalColumnsType>();
57
+ const { defineColumns, setColumnsConfig } = useTableColumns<LocalColumnsType>();
58
58
  const defineRowSelection = (rowSelectionGetter: () => LocalTableRowSelection = () => ({})) => {
59
59
  const rowSelection = reactive(rowSelectionGetter());
60
60
 
@@ -114,8 +114,10 @@ export function useAntdTable<
114
114
  dataIndexs,
115
115
  /** 【类型辅助】bodyCell 插槽数据的精确类型描述 */
116
116
  bodyCellType,
117
- /** 【类型辅助】用于定义出类型精确的 columns */
117
+ /** 用于定义 columns */
118
118
  defineColumns,
119
+ /** 用于设置 columns 的配置 */
120
+ setColumnsConfig,
119
121
  /** 【类型辅助】用于定义出类型精确的 rowSelection */
120
122
  defineRowSelection,
121
123
  /** 内置的 ATable onChange 事件,默认在 `tableProps` 中 */
@@ -129,8 +131,9 @@ type GetRecordType<T> = T extends UseQueryReturnType<infer D, any>
129
131
  : never
130
132
  : never;
131
133
 
134
+ export type ColumnConfig = { title: string, dataIndex: string, visible: boolean, compact: boolean }
135
+
132
136
  function useTableColumns<LCT extends any[]>() {
133
- type ColumnConfig = {title: string, dataIndex: string, visible: boolean}
134
137
 
135
138
  const columnsConfig = ref<Array<ColumnConfig> | null>(null);
136
139
  let originalColumns: LCT | null = null;
@@ -143,11 +146,18 @@ function useTableColumns<LCT extends any[]>() {
143
146
  let columns = columnsGetter();
144
147
 
145
148
  if (config?.length) {
146
- // 过滤掉不可见的列
147
- columns = columns.filter((col: any) => {
149
+ columns = columns.map((col: any) => {
148
150
  const x = config.find(c => c.dataIndex === col.dataIndex);
149
- return x ? x.visible : true;
151
+ if (x) {
152
+ return { ...col, visible: x.visible, compact: x.compact,};
153
+ }
154
+ return col;
150
155
  }) as LCT;
156
+ // 过滤掉不可见的列
157
+ // columns = columns.filter((col: any) => {
158
+ // const x = config.find(c => c.dataIndex === col.dataIndex);
159
+ // return x ? x.visible : true;
160
+ // }) as LCT;
151
161
  // 基于 config 的顺序排序
152
162
  columns = config.map(x => {
153
163
  const col = columns.find(c => c.dataIndex === x.dataIndex);
@@ -161,18 +171,12 @@ function useTableColumns<LCT extends any[]>() {
161
171
 
162
172
  const setColumnsConfig = (columns: Array<ColumnConfig>) => {
163
173
  columnsConfig.value = columns;
164
-
165
- // if (!columnsConfig.value) {
166
- // columnsConfig.value = originalColumns?.map(col => ({
167
- // title: col.title,
168
- // dataIndex: col.dataIndex as string,
169
- // visible: true,
170
- // })) || [];
171
- // }
174
+ console.log('🤡 / columns:', columns);
172
175
  };
173
176
 
174
177
 
175
178
  return {
176
179
  defineColumns,
180
+ setColumnsConfig
177
181
  };
178
182
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@peng_kai/kit",
3
3
  "type": "module",
4
- "version": "0.3.0-beta.12",
4
+ "version": "0.3.0-beta.14",
5
5
  "description": "",
6
6
  "author": "",
7
7
  "license": "ISC",