@neatui/vue 2.17.5 → 3.1.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 (29) hide show
  1. package/.prettierrc +12 -0
  2. package/README.md +82 -0
  3. package/package.json +7 -4
  4. package/src/components/basic/IFollowView.vue +47 -34
  5. package/src/components/basic/IPickerView.vue +16 -8
  6. package/src/components/basic/IRouterView.vue +133 -74
  7. package/src/components/basic/IScrollView.vue +460 -52
  8. package/src/components/basic/LayerView/Layer.vue +33 -24
  9. package/src/components/basic/LayerView/index.ts +3 -1
  10. package/src/components/form/DateView@v3.vue +2 -1
  11. package/src/components/form/Input@v3.vue +9 -6
  12. package/src/components/form/TextArea.vue +3 -3
  13. package/src/components/loader/FormLoader/FormLoader.vue +29 -4
  14. package/src/components/loader/LayerLoader/LayerLoader.vue +2 -1
  15. package/src/components/loader/LimitLoader/LimitLoader@v3.vue +3 -3
  16. package/src/components/loader/TableLoader/TableLoader.vue +3 -3
  17. package/src/components/loader/index.ts +1 -1
  18. package/src/components/tools/FormDraftsView.vue +15 -11
  19. package/src/components/tools/FormVerifyView.vue +4 -3
  20. package/src/components/tools/MoreTools.vue +4 -3
  21. package/src/components/tools/Pagination@a.vue +74 -38
  22. package/src/components/tools/Pagination@b.vue +2 -1
  23. package/src/store/frame.ts +18 -10
  24. package/src/utils/theme.ts +3 -0
  25. package/src/components/basic/follow.ts +0 -133
  26. package/src/components/loader/FormLoader/FormLoader@v2.vue +0 -422
  27. package/src/components/loader/FormLoader/NodeLoader.vue +0 -85
  28. package/src/components/loader/FormLoader@v1/FormLoader.vue +0 -506
  29. package/src/components/loader/FormLoader@v1/FormRender.vue +0 -302
@@ -1,34 +1,64 @@
1
1
  <template>
2
2
  <div
3
+ ref="root"
3
4
  class="fekit-ipull-scroll"
4
5
  :ui-scroll="`:y ${stable ? 'stable' : ''}`"
5
- ref="root"
6
6
  >
7
- <div class="full">
8
- <div class="fs-xs co-text o-mm" fekit-pullload-head="" v-if="pull">
9
- <slot name="pull-head" :state="demo.store.pull">
10
- <div v-show="demo.store.pull < 2" ui-flex="row cm">
11
- <i class="pulldown icon icon-pulldown" :class="`${demo.store.pull === 1 ? 'toup' : ''}`"></i>
12
- <span v-show="demo.store.pull === 0">下拉刷新</span>
13
- <span v-show="demo.store.pull === 1">松开加载</span>
14
- </div>
15
- <div v-show="demo.store.pull === 2" ui-flex="row cm">
16
- <span ui-load="@d"></span>
17
- </div>
18
- <div v-show="demo.store.pull === 3" ui-flex="row cm">
19
- <span>刷新完成</span>
20
- </div>
7
+ <div>
8
+ <div v-if="pull" class="co-text o-mm" fekit-pullload-head="">
9
+ <slot name="pull-head" :state="demo.store.pull" :text="pullText()" :locale="words" :pullload="demo">
10
+ <slot v-if="demo.store.pull === 0" name="pull-idle" :state="demo.store.pull" :text="pullText('idle')" :locale="words" :pullload="demo">
11
+ <div ui-flex="row cm">
12
+ <i class="pulldown icon icon-pulldown"></i>
13
+ <span>{{ pullText("idle") }}</span>
14
+ </div>
15
+ </slot>
16
+ <slot v-else-if="demo.store.pull === 1" name="pull-ready" :state="demo.store.pull" :text="pullText('ready')" :locale="words" :pullload="demo">
17
+ <div ui-flex="row cm">
18
+ <i class="pulldown icon icon-pulldown toup"></i>
19
+ <span>{{ pullText("ready") }}</span>
20
+ </div>
21
+ </slot>
22
+ <slot v-else-if="demo.store.pull === 2" name="pull-loading" :state="demo.store.pull" :text="pullText('loading')" :locale="words" :pullload="demo">
23
+ <div ui-flex="row cm">
24
+ <span ui-load="@d"></span>
25
+ <span v-if="pullText('loading')">{{ pullText("loading") }}</span>
26
+ </div>
27
+ </slot>
28
+ <slot v-else-if="demo.store.pull === 3" name="pull-finished" :state="demo.store.pull" :text="pullText('finished')" :locale="words" :pullload="demo">
29
+ <div ui-flex="row cm">
30
+ <span>{{ pullText("finished") }}</span>
31
+ </div>
32
+ </slot>
21
33
  </slot>
22
34
  </div>
23
35
  <slot></slot>
24
- <div class="fs-xs co-text o-mm my-sm" fekit-pullload-foot="" v-if="load">
25
- <slot name="load-foot" :state="demo.store.load">
36
+ <div v-if="load" class="co-text o-mm my-ms" fekit-pullload-foot="">
37
+ <slot name="load-foot" :state="demo.store.load" :text="loadText()" :locale="words" :pullload="demo">
26
38
  <transition name="fekit-pullload-fade" mode="out-in">
27
- <div v-if="demo.store.load === 2" ui-flex="row cm">
28
- <span ui-load="@d"></span>
29
- </div>
30
- <div v-else-if="demo.store.load === 3">没有更多了</div>
31
- <div v-else>&nbsp;</div>
39
+ <slot v-if="demo.store.load === 2" name="load-loading" :state="demo.store.load" :text="loadText('loading')" :locale="words" :pullload="demo">
40
+ <div ui-flex="row cm">
41
+ <span ui-load="@d"></span>
42
+ <span v-if="loadText('loading')">{{ loadText("loading") }}</span>
43
+ </div>
44
+ </slot>
45
+ <slot v-else-if="demo.store.load === 3" name="load-over" :state="demo.store.load" :text="loadText('over')" :locale="words" :pullload="demo">
46
+ <div class="fekit-pullload-over" ui-flex="row cm">
47
+ <span>{{ loadText("over") }}</span>
48
+ </div>
49
+ </slot>
50
+ <slot v-else-if="demo.store.load === 1" name="load-loaded" :state="demo.store.load" :text="loadText('loaded')" :locale="words" :pullload="demo">
51
+ <div ui-flex="row cm">
52
+ <span v-if="loadText('loaded')">{{ loadText("loaded") }}</span>
53
+ <span v-else>&nbsp;</span>
54
+ </div>
55
+ </slot>
56
+ <slot v-else name="load-idle" :state="demo.store.load" :text="loadText('idle')" :locale="words" :pullload="demo">
57
+ <div ui-flex="row cm">
58
+ <span v-if="loadText('idle')">{{ loadText("idle") }}</span>
59
+ <span v-else>&nbsp;</span>
60
+ </div>
61
+ </slot>
32
62
  </transition>
33
63
  </slot>
34
64
  </div>
@@ -36,9 +66,22 @@
36
66
  </div>
37
67
  </template>
38
68
  <script setup lang="ts">
39
- import { onMounted, onBeforeUnmount, ref } from "vue";
40
- import PullLoad, { Easing } from "@fekit/pullload";
69
+ import { computed, nextTick, onMounted, onBeforeUnmount, ref, watch } from "vue";
41
70
  const emits = defineEmits(["onpull", "onload"]);
71
+ const defaultLocale = {
72
+ pull: {
73
+ idle: "下拉刷新",
74
+ ready: "松开加载",
75
+ loading: "",
76
+ finished: "刷新完成",
77
+ },
78
+ load: {
79
+ idle: "",
80
+ loaded: "",
81
+ loading: "",
82
+ over: "没有更多了",
83
+ },
84
+ };
42
85
  const props: any = defineProps({
43
86
  pull: {
44
87
  type: Boolean,
@@ -52,47 +95,401 @@ const props: any = defineProps({
52
95
  type: Boolean,
53
96
  default: false,
54
97
  },
98
+ loadPos: {
99
+ type: [Number, String],
100
+ default: null,
101
+ },
102
+ loadPosition: {
103
+ type: [Number, String],
104
+ default: null,
105
+ },
106
+ loadOffset: {
107
+ type: [Number, String],
108
+ default: null,
109
+ },
110
+ initialLoad: {
111
+ type: [Boolean, String],
112
+ default: false,
113
+ },
114
+ locale: {
115
+ type: Object,
116
+ default: () => ({}),
117
+ },
55
118
  });
56
119
  const root: any = ref(null);
57
- const demo: any = ref(null);
58
- demo.value = new PullLoad({
59
- easing: Easing.easeOut,
60
- friction: 0.3,
61
- triggerDistance: 60,
62
- loadingDistance: 50,
63
- ...(props.pull
64
- ? {
65
- onpull: async () => {
66
- emits("onpull", demo.value);
67
- },
68
- }
69
- : {}),
70
- ...(props.load
71
- ? {
72
- onload: async () => {
73
- emits("onload", demo.value);
74
- },
75
- }
76
- : {}),
77
- });
120
+ const demo: any = ref({ store: { pull: 0, load: 0 } });
121
+ let alive = true;
122
+ let removeLoadOffsetListener = () => {};
123
+ let checkingLoad = false;
124
+ let loadPending = false;
125
+ let initialPreloadDone = false;
126
+ let pullLoadListening = false;
127
+ let removePullLoadListener = () => {};
128
+ let resizeObserver: any = null;
129
+ let pullLoadReady: Promise<any> | null = null;
130
+
131
+ const words = computed(() => ({
132
+ pull: {
133
+ ...defaultLocale.pull,
134
+ ...(props.locale?.pull || {}),
135
+ },
136
+ load: {
137
+ ...defaultLocale.load,
138
+ ...(props.locale?.load || {}),
139
+ },
140
+ }));
141
+
142
+ const pullStatusMap: any = {
143
+ 0: "idle",
144
+ 1: "ready",
145
+ 2: "loading",
146
+ 3: "finished",
147
+ };
148
+
149
+ const loadStatusMap: any = {
150
+ 0: "idle",
151
+ 1: "loaded",
152
+ 2: "loading",
153
+ 3: "over",
154
+ };
155
+
156
+ const pullText = (status = pullStatusMap[demo.value?.store?.pull] || "idle") => {
157
+ return words.value.pull?.[status] ?? "";
158
+ };
159
+
160
+ const loadText = (status = loadStatusMap[demo.value?.store?.load] || "idle") => {
161
+ return words.value.load?.[status] ?? "";
162
+ };
163
+
164
+ const numberValue = (value: any) => {
165
+ const num = parseFloat(String(value ?? "").trim());
166
+ return Number.isFinite(num) ? num : 0;
167
+ };
168
+
169
+ const hasValue = (value: any) => value !== null && value !== undefined && value !== "";
170
+
171
+ const boolValue = (value: any) => {
172
+ if (value === false || value === 0) return false;
173
+ const text = String(value ?? "").trim().toLowerCase();
174
+ return !["", "false", "0", "off", "no"].includes(text);
175
+ };
176
+
177
+ const clampRatio = (value: any) => {
178
+ const text = String(value ?? "").trim();
179
+ const ratio = text.endsWith("%") ? numberValue(text) / 100 : numberValue(text);
180
+ return Math.min(1, Math.max(0, ratio > 1 ? ratio / 100 : ratio));
181
+ };
182
+
183
+ const effectiveLoadPos = () => {
184
+ if (hasValue(props.loadPos)) return props.loadPos;
185
+ if (hasValue(props.loadPosition)) return props.loadPosition;
186
+ if (hasValue(props.loadOffset)) return null;
187
+ return 0.8;
188
+ };
189
+
190
+ const loadOffsetPx = (el: HTMLElement) => {
191
+ const text = String(props.loadOffset ?? "").trim();
192
+ const value = numberValue(text);
193
+ if (text.endsWith("%")) return Math.max(0, el.clientHeight * (value / 100));
194
+ return Math.max(0, value);
195
+ };
196
+
197
+ const isInitialLoadEnabled = () => {
198
+ return boolValue(props.initialLoad);
199
+ };
200
+
201
+ const shouldLoad = (el: HTMLElement) => {
202
+ const scrollable = el.scrollHeight - el.clientHeight;
203
+ if (scrollable <= 0) return false;
204
+ const loadPos = effectiveLoadPos();
205
+ if (hasValue(loadPos)) {
206
+ return el.scrollTop / scrollable >= clampRatio(loadPos);
207
+ }
208
+ return scrollable - el.scrollTop <= loadOffsetPx(el);
209
+ };
210
+
211
+ const shouldInitialPreload = (el: HTMLElement) => {
212
+ if (initialPreloadDone || !props.load || demo.value?.store?.load >= 2) return false;
213
+ if (!isInitialLoadEnabled()) return false;
214
+ return el.scrollHeight - el.clientHeight > 0;
215
+ };
216
+
217
+ const emitPull = async () => {
218
+ if (!props.pull) return;
219
+ emits("onpull", demo.value);
220
+ };
221
+
222
+ const emitLoad = async () => {
223
+ if (!props.load) {
224
+ demo.value?.loaded?.();
225
+ return;
226
+ }
227
+ try {
228
+ emits("onload", demo.value);
229
+ } catch (error) {
230
+ resetLoad();
231
+ throw error;
232
+ }
233
+ };
234
+
235
+ const syncPullLoadHandlers = () => {
236
+ if (!demo.value) return;
237
+ demo.value.onpull = props.pull ? emitPull : null;
238
+ demo.value.onload = props.load ? emitLoad : null;
239
+ };
240
+
241
+ const checkLoad = () => {
242
+ const el = root.value;
243
+ if (!props.load || !el || loadPending || demo.value?.store?.pull === 2 || demo.value?.store?.load >= 2) return;
244
+ if (shouldInitialPreload(el)) {
245
+ initialPreloadDone = true;
246
+ triggerLoad();
247
+ return;
248
+ }
249
+ if (shouldLoad(el)) {
250
+ triggerLoad();
251
+ }
252
+ };
253
+
254
+ const triggerLoad = () => {
255
+ if (loadPending || demo.value?.store?.load >= 2) return;
256
+ loadPending = true;
257
+ const run = () => {
258
+ if (!alive || !props.load || demo.value?.store?.load >= 2) {
259
+ loadPending = false;
260
+ return;
261
+ }
262
+ if (typeof demo.value?.isload !== "function") {
263
+ loadPending = false;
264
+ return;
265
+ }
266
+ demo.value.isload();
267
+ };
268
+ if (typeof window !== "undefined" && window.requestAnimationFrame) {
269
+ window.requestAnimationFrame(() => setTimeout(run, 0));
270
+ } else {
271
+ setTimeout(run, 0);
272
+ }
273
+ };
274
+
275
+ const requestCheckLoad = () => {
276
+ if (checkingLoad) return;
277
+ checkingLoad = true;
278
+ const run = () => {
279
+ checkingLoad = false;
280
+ checkLoad();
281
+ };
282
+ if (typeof window !== "undefined" && window.requestAnimationFrame) {
283
+ window.requestAnimationFrame(run);
284
+ } else {
285
+ setTimeout(run, 0);
286
+ }
287
+ };
288
+
289
+ const scheduleCheckLoad = async () => {
290
+ await nextTick();
291
+ if (!alive) return;
292
+ requestCheckLoad();
293
+ };
294
+
295
+ const removeLoadListener = () => {
296
+ removeLoadOffsetListener();
297
+ removeLoadOffsetListener = () => {};
298
+ };
299
+
300
+ const removePullListener = () => {
301
+ removePullLoadListener();
302
+ removePullLoadListener = () => {};
303
+ pullLoadListening = false;
304
+ };
305
+
306
+ const syncPullListener = () => {
307
+ const el = root.value;
308
+ if (!demo.value || !el) return;
309
+ if (!props.pull) {
310
+ removePullListener();
311
+ demo.value?.setcss?.(0);
312
+ if (demo.value?.store) {
313
+ demo.value.store.pull = 0;
314
+ }
315
+ return;
316
+ }
317
+ if (pullLoadListening) return;
318
+ demo.value?.listen?.(el);
319
+ removePullLoadListener = typeof demo.value?.remove === "function" ? () => demo.value.remove() : () => {};
320
+ pullLoadListening = true;
321
+ };
322
+
323
+ const syncLoadListener = () => {
324
+ removeLoadListener();
325
+ const el = root.value;
326
+ if (!props.load) {
327
+ loadPending = false;
328
+ initialPreloadDone = false;
329
+ if (demo.value?.store) {
330
+ demo.value.store.load = 0;
331
+ }
332
+ return;
333
+ }
334
+ if (!el) return;
335
+
336
+ const onChange = () => {
337
+ requestCheckLoad();
338
+ };
339
+ el.addEventListener("scroll", onChange, { passive: true });
340
+ el.addEventListener("touchmove", onChange, { passive: true });
341
+ removeLoadOffsetListener = () => {
342
+ el.removeEventListener("scroll", onChange);
343
+ el.removeEventListener("touchmove", onChange);
344
+ resizeObserver?.disconnect?.();
345
+ resizeObserver = null;
346
+ };
347
+ if (typeof ResizeObserver !== "undefined") {
348
+ resizeObserver = new ResizeObserver(onChange);
349
+ resizeObserver.observe(el);
350
+ if (el.firstElementChild) {
351
+ resizeObserver.observe(el.firstElementChild);
352
+ }
353
+ }
354
+ scheduleCheckLoad();
355
+ };
356
+
357
+ const createPullLoad = async () => {
358
+ const { default: PullLoad, Easing } = await import("@fekit/pullload");
359
+ return new PullLoad({
360
+ easing: Easing.easeOut,
361
+ friction: 0.3,
362
+ triggerDistance: 60,
363
+ loadingDistance: 50,
364
+ onpull: props.pull ? emitPull : null,
365
+ // IScrollView owns the scroll threshold, so onload is attached after listen().
366
+ onload: null,
367
+ });
368
+ };
369
+
370
+ const ensurePullLoad = async () => {
371
+ if (demo.value?.isload || demo.value?.ispull) return demo.value;
372
+ if (!pullLoadReady) {
373
+ pullLoadReady = createPullLoad()
374
+ .then((pullLoad) => {
375
+ if (!alive) {
376
+ pullLoad?.remove?.();
377
+ return null;
378
+ }
379
+ demo.value = pullLoad;
380
+ syncPullLoadHandlers();
381
+ return pullLoad;
382
+ })
383
+ .catch((error) => {
384
+ pullLoadReady = null;
385
+ throw error;
386
+ });
387
+ }
388
+ return pullLoadReady;
389
+ };
390
+
391
+ onMounted(async () => {
392
+ if (props.pull || props.load) {
393
+ await ensurePullLoad();
394
+ }
78
395
 
79
- onMounted(() => {
80
396
  if (root.value) {
81
- demo.value?.listen(root.value);
397
+ syncPullLoadHandlers();
398
+ syncPullListener();
399
+ syncLoadListener();
82
400
  if (props.pull) {
83
- demo.value?.ispull();
401
+ demo.value?.ispull?.();
84
402
  }
85
403
  }
86
404
  });
87
405
  onBeforeUnmount(() => {
88
- demo.value?.remove();
406
+ alive = false;
407
+ removePullListener();
408
+ removeLoadListener();
409
+ pullLoadReady = null;
89
410
  });
90
411
 
91
- const pullload = () => {
92
- demo.value?.ispull();
412
+ const pullload = async () => {
413
+ if (!props.pull) return;
414
+ await ensurePullLoad();
415
+ demo.value?.ispull?.();
416
+ };
417
+
418
+ const loadmore = async () => {
419
+ if (!props.load || demo.value?.store?.load >= 2) return;
420
+ await ensurePullLoad();
421
+ demo.value?.isload?.();
422
+ };
423
+
424
+ const loaded = () => {
425
+ loadPending = false;
426
+ demo.value?.loaded?.();
427
+ };
428
+
429
+ const noMore = () => {
430
+ loadPending = false;
431
+ demo.value?.isover?.();
432
+ };
433
+
434
+ const resetLoad = () => {
435
+ loadPending = false;
436
+ if (demo.value?.store) {
437
+ demo.value.store.load = 0;
438
+ }
439
+ initialPreloadDone = false;
440
+ scheduleCheckLoad();
441
+ };
442
+
443
+ const scrollToTop = () => {
444
+ if (root.value) {
445
+ root.value.scrollTop = 0;
446
+ }
447
+ };
448
+
449
+ const pulled = () => {
450
+ demo.value?.pulled?.();
93
451
  };
94
452
 
95
- defineExpose({ pullload, ex: () => demo.value });
453
+ watch(
454
+ () => props.pull,
455
+ async () => {
456
+ if (props.pull) {
457
+ await ensurePullLoad();
458
+ }
459
+ syncPullLoadHandlers();
460
+ syncPullListener();
461
+ }
462
+ );
463
+
464
+ watch(
465
+ () => props.load,
466
+ async () => {
467
+ if (props.load) {
468
+ await ensurePullLoad();
469
+ }
470
+ syncPullLoadHandlers();
471
+ syncLoadListener();
472
+ }
473
+ );
474
+
475
+ watch(
476
+ () => [props.loadPos, props.loadPosition, props.loadOffset, props.initialLoad],
477
+ () => {
478
+ initialPreloadDone = false;
479
+ scheduleCheckLoad();
480
+ }
481
+ );
482
+
483
+ watch(
484
+ () => demo.value?.store?.load,
485
+ (load) => {
486
+ if (load !== 2) {
487
+ loadPending = false;
488
+ }
489
+ }
490
+ );
491
+
492
+ defineExpose({ pullload, loadmore, loaded, noMore, resetLoad, scrollToTop, pulled, ex: () => demo.value });
96
493
  </script>
97
494
 
98
495
  <style lang="scss">
@@ -132,5 +529,16 @@ defineExpose({ pullload, ex: () => demo.value });
132
529
  transform: rotate(180deg);
133
530
  }
134
531
  }
532
+
533
+ .fekit-pullload-over {
534
+ gap: 0.75em;
535
+ &::before,
536
+ &::after {
537
+ content: "";
538
+ width: 3em;
539
+ border-top: 1px solid currentColor;
540
+ opacity: 0.35;
541
+ }
542
+ }
135
543
  }
136
544
  </style>
@@ -1,29 +1,34 @@
1
1
  <!-- 实验性插件 -->
2
2
  <template>
3
- <Teleport :to="area">
4
- <div
5
- v-if="state.view"
6
- :am-view="am"
7
- :data-key="id"
8
- :style="`${`${dark}` ? 'background-color: rgba(0, 0, 0, ' + dark + ');' : ''}${zIndex ? 'z-index:' + zIndex + ';' : ''}`"
9
- :view="state.view"
10
- class="fekit-layer"
11
- >
12
- <div :ui-flex="`col ${flex}`" :style="wrapStyle" class="fekit-layer-wrap" @animationend="anim" @click="_sys_hide">
13
- <slot :param="_tasks[id]?.params"></slot>
3
+ <div>
4
+ <Teleport :to="area">
5
+ <div
6
+ v-if="state.view"
7
+ :am-view="am"
8
+ :data-key="id"
9
+ :style="`${`${dark}` ? 'background-color: rgba(0, 0, 0, ' + dark + ');' : ''}${zIndex ? 'z-index:' + zIndex + ';' : ''}`"
10
+ :view="state.view"
11
+ class="fekit-layer"
12
+ >
13
+ <div :ui-flex="`col ${flex}`" :style="wrapStyle" class="fekit-layer-wrap" @animationend="anim" @click="_sys_hide">
14
+ <slot :param="_tasks[id]?.params"></slot>
15
+ </div>
14
16
  </div>
15
- </div>
16
- </Teleport>
17
+ </Teleport>
18
+ </div>
17
19
  </template>
18
20
  <script lang="ts" setup>
19
21
  import { onBeforeUnmount, reactive, watch } from 'vue';
20
- import { isFunction } from '@fekit/utils';
22
+ import { env, isFunction } from '@fekit/utils';
21
23
 
22
24
  // 弹层队列
23
- if (!(window as any)._FEKIT_LAYER_TASKS) {
24
- (window as any)._FEKIT_LAYER_TASKS = {};
25
- }
26
- const _tasks: any = (window as any)._FEKIT_LAYER_TASKS;
25
+ const _tasks: any = (() => {
26
+ if (!env.client) return {};
27
+ if (!(window as any)._FEKIT_LAYER_TASKS) {
28
+ (window as any)._FEKIT_LAYER_TASKS = {};
29
+ }
30
+ return (window as any)._FEKIT_LAYER_TASKS;
31
+ })();
27
32
 
28
33
  // 获取活跃的弹层
29
34
  const getActiveLayer = () => {
@@ -54,12 +59,14 @@
54
59
  wrapStyle: '',
55
60
  });
56
61
 
57
- const _area: any = document.querySelector(props.area);
58
- if (!_area) {
59
- const el = document.createElement('div');
60
- el.id = (props.area || '#fekit').substring(1);
61
- el.style.position = 'absolute';
62
- document.body.appendChild(el);
62
+ if (env.client) {
63
+ const _area: any = document.querySelector(props.area);
64
+ if (!_area) {
65
+ const el = document.createElement('div');
66
+ el.id = (props.area || '#fekit').substring(1);
67
+ el.style.position = 'absolute';
68
+ document.body.appendChild(el);
69
+ }
63
70
  }
64
71
 
65
72
  // 状态管理
@@ -71,6 +78,7 @@
71
78
  });
72
79
 
73
80
  function disableScroll() {
81
+ if (!env.client) return;
74
82
  state.top = document.documentElement.scrollTop;
75
83
  const sw = window.innerWidth - document.documentElement.clientWidth;
76
84
  state.sw = sw;
@@ -82,6 +90,7 @@
82
90
  }
83
91
 
84
92
  function enableScroll() {
93
+ if (!env.client) return;
85
94
  document.body.style.removeProperty('overflow');
86
95
  document.body.style.removeProperty('position');
87
96
  document.body.style.removeProperty('top');
@@ -1,5 +1,7 @@
1
1
  import Layer from './Layer.vue';
2
+ import { env } from '@fekit/utils';
3
+
2
4
  const LayerById = (id: any) => {
3
- return (window as any)._FEKIT_LAYER_TASKS[id];
5
+ return env.client ? (window as any)._FEKIT_LAYER_TASKS?.[id] : undefined;
4
6
  };
5
7
  export { Layer, LayerById };
@@ -217,7 +217,8 @@
217
217
  // 创建日期
218
218
  const cDate = (date: any = null) => {
219
219
  const normalized = normalizeDateInput(date);
220
- return isDateString(normalized) ? new Date(normalized) : new Date();
220
+ // iOS 兼容:Safari 不支持 "YYYY-MM-DD" 格式,需要替换为 "YYYY/MM/DD"
221
+ return isDateString(normalized) ? new Date(normalized?.replace(/-/g, '/')) : new Date();
221
222
  };
222
223
 
223
224
  // 快捷预设