@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.
- package/.prettierrc +12 -0
- package/README.md +82 -0
- package/package.json +7 -4
- package/src/components/basic/IFollowView.vue +47 -34
- package/src/components/basic/IPickerView.vue +16 -8
- package/src/components/basic/IRouterView.vue +133 -74
- package/src/components/basic/IScrollView.vue +460 -52
- package/src/components/basic/LayerView/Layer.vue +33 -24
- package/src/components/basic/LayerView/index.ts +3 -1
- package/src/components/form/DateView@v3.vue +2 -1
- package/src/components/form/Input@v3.vue +9 -6
- package/src/components/form/TextArea.vue +3 -3
- package/src/components/loader/FormLoader/FormLoader.vue +29 -4
- package/src/components/loader/LayerLoader/LayerLoader.vue +2 -1
- package/src/components/loader/LimitLoader/LimitLoader@v3.vue +3 -3
- package/src/components/loader/TableLoader/TableLoader.vue +3 -3
- package/src/components/loader/index.ts +1 -1
- package/src/components/tools/FormDraftsView.vue +15 -11
- package/src/components/tools/FormVerifyView.vue +4 -3
- package/src/components/tools/MoreTools.vue +4 -3
- package/src/components/tools/Pagination@a.vue +74 -38
- package/src/components/tools/Pagination@b.vue +2 -1
- package/src/store/frame.ts +18 -10
- package/src/utils/theme.ts +3 -0
- package/src/components/basic/follow.ts +0 -133
- package/src/components/loader/FormLoader/FormLoader@v2.vue +0 -422
- package/src/components/loader/FormLoader/NodeLoader.vue +0 -85
- package/src/components/loader/FormLoader@v1/FormLoader.vue +0 -506
- 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
|
|
8
|
-
<div class="
|
|
9
|
-
<slot name="pull-head" :state="demo.store.pull">
|
|
10
|
-
<
|
|
11
|
-
<
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
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="
|
|
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
|
-
<
|
|
28
|
-
<
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
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> </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> </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(
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
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
|
-
|
|
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
|
-
|
|
406
|
+
alive = false;
|
|
407
|
+
removePullListener();
|
|
408
|
+
removeLoadListener();
|
|
409
|
+
pullLoadReady = null;
|
|
89
410
|
});
|
|
90
411
|
|
|
91
|
-
const pullload = () => {
|
|
92
|
-
|
|
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
|
-
|
|
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
|
-
<
|
|
4
|
-
<
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
<
|
|
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
|
-
</
|
|
16
|
-
</
|
|
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
|
-
|
|
24
|
-
(
|
|
25
|
-
|
|
26
|
-
|
|
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
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
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
|
-
|
|
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
|
// 快捷预设
|