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

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.
@@ -1,6 +1,6 @@
1
1
  import dayjs, { type Dayjs } from '../../../libs/dayjs';
2
2
  import { tryOnScopeDispose } from '@vueuse/core';
3
- import { computed, reactive, watch, ref, type Ref } from 'vue';
3
+ import { computed, reactive, watch, customRef, type Ref } from 'vue';
4
4
  import type { Simplify } from 'type-fest';
5
5
 
6
6
  /**
@@ -11,7 +11,27 @@ export function getTtaTimeZone() {
11
11
  const win = window as any;
12
12
  const key = '__APP_TZ__';
13
13
 
14
- return (win[key] || (win[key] = ref(dayjs.tz.guess()))) as Ref<string>;
14
+ if (!win[key]) {
15
+ win[key] = customRef<string>((track, trigger) => {
16
+ return {
17
+ get() {
18
+ let value = localStorage.getItem(key);
19
+ if (!value) {
20
+ value = dayjs.tz.guess();
21
+ localStorage.setItem(key, value);
22
+ }
23
+ track();
24
+ return value;
25
+ },
26
+ set(newValue: string) {
27
+ localStorage.setItem(key, newValue);
28
+ trigger();
29
+ }
30
+ }
31
+ })
32
+ }
33
+
34
+ return win[key] as Ref<string>;
15
35
  }
16
36
 
17
37
  /**
@@ -41,6 +61,15 @@ export const onTtaTimeZone = (() => {
41
61
  }
42
62
  })();
43
63
 
64
+ export function standardizeTzParam(tz: string) {
65
+ if (tz === 'APP') {
66
+ return getTtaTimeZone().value;
67
+ } else if (tz === 'LOCAL') {
68
+ return dayjs.tz.guess();
69
+ }
70
+ return tz;
71
+ }
72
+
44
73
  type OfDayType = dayjs.Dayjs | undefined | null;
45
74
  type UnitType = dayjs.QUnitType | dayjs.OpUnitType;
46
75
  export const datetime = {
@@ -48,29 +77,29 @@ export const datetime = {
48
77
  * 将日期范围转换为 API 参数格式的时间戳范围
49
78
  * @param days 时间范围元组,包含开始和结束时间
50
79
  * @param unit 时间单位,默认为 'day'
51
- * @param useAppTz 是否使用时区,默认为 true
80
+ * @param tz 时区字符串,默认为 'APP'(应用时区)。特殊值:UTC、LOCAL、APP
52
81
  * @param keys 可选的键名元组,默认为 ['start_time', 'end_time']
53
82
  * @returns 返回一个对象,包含开始和结束时间的时间戳
54
83
  */
55
84
  toRangeForApiParams<KS extends readonly [string, string] = ['start_time', 'end_time']>(
56
85
  days: Array<OfDayType | undefined | null> | undefined | null,
57
- unit: UnitType = 'day',
58
- useAppTz: boolean = true,
86
+ unit: UnitType = 'day',
87
+ tz: string = 'APP',
59
88
  keys?: KS
60
89
  ) {
61
90
  if (!days || !days[0] || !days[1])
62
91
  return undefined;
63
92
 
64
- const tz = useAppTz ? getTtaTimeZone().value : dayjs.tz.guess();
93
+ const _tz = standardizeTzParam(tz);
65
94
  const _keys = (Array.isArray(keys) && keys?.length > 1) ? keys : ['start_time', 'end_time'];
66
95
 
67
96
  type RetType = KS extends readonly [string, string]
68
- ? Simplify<{ [K in KS[0]]: number } & { [K in KS[1]]: number }>
97
+ ? Simplify<{ [K in KS[0]]: number } & { [K in KS[1]]: number }>
69
98
  : { start_time: number; end_time: number };
70
99
 
71
100
  return {
72
- [_keys[0]]: dayjs(days[0].valueOf()).tz(tz).startOf(unit).valueOf(),
73
- [_keys[1]]: dayjs(days[1].valueOf()).tz(tz).endOf(unit).valueOf(),
101
+ [_keys[0]]: dayjs(days[0].valueOf()).tz(_tz).startOf(unit).valueOf(),
102
+ [_keys[1]]: dayjs(days[1].valueOf()).tz(_tz).endOf(unit).valueOf(),
74
103
  } as RetType;
75
104
  },
76
105
  /**
@@ -80,21 +109,19 @@ export const datetime = {
80
109
  * @return 返回一个包含开始和结束时间的元组,格式为 dayjs 对象
81
110
  */
82
111
  toRangeForForm(
83
- days: Array<OfDayType | string | undefined | null>,
84
- defaultRangeUnit?: UnitType,
112
+ days: Array<OfDayType | string | number | undefined | null>,
113
+ defaultRangeUnit?: UnitType,
85
114
  ) {
86
115
  const getDefaultRange = () => {
87
116
  const now = dayjs();
88
- return defaultRangeUnit
89
- ? [now.startOf(defaultRangeUnit), now.endOf(defaultRangeUnit)] as [dayjs.Dayjs, dayjs.Dayjs]
117
+ return defaultRangeUnit
118
+ ? [now.startOf(defaultRangeUnit), now.endOf(defaultRangeUnit)] as [dayjs.Dayjs, dayjs.Dayjs]
90
119
  : undefined;
91
120
  }
92
121
 
93
122
  if (!days || !days[0] || !days[1])
94
123
  return getDefaultRange();
95
124
 
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
125
  const [sDay, eDay] = days.map(d => dayjs(typeof d === 'string' ? Number(d) : d?.valueOf()));
99
126
 
100
127
  if (!sDay.isValid() || !eDay.isValid())
@@ -106,34 +133,34 @@ export const datetime = {
106
133
  * 获取指定日期的开始时间
107
134
  * @param unit 时间单位
108
135
  * @param day 日期对象
109
- * @param useAppTz 是否使用应用时区,默认为 true
136
+ * @param tz 时区字符串,默认为 'APP'(应用时区)。特殊值:UTC、LOCAL、APP
110
137
  * @returns 返回指定日期的开始时间,格式为 dayjs 对象
111
138
  */
112
- ofStart(unit: UnitType, day: OfDayType, useAppTz = true) {
139
+ ofStart(unit: UnitType, day: OfDayType, tz: string = 'APP') {
113
140
  if (!day)
114
141
  return undefined;
115
142
 
116
- const tz = useAppTz ? getTtaTimeZone().value : dayjs.tz.guess();
117
- return dayjs(day.valueOf()).tz(tz).startOf(unit);
143
+ const _tz = standardizeTzParam(tz);
144
+ return dayjs(day.valueOf()).tz(_tz).startOf(unit);
118
145
  },
119
146
  /**
120
147
  * 获取指定日期的结束时间
121
148
  * @param unit 时间单位
122
149
  * @param day 日期对象
123
- * @param useAppTz 是否使用应用时区,默认为 true
150
+ * @param tz 时区字符串,默认为 'APP'(应用时区)。特殊值:UTC、LOCAL、APP
124
151
  * @returns 返回指定日期的结束时间,格式为 dayjs 对象
125
152
  */
126
- ofEnd(unit: UnitType, day: OfDayType, useAppTz = true) {
153
+ ofEnd(unit: UnitType, day: OfDayType, tz: string = 'APP') {
127
154
  if (!day)
128
155
  return undefined;
129
156
 
130
- const tz = useAppTz ? getTtaTimeZone().value : dayjs.tz.guess();
131
- return dayjs(day.valueOf()).tz(tz).endOf(unit);
157
+ const _tz = standardizeTzParam(tz);
158
+ return dayjs(day.valueOf()).tz(_tz).endOf(unit);
132
159
  },
133
160
  }
134
161
 
135
162
  /** 为 DatePicker 组件提供响应式时区支持,当时区更新时,自动调整时间戳 */
136
- export function useDatePickerPropsForTz(
163
+ function useDatePickerPropsForTz(
137
164
  value: Ref<Dayjs | undefined>,
138
165
  props: {
139
166
  createPresets?: (day: Dayjs) => { label: string; value: Dayjs }[];
@@ -167,7 +194,7 @@ export function useDatePickerPropsForTz(
167
194
  });
168
195
  }
169
196
 
170
- export function useRangePickerPropsForTz(
197
+ function useRangePickerPropsForTz(
171
198
  value: Ref<[string, string] | [Dayjs, Dayjs] | undefined>,
172
199
  props: {
173
200
  createPresets?: (day: Dayjs) => { label: string; value: Dayjs[] }[];
@@ -192,86 +219,22 @@ export function useRangePickerPropsForTz(
192
219
  { label: '近30天', value: [day.subtract(29, 'day').startOf('day'), day.endOf('day')] },
193
220
  ];
194
221
  };
195
- const nowDay = computed(() => dayjs().tz(_tz.value));
196
222
  const _value = computed(() => {
197
223
  const v = value.value;
198
224
  if (v && v[0] && v[1]) {
199
225
  return [
200
- dayjs(v[0].valueOf()).tz(_tz.value),
201
- dayjs(v[1].valueOf()).tz(_tz.value),
226
+ dayjs(v[0].valueOf()),
227
+ dayjs(v[1].valueOf()),
202
228
  ] as [Dayjs, Dayjs];
203
229
  }
204
230
  return undefined;
205
231
  });
206
232
 
207
- watch(_tz, (newV, oldV) => {
208
- const v = value.value;
209
- if (!v || !v[0] || !v[1]) return;
210
-
211
- const newTzOffset = dayjs().tz(newV).utcOffset();
212
- const oldTzOffset = dayjs().tz(oldV).utcOffset();
213
- value.value = [
214
- dayjs(v[0].valueOf()).add((oldTzOffset - newTzOffset) * 60 * 1000),
215
- dayjs(v[1].valueOf()).add((oldTzOffset - newTzOffset) * 60 * 1000),
216
- ]
217
- });
218
-
219
233
  return reactive({
220
234
  'value': _value,
221
- 'onUpdate:value': (newVal: any) => value.value = newVal,
222
- 'presets': computed(() => props.createPresets!(nowDay.value)),
235
+ 'onUpdate:value': (v: any) => value.value = v,
236
+ 'presets': computed(() => props.createPresets!(dayjs())),
237
+ // showTime: computed(() => ({ defaultValue: [dayjs().startOf('day'), dayjs().endOf('day')] })),
238
+ format: 'YY-MM-DD HH:mm:ss'
223
239
  });
224
240
  };
225
-
226
- /** 为 RangePicker 组件提供响应式时区支持,当时区更新时,自动调整时间戳 */
227
- export function useRangePickerPropsForTz_old(
228
- ts: [Ref<number | undefined>, Ref<number | undefined>],
229
- props: {
230
- createPresets?: (day: Dayjs) => { label: string; value: Dayjs[] }[];
231
- } = {},
232
- tz?: Ref<string>,
233
- ) {
234
- // 默认值
235
- props.createPresets ??= (day: Dayjs) => {
236
- return [
237
- { label: '今天', value: [day.startOf('day'), day.endOf('day')] },
238
- { label: '昨天', value: [day.subtract(1, 'day').startOf('day'), day.subtract(1, 'day').endOf('day')] },
239
- { label: '前一天', value: [day.subtract(1, 'day').startOf('day'), day.subtract(1, 'day').endOf('day')] },
240
- { label: '后一天', value: [day.add(1, 'day').startOf('day'), day.add(1, 'day').endOf('day')] },
241
- { label: '本周', value: [day.startOf('week'), day.endOf('week')] },
242
- { label: '上周', value: [day.subtract(1, 'week').startOf('week'), day.subtract(1, 'week').endOf('week')] },
243
- { label: '本月', value: [day.startOf('month'), day.endOf('month')] },
244
- { label: '上个月', value: [day.subtract(1, 'month').startOf('month'), day.subtract(1, 'month').endOf('month')] },
245
- { label: '上上月', value: [day.subtract(2, 'month').startOf('month'), day.subtract(2, 'month').endOf('month')] },
246
- { label: '近7天', value: [day.subtract(6, 'day').startOf('day'), day.endOf('day')] },
247
- { label: '近30天', value: [day.subtract(29, 'day').startOf('day'), day.endOf('day')] },
248
- ];
249
- };
250
- const _tz = tz || getTtaTimeZone();
251
- const nowDay = computed(() => dayjs().tz(_tz.value));
252
- const inputDay = computed(() => {
253
- console.log('🤡 / ts:', ts);
254
- if (ts[0].value && ts[1].value)
255
- return [dayjs(ts[0].value).tz(_tz.value), dayjs(ts[1].value).tz(_tz.value)] as [Dayjs, Dayjs];
256
- return undefined;
257
- });
258
-
259
- watch(_tz, (newV, oldV) => {
260
- if (!ts[0].value || !ts[1].value) return;
261
-
262
- const newTzOffset = dayjs().tz(newV).utcOffset();
263
- const oldTzOffset = dayjs().tz(oldV).utcOffset();
264
- ts[0].value = ts[0].value + (oldTzOffset - newTzOffset) * 60 * 1000;
265
- ts[1].value = ts[1].value + (oldTzOffset - newTzOffset) * 60 * 1000;
266
- })
267
-
268
- return reactive({
269
- 'value': inputDay,
270
- 'onUpdate:value': (value: any) => {
271
- console.log('🤡 / value:', value);
272
- ts[0].value = dayjs(value[0]).valueOf();
273
- ts[1].value = dayjs(value[1]).valueOf();
274
- },
275
- 'presets': computed(() => props.createPresets!(nowDay.value)),
276
- });
277
- };
@@ -1,4 +1,5 @@
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, datetime } from './helpers';
4
+ export { getTtaTimeZone, onTtaTimeZone, datetime } from './helpers';
5
+ export { antdRangePickerPresets, antdRangePickerShowTimeProps } from './presetProps';
@@ -0,0 +1,23 @@
1
+ import { type RangePicker } from 'ant-design-vue';
2
+ import dayjs, { type Dayjs } from '../../../libs/dayjs';
3
+ import { type ComponentProps } from 'vue-component-type-helpers'
4
+
5
+ export const antdRangePickerPresets = [
6
+ { label: '今天', value: [dayjs().startOf('day'), dayjs().endOf('day')] },
7
+ { label: '昨天', value: [dayjs().subtract(1, 'day').startOf('day'), dayjs().subtract(1, 'day').endOf('day')] },
8
+ { label: '前一天', value: [dayjs().subtract(1, 'day').startOf('day'), dayjs().subtract(1, 'day').endOf('day')] },
9
+ { label: '后一天', value: [dayjs().add(1, 'day').startOf('day'), dayjs().add(1, 'day').endOf('day')] },
10
+ { label: '本周', value: [dayjs().startOf('week'), dayjs().endOf('week')] },
11
+ { label: '上周', value: [dayjs().subtract(1, 'week').startOf('week'), dayjs().subtract(1, 'week').endOf('week')] },
12
+ { label: '本月', value: [dayjs().startOf('month'), dayjs().endOf('month')] },
13
+ { label: '上个月', value: [dayjs().subtract(1, 'month').startOf('month'), dayjs().subtract(1, 'month').endOf('month')] },
14
+ { label: '上上月', value: [dayjs().subtract(2, 'month').startOf('month'), dayjs().subtract(2, 'month').endOf('month')] },
15
+ { label: '近7天', value: [dayjs().subtract(6, 'day').startOf('day'), dayjs().endOf('day')] },
16
+ { label: '近30天', value: [dayjs().subtract(29, 'day').startOf('day'), dayjs().endOf('day')] },
17
+ ] as { label: string; value: [Dayjs, Dayjs] }[]
18
+
19
+ export const antdRangePickerShowTimeProps: ComponentProps<typeof RangePicker> = {
20
+ presets: antdRangePickerPresets,
21
+ showTime: { defaultValue: [dayjs().startOf('day'), dayjs().endOf('day')] },
22
+ format: 'YY-MM-DD HH:mm:ss'
23
+ }
@@ -39,7 +39,7 @@ const PageRefresh = defineComponent({
39
39
  mounted() {
40
40
  const { router } = this.$props;
41
41
  const fullPath = router.currentRoute.value.fullPath;
42
- router.replace({ ...router.resolve(fullPath), force: true });
42
+ router.replace({ ...router.resolve(fullPath), force: true });
43
43
  },
44
44
  setup() {
45
45
  return () => null;
@@ -20,6 +20,7 @@ const props = withDefaults(
20
20
  );
21
21
 
22
22
  const tz = getTtaTimeZone();
23
+ const localTz = dayjs.tz.guess();
23
24
  const timestamp = computed(() => {
24
25
  let tsStr = String(props.ts || props.timestamp);
25
26
 
@@ -49,7 +50,7 @@ const text = computed(() => {
49
50
  <span class="op-50">指定</span>
50
51
  </div>
51
52
  <div>
52
- {{ dayjs(timestamp).tz(tz).format('YYYY-MM-DD HH:mm:ss') }}
53
+ {{ dayjs(timestamp).tz(localTz).format('YYYY-MM-DD HH:mm:ss') }}
53
54
  <span class="op-50">本地</span>
54
55
  </div>
55
56
  <div v-if="dayjs().utc">
@@ -5,13 +5,18 @@ import { KeepAlive, type KeepAliveProps } from 'vue';
5
5
  const props = defineProps<{
6
6
  cached: KeepAliveProps['include']
7
7
  }>();
8
+
9
+ function side(comp: any) {
10
+ console.log('🤡 / side / comp:', comp)
11
+ return comp;
12
+ }
8
13
  </script>
9
14
 
10
15
  <template>
11
16
  <RouterView #default="{ Component }">
12
17
  <KeepAlive :include="props.cached">
13
18
  <Suspense>
14
- <component :is="Component" />
19
+ <component :is="Component" :key="$route.fullPath" />
15
20
  <template #fallback>
16
21
  <div class="flex justify-center items-center h-full">
17
22
  <div class="flex items-center">
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.14",
4
+ "version": "0.3.0-beta.15",
5
5
  "description": "",
6
6
  "author": "",
7
7
  "license": "ISC",
@@ -1,3 +1,4 @@
1
+ import type { I18nOptions } from 'vue-i18n';
1
2
  import { omitBy } from '../../libs/lodash-es';
2
3
 
3
4
  /**
@@ -32,6 +33,14 @@ export function omitLocale(modules: Record<string, any>, excludes: string[] = []
32
33
  return omitBy(modules, (_, path) => excludes.some(locale => path.includes(locale)));
33
34
  }
34
35
 
36
+ /** 添加语言格式 */
37
+ export function addDatetimeFormat<T extends string>(name: T, config: NonNullable<I18nOptions['datetimeFormats']>[string][string]) {
38
+ return {
39
+ [name]: config,
40
+ [`${name}-utc`]: { ...config, timeZone: 'UTC' },
41
+ } as Record<T | `${T}-utc`, typeof config>;
42
+ }
43
+
35
44
  /**
36
45
  * 加密 JSON 消息
37
46
  */
@@ -1,9 +0,0 @@
1
- <script setup lang="ts">
2
- import { useTestStore } from './testStore';
3
-
4
- useTestStore();
5
- </script>
6
-
7
- <template>
8
- <div>123</div>
9
- </template>
@@ -1,11 +0,0 @@
1
- import { useQueryClient } from '@tanstack/vue-query';
2
- import { defineStore } from 'pinia';
3
- import { useRouter } from 'vue-router';
4
-
5
- export const useTestStore = defineStore('test-store', () => {
6
- const router = useRouter();
7
- const queryClient = useQueryClient();
8
- console.log('🤡 / router:', router);
9
- console.log('🤡 / queryClient:', queryClient);
10
- return {};
11
- });