@mybricks/taro-core 0.0.1

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.
@@ -0,0 +1,2504 @@
1
+ import { useState, useRef, useMemo, createContext, useContext, useEffect } from 'react';
2
+ import { jsx } from 'react/jsx-runtime';
3
+ import { View } from '@tarojs/components';
4
+ import Taro, { useTabItemTap } from '@tarojs/taro';
5
+ import CryptoJS from 'crypto-js';
6
+
7
+ const SUBJECT_NEXT = Symbol("SUBJECT_NEXT");
8
+ const SUBJECT_VALUE = Symbol("SUBJECT_VALUE");
9
+ const SUBJECT_SUBSCRIBE = Symbol("SUBJECT_SUBSCRIBE");
10
+ const SUBJECT_UNSUBSCRIBE = Symbol("SUBJECT_UNSUBSCRIBE");
11
+ const SUBJECT_EMPTY = Symbol("SUBJECT_EMPTY");
12
+ const SUBJECT_SETVALUE = Symbol("SUBJECT_SETVALUE");
13
+ const EXE_TITLE_MAP = {
14
+ output: "输出",
15
+ input: "输入"
16
+ };
17
+
18
+ const log = (...args) => {
19
+ // console.log("[MyBricks]", ...args)
20
+ };
21
+
22
+ const logger = {
23
+ info: log,
24
+ warn: log,
25
+ error: log,
26
+ };
27
+
28
+ /** 数据流 */
29
+ class Subject {
30
+ _values = []
31
+ _observers = new Set()
32
+ _log = undefined
33
+ _empty = true;
34
+
35
+ constructor(params = {}) {
36
+ this._log = params.log;
37
+ return new Proxy(this, {
38
+ get(target, prop) {
39
+ if (prop in target) {
40
+ return target[prop];
41
+ }
42
+
43
+ const subjectNext = new SubjectNext(prop);
44
+
45
+ target[SUBJECT_SUBSCRIBE]((value, extra) => {
46
+ subjectNext[SUBJECT_NEXT](value, extra);
47
+ });
48
+
49
+ return subjectNext
50
+ }
51
+ })
52
+ }
53
+
54
+ get [SUBJECT_VALUE]() {
55
+ return this._values[0]
56
+ }
57
+
58
+ get [SUBJECT_EMPTY]() {
59
+ return this._empty;
60
+ }
61
+
62
+ [SUBJECT_SETVALUE](value) {
63
+ this._values[0] = value;
64
+ this._empty = false;
65
+ }
66
+
67
+ [SUBJECT_NEXT](value, extra) {
68
+ log(this._log, JSON.stringify(value));
69
+ this._values[0] = value;
70
+ this._empty = false;
71
+ this._observers.forEach((observer) => observer(value, extra));
72
+ }
73
+
74
+ [SUBJECT_SUBSCRIBE](observer) {
75
+ if (this._values.length) {
76
+ observer(this._values[0]);
77
+ }
78
+ this._observers.add(observer);
79
+ }
80
+
81
+ [SUBJECT_UNSUBSCRIBE](observer) {
82
+ this._observers.delete(observer);
83
+ }
84
+ }
85
+
86
+ function getValueNextByPath(params) {
87
+ const { value, path } = params;
88
+ let current = value;
89
+ for (const key of path) {
90
+ if (current === null || current === undefined) {
91
+ return undefined
92
+ }
93
+ current = current[key];
94
+ }
95
+ return current
96
+ }
97
+
98
+ class SubjectNext extends Subject {
99
+ _path = []
100
+
101
+ constructor(path) {
102
+ super();
103
+
104
+ this._path.push(path);
105
+
106
+ return new Proxy(this, {
107
+ get(target, prop) {
108
+ if (prop in target) {
109
+ return target[prop];
110
+ }
111
+
112
+ target._path.push(prop);
113
+
114
+ return target;
115
+ }
116
+ })
117
+ }
118
+
119
+ [SUBJECT_NEXT](value, extra) {
120
+ this._values[0] = value;
121
+ this._empty = false;
122
+ const nextValue = getValueNextByPath({ value, path: this._path });
123
+ this._observers.forEach((observer) => observer(nextValue, extra));
124
+ }
125
+
126
+ [SUBJECT_SUBSCRIBE](observer) {
127
+ if (this._values.length) {
128
+ observer(getValueNextByPath({ value: this._values[0], path: this._path }));
129
+ }
130
+ this._observers.add(observer);
131
+ }
132
+ }
133
+
134
+ /** 组件的输入 */
135
+ const createReactiveInputHandler = (params) => {
136
+ const { input, value, rels, title } = params;
137
+ if (value?.[SUBJECT_SUBSCRIBE]) {
138
+ value[SUBJECT_SUBSCRIBE]((value) => {
139
+ input(value, new Proxy({}, {
140
+ get(_, key) {
141
+ return (value) => {
142
+ (rels[key] ||
143
+ (rels[key] = new Subject({ log: `${EXE_TITLE_MAP["output"]} ${title} | ${key}` })))[SUBJECT_NEXT](value);
144
+ }
145
+ }
146
+ }));
147
+ });
148
+ } else {
149
+ input(value, new Proxy({},
150
+ {
151
+ get(_, key) {
152
+ return (value) => {
153
+ (rels[key] ||
154
+ (rels[key] = new Subject({ log: `${EXE_TITLE_MAP["output"]} ${title} | ${key}` })))[SUBJECT_NEXT](value);
155
+ }
156
+ }
157
+ }
158
+ ));
159
+ }
160
+
161
+ return new Proxy({},
162
+ {
163
+ get(_, key) {
164
+ return rels[key] || (rels[key] = new Subject({ log: `${EXE_TITLE_MAP["output"]} ${title} | ${key}` }))
165
+ }
166
+ }
167
+ )
168
+ };
169
+
170
+ /**
171
+ * 深度代理,支持自动路径初始化和响应式更新(鸿蒙化处理方案)
172
+ */
173
+ function deepProxy(target, onSet) {
174
+ if (target === null || typeof target !== 'object' || target.__isProxy) {
175
+ return target;
176
+ }
177
+ return new Proxy(target, {
178
+ get(obj, prop) {
179
+ if (prop === '__isProxy')
180
+ return true;
181
+ if (prop === 'toJSON')
182
+ return () => obj;
183
+ let value = obj[prop];
184
+ // 只代理已存在的对象属性,不自动创建空对象
185
+ // 避免访问不存在的属性(如 disabled)时污染原始数据
186
+ if (typeof value === 'object' && value !== null && !value.__isProxy) {
187
+ obj[prop] = deepProxy(value, onSet);
188
+ }
189
+ return obj[prop];
190
+ },
191
+ set(obj, prop, value) {
192
+ const result = Reflect.set(obj, prop, value);
193
+ if (onSet)
194
+ onSet();
195
+ return result;
196
+ }
197
+ });
198
+ }
199
+ function useModel(rawData) {
200
+ const [, forceUpdate] = useState({});
201
+ const dataRef = useRef(rawData || {});
202
+ return useMemo(() => {
203
+ return deepProxy(dataRef.current, () => forceUpdate({}));
204
+ }, []);
205
+ }
206
+ function useBindInputs(scope, id, initialHandlers) {
207
+ const handlersRef = useRef({ ...initialHandlers });
208
+ // 同步最新的 initialHandlers
209
+ if (initialHandlers) {
210
+ Object.assign(handlersRef.current, initialHandlers);
211
+ }
212
+ return useMemo(() => {
213
+ const proxy = new Proxy({}, {
214
+ get: (_target, pin) => {
215
+ return (arg, ...args) => {
216
+ if (typeof arg === 'function') {
217
+ // 组件注册回调
218
+ handlersRef.current[pin] = arg;
219
+ }
220
+ else {
221
+ // 逻辑流触发输入
222
+ const handler = handlersRef.current[pin];
223
+ if (typeof handler === 'function') {
224
+ if (pin === '_setData') {
225
+ return handler(arg, ...args);
226
+ }
227
+ // 构造 createReactiveInputHandler 需要的参数
228
+ return createReactiveInputHandler({
229
+ input: handler,
230
+ value: arg,
231
+ rels: {}, // 这里可以扩展 output 关联
232
+ title: id
233
+ });
234
+ }
235
+ }
236
+ };
237
+ }
238
+ });
239
+ // 将代理对象挂载到作用域,供外部 comRefs.current.id.pin() 调用
240
+ if (scope && scope.current) {
241
+ scope.current[id] = proxy;
242
+ }
243
+ return proxy;
244
+ }, [scope, id]);
245
+ }
246
+ function useBindEvents(props, context) {
247
+ return useMemo(() => {
248
+ const _events = {};
249
+ // 预处理已存在的事件
250
+ Object.keys(props).forEach(key => {
251
+ // 兼容:MyBricks 输出 pin 既可能是 onChange,也可能是 changeTab 这种非 on 前缀
252
+ if (typeof props[key] === 'function') {
253
+ const handler = props[key];
254
+ const wrapped = (originalValue) => {
255
+ var _a, _b;
256
+ // 鸿蒙/render-web 规范:如果是在插槽中触发事件,且存在父级协议,则自动封装元数据
257
+ // 这解决了 FormContainer 等组件识别子项的需求
258
+ // 注意:不要仅凭 parentSlot 存在就封装,否则会影响 Tabs2/changeTab 这类事件直接给 JS 计算组件传参
259
+ // 仅在父级 slot 使用 itemWrap 协议时才需要这层元数据
260
+ const value = ((_b = (_a = context === null || context === void 0 ? void 0 : context.parentSlot) === null || _a === void 0 ? void 0 : _a.params) === null || _b === void 0 ? void 0 : _b.itemWrap) ? {
261
+ id: context.id,
262
+ name: context.name,
263
+ value: originalValue
264
+ } : originalValue;
265
+ return handler(value);
266
+ };
267
+ wrapped.getConnections = () => [{ id: 'default' }];
268
+ _events[key] = wrapped;
269
+ }
270
+ });
271
+ return new Proxy(_events, {
272
+ get(target, key) {
273
+ // 对 onXXX 事件(不少组件 runtime 直接 outputs["onChange"](...))提供兜底函数,避免未连线时报错
274
+ if (typeof key === 'string' && key.startsWith('on')) {
275
+ if (target[key]) {
276
+ return target[key];
277
+ }
278
+ // 对未连接的事件返回兜底函数
279
+ const emptyFn = () => { };
280
+ emptyFn.getConnections = () => [];
281
+ return emptyFn;
282
+ }
283
+ return target[key];
284
+ }
285
+ });
286
+ }, [props, context]);
287
+ }
288
+
289
+ function useAppCreateContext(id) {
290
+ // 约定:场景级 inputs 统一挂载到 $inputs,避免与组件 runtime 的 inputs 命名冲突
291
+ // 同时可避免 `Cannot set property 'open' of undefined`
292
+ // 注册表拆分:
293
+ // - comRefs: 组件实例/inputs/outputs 注册表(可 scoped)
294
+ // - $vars/$fxs: 逻辑能力注册表(仅页面级,全作用域共享)
295
+ const comRefs = useRef(deepProxy({ $inputs: {}, $outputs: {} }));
296
+ const $vars = useRef({});
297
+ const $fxs = useRef({});
298
+ const [popupState, setPopupState] = useState({
299
+ visible: false,
300
+ name: '',
301
+ value: null,
302
+ controller: null
303
+ });
304
+ const appContext = useRef({
305
+ canvas: {
306
+ id, // 使用 data 中的 id
307
+ },
308
+ runtime: {
309
+ debug: false,
310
+ },
311
+ edit: false,
312
+ isH5: false,
313
+ isDesigner: false,
314
+ isPreview: false,
315
+ isRelease: false,
316
+ isDebug: false,
317
+ isLocal: false,
318
+ isTest: false,
319
+ tabBar: [],
320
+ useTabBar: false,
321
+ }).current;
322
+ return useMemo(() => ({
323
+ comRefs,
324
+ $vars,
325
+ $fxs,
326
+ appContext,
327
+ popupState,
328
+ setPopupState
329
+ }), [popupState]);
330
+ }
331
+
332
+ const safeSetByPath = (params) => {
333
+ const { data, path, value } = params;
334
+ const nextIndex = path.length - 1;
335
+ let current = data;
336
+ let errorFlag = false;
337
+ for (let i = 0; i < nextIndex; i++) {
338
+ try {
339
+ current = current[path[i]];
340
+ } catch (error) {
341
+ errorFlag = true;
342
+ break;
343
+ }
344
+ }
345
+
346
+ if (!errorFlag) {
347
+ current[path[nextIndex]] = value;
348
+ }
349
+ };
350
+
351
+ const safeGetByPath = (params) => {
352
+ const { data, path } = params;
353
+ let current = data;
354
+ let errorFlag = false;
355
+ for (let i = 0; i < path.length; i++) {
356
+ try {
357
+ current = current[path[i]];
358
+ } catch (error) {
359
+ errorFlag = true;
360
+ break;
361
+ }
362
+ }
363
+
364
+ if (!errorFlag) {
365
+ return current;
366
+ }
367
+
368
+ return undefined;
369
+ };
370
+
371
+ /** utils */
372
+ /**
373
+ * 判断是否js多输入
374
+ */
375
+ const validateJsMultipleInputs = (input) => {
376
+ return input.match(/\./); // input.xxx 为多输入模式
377
+ };
378
+
379
+ // JS
380
+ const createJSHandle = (fn, options) => {
381
+ let controller;
382
+
383
+ const { props, appContext } = options;
384
+
385
+ const inputs = new Proxy({}, {
386
+ getOwnPropertyDescriptor() {
387
+ return {
388
+ enumerable: true,
389
+ configurable: true,
390
+ }
391
+ },
392
+ ownKeys() {
393
+ return props.inputs
394
+ },
395
+ get() {
396
+ return (input) => {
397
+ // 约定只有一个输入
398
+ controller = input;
399
+ }
400
+ }
401
+ });
402
+
403
+ const rels = {};
404
+
405
+ const outputs = new Proxy({}, {
406
+ getOwnPropertyDescriptor() {
407
+ return {
408
+ enumerable: true,
409
+ configurable: true,
410
+ }
411
+ },
412
+ ownKeys() {
413
+ return props.outputs
414
+ },
415
+ get(_, key) {
416
+ return (value) => {
417
+ (rels[key] ||
418
+ (rels[key] = new Subject({ log: `${EXE_TITLE_MAP["output"]} ${props.title} | ${key}` })))[SUBJECT_NEXT](value);
419
+ }
420
+ }
421
+ });
422
+
423
+ fn({
424
+ data: props.data,
425
+ inputs,
426
+ outputs,
427
+ logger,
428
+ env: appContext?.env
429
+ });
430
+
431
+ const isJsMultipleInputs = props.inputs[0]
432
+ ? validateJsMultipleInputs(props.inputs[0])
433
+ : false;
434
+
435
+ const exeOutputs = new Proxy(
436
+ {},
437
+ {
438
+ get(_, key) {
439
+ return rels[key] || (rels[key] = new Subject({ log: `${EXE_TITLE_MAP["output"]} ${props.title} | ${key}` }))
440
+ },
441
+ },
442
+ );
443
+
444
+ const exe = (...args) => {
445
+ if (args.length) {
446
+ // 调用输入
447
+ if (isJsMultipleInputs) {
448
+ // 多输入模式
449
+ const length = args.length;
450
+ let valueAry = {};
451
+ args.forEach((value, index) => {
452
+ if (value?.[SUBJECT_SUBSCRIBE]) {
453
+ value[SUBJECT_SUBSCRIBE]((value) => {
454
+ log(`${EXE_TITLE_MAP["input"]} ${props.title} | ${props.inputs[index]}`, JSON.stringify(value));
455
+ valueAry[props.inputs[index]] = value;
456
+ if (Object.keys(valueAry).length === length) {
457
+ createReactiveInputHandler({
458
+ input: controller,
459
+ value: valueAry,
460
+ rels,
461
+ title: props.title
462
+ });
463
+ // 触发输入后清除
464
+ valueAry = {};
465
+ }
466
+ });
467
+ } else {
468
+ log(`${EXE_TITLE_MAP["input"]} ${props.title} | ${props.inputs[index]}`, JSON.stringify(value));
469
+ valueAry[props.inputs[index]] = value;
470
+
471
+ if (Object.keys(valueAry).length === length) {
472
+ createReactiveInputHandler({
473
+ input: controller,
474
+ value: valueAry,
475
+ rels,
476
+ title: props.title
477
+ });
478
+ // 触发输入后清除
479
+ valueAry = {};
480
+ }
481
+ }
482
+ });
483
+ } else {
484
+ // 非多输入
485
+ const value = args[0];
486
+ if (value?.[SUBJECT_SUBSCRIBE]) {
487
+ value[SUBJECT_SUBSCRIBE]((value) => {
488
+ log(`${EXE_TITLE_MAP["input"]} ${props.title} | ${props.inputs[0]}`, JSON.stringify(value));
489
+ createReactiveInputHandler({
490
+ input: controller,
491
+ value,
492
+ rels,
493
+ title: props.title
494
+ });
495
+ });
496
+ } else {
497
+ log(`${EXE_TITLE_MAP["input"]} ${props.title} | ${props.inputs[0]}`, JSON.stringify(value));
498
+ createReactiveInputHandler({
499
+ input: controller,
500
+ value,
501
+ rels,
502
+ title: props.title
503
+ });
504
+ }
505
+ }
506
+ }
507
+
508
+ return exeOutputs;
509
+ };
510
+
511
+ return exe;
512
+ };
513
+
514
+ /** 创建变量 */
515
+ const createVariable = (...args) => {
516
+ const hasDefaultValue = args.length > 0;
517
+ const initValue = args[0];
518
+ const value = new Subject();
519
+ if (hasDefaultValue) {
520
+ value[SUBJECT_NEXT](initValue);
521
+ }
522
+ const ref = {
523
+ value,
524
+ callBacksMap: new Map(),
525
+
526
+ // 注册change后,设置一个subject,用于触发change
527
+ changeValues: new Set(),
528
+ // change到上述subject的映射
529
+ changeValuesMap: new Map(),
530
+ };
531
+
532
+ const variable = {
533
+ /** 读取 */
534
+ get(value, path) {
535
+ const nextValue = new Subject();
536
+ const next = () => {
537
+ nextValue[SUBJECT_NEXT](path ? safeGetByPath({
538
+ data: ref.value[SUBJECT_VALUE],
539
+ path: path.split(".")
540
+ }) : ref.value[SUBJECT_VALUE]);
541
+ };
542
+ if (value?.[SUBJECT_SUBSCRIBE]) {
543
+ value[SUBJECT_SUBSCRIBE](() => {
544
+ next();
545
+ });
546
+ } else {
547
+ next();
548
+ }
549
+ return nextValue
550
+ },
551
+ /** 赋值 */
552
+ set(value, path) {
553
+ const nextValue = new Subject();
554
+ const next = (value, extra) => {
555
+ if (path) {
556
+ const isEmpty = ref.value[SUBJECT_EMPTY];
557
+ if (isEmpty) {
558
+ ref.value[SUBJECT_SETVALUE]({});
559
+ }
560
+ safeSetByPath({
561
+ data: ref.value[SUBJECT_VALUE],
562
+ path: path.split("."),
563
+ value: value
564
+ });
565
+
566
+ value = ref.value[SUBJECT_VALUE];
567
+ }
568
+
569
+ ref.value[SUBJECT_NEXT](value, extra);
570
+ ref.changeValues.forEach((changeValue) => {
571
+ changeValue[SUBJECT_NEXT](value, extra);
572
+ });
573
+ nextValue[SUBJECT_NEXT](value, extra);
574
+ };
575
+ if (value?.[SUBJECT_SUBSCRIBE]) {
576
+ value[SUBJECT_SUBSCRIBE]((value, extra) => {
577
+ next(value, extra);
578
+ });
579
+ } else {
580
+ next(value);
581
+ }
582
+ return nextValue
583
+ },
584
+ /** 重置 */
585
+ reset(value) {
586
+ const nextValue = new Subject();
587
+ const next = () => {
588
+ ref.value[SUBJECT_NEXT](initValue);
589
+ ref.changeValues.forEach((changeValue) => {
590
+ changeValue[SUBJECT_NEXT](initValue);
591
+ });
592
+ nextValue[SUBJECT_NEXT](initValue);
593
+ };
594
+ if (value?.[SUBJECT_SUBSCRIBE]) {
595
+ value[SUBJECT_SUBSCRIBE](() => {
596
+ next();
597
+ });
598
+ } else {
599
+ next();
600
+ }
601
+ return nextValue
602
+ },
603
+ /** 值变更监听 */
604
+ changed() {
605
+ const changeValue = new Subject();
606
+ ref.changeValues.add(changeValue);
607
+
608
+ const result = {
609
+ destroy() {
610
+ ref.changeValues.delete(changeValue);
611
+ },
612
+ [SUBJECT_SUBSCRIBE](next) {
613
+ changeValue[SUBJECT_SUBSCRIBE](next);
614
+ }
615
+ };
616
+
617
+ return result
618
+ },
619
+ bind(callBack) {
620
+ if (!ref.callBacksMap.has("")) {
621
+ ref.callBacksMap.set("", new Set());
622
+ }
623
+ const callBacks = ref.callBacksMap.get("");
624
+ callBacks.add(callBack);
625
+ // 默认触发一次
626
+ callBack(ref.value[SUBJECT_VALUE]);
627
+ },
628
+ ext() {
629
+ return {
630
+ setValue(value) {
631
+ variable.set(value);
632
+ },
633
+ getValue() {
634
+ return ref.value[SUBJECT_VALUE]
635
+ }
636
+ }
637
+ },
638
+ registerChange(change) {
639
+ const changeValue = new Subject();
640
+ // 默认执行,进行初始化动作
641
+ change(changeValue);
642
+
643
+ ref.changeValues.add(changeValue);
644
+ ref.changeValuesMap.set(change, changeValue);
645
+
646
+ if (!ref.value[SUBJECT_EMPTY]) {
647
+ // 有值就默认执行
648
+ changeValue[SUBJECT_NEXT](ref.value[SUBJECT_VALUE]);
649
+ }
650
+ },
651
+ unregisterChange(change) {
652
+ const changeValue = ref.changeValuesMap.get(change);
653
+ ref.changeValues.delete(changeValue);
654
+ ref.changeValuesMap.delete(change);
655
+ },
656
+ // 内置的赋值操作
657
+ setTrue() {
658
+ return variable.set(true)
659
+ },
660
+ setFalse() {
661
+ return variable.set(false)
662
+ },
663
+ setAryAdd(value) {
664
+ const nextValue = new Subject();
665
+
666
+ if (Array.isArray(ref.value[SUBJECT_VALUE])) {
667
+ const next = (value) => {
668
+ const arrayValue = ref.value[SUBJECT_VALUE].concat(value);
669
+ ref.value[SUBJECT_NEXT](arrayValue);
670
+ ref.changeValues.forEach((changeValue) => {
671
+ changeValue[SUBJECT_NEXT](value);
672
+ });
673
+ nextValue[SUBJECT_NEXT](arrayValue);
674
+ };
675
+ if (value?.[SUBJECT_SUBSCRIBE]) {
676
+ value[SUBJECT_SUBSCRIBE]((value) => {
677
+ next(value);
678
+ });
679
+ } else {
680
+ next(value);
681
+ }
682
+ }
683
+
684
+ return nextValue
685
+ }
686
+ };
687
+
688
+ return new Proxy({}, {
689
+ get(_, key) {
690
+ return variable[key]
691
+ }
692
+ })
693
+ };
694
+
695
+ /** 合并数据流 */
696
+ const merge = (...subjects) => {
697
+ const merge = new Subject();
698
+
699
+ subjects.forEach((subject) => {
700
+ if (subject?.[SUBJECT_SUBSCRIBE]) {
701
+ subject[SUBJECT_SUBSCRIBE]((value) => {
702
+ merge[SUBJECT_NEXT](value);
703
+ });
704
+ } else {
705
+ merge[SUBJECT_NEXT](subject);
706
+ }
707
+ });
708
+
709
+ return merge
710
+ };
711
+
712
+ // 场景打开、输出
713
+ const pageController = () => {
714
+ return new Proxy({
715
+ commit: new Subject(),
716
+ cancel: new Subject(),
717
+ apply: new Subject(),
718
+ close: new Subject(),
719
+ }, {
720
+ get(target, key) {
721
+ return target[key]
722
+ }
723
+ })
724
+ };
725
+
726
+ class Page {
727
+ appRouter
728
+
729
+ constructor(appRouter) {
730
+ this.appRouter = appRouter;
731
+ }
732
+
733
+ /** 获取当前页面入参 */
734
+ getParams(name) {
735
+ const params = this.appRouter.getParams(name);
736
+ const subject = new Subject();
737
+ subject[SUBJECT_NEXT](params?.value);
738
+ return subject
739
+ }
740
+
741
+ /** 打开 */
742
+ open(name, value) {
743
+ const controller = pageController();
744
+
745
+ if (value?.[SUBJECT_SUBSCRIBE]) {
746
+ value[SUBJECT_SUBSCRIBE]((value) => {
747
+ this.appRouter.push(name, { value, controller });
748
+ });
749
+ } else {
750
+ this.appRouter.push(name, { value, controller });
751
+ }
752
+
753
+ return controller
754
+ }
755
+
756
+ /** 打开 */
757
+ replace(name, value) {
758
+ const controller = pageController();
759
+
760
+ if (value?.[SUBJECT_SUBSCRIBE]) {
761
+ value[SUBJECT_SUBSCRIBE]((value) => {
762
+ this.appRouter.replace(name, { value, controller });
763
+ });
764
+ } else {
765
+ this.appRouter.replace(name, { value, controller });
766
+ }
767
+
768
+ return controller
769
+ }
770
+
771
+ /** 确定 */
772
+ commit(name, value) {
773
+ const params = this.appRouter.getParams(name);
774
+
775
+ if (value?.[SUBJECT_SUBSCRIBE]) {
776
+ value[SUBJECT_SUBSCRIBE]((value) => {
777
+ this.appRouter.pop();
778
+ setTimeout(() => {
779
+ params.controller.commit[SUBJECT_NEXT](value);
780
+ }, 100);
781
+ });
782
+ } else {
783
+ this.appRouter.pop();
784
+ setTimeout(() => {
785
+ params.controller.commit[SUBJECT_NEXT](value);
786
+ }, 100);
787
+ }
788
+ }
789
+
790
+ /** 取消 */
791
+ cancel(name, value) {
792
+ const params = this.appRouter.getParams(name);
793
+ if (value?.[SUBJECT_SUBSCRIBE]) {
794
+ value[SUBJECT_SUBSCRIBE]((value) => {
795
+ this.appRouter.pop();
796
+ setTimeout(() => {
797
+ params.controller.cancel[SUBJECT_NEXT](value);
798
+ }, 100);
799
+ });
800
+ } else {
801
+ this.appRouter.pop();
802
+ setTimeout(() => {
803
+ params.controller.cancel[SUBJECT_NEXT](value);
804
+ }, 100);
805
+ }
806
+ }
807
+
808
+ /** 应用,不关闭 */
809
+ apply(name, value) {
810
+ const params = this.appRouter.getParams(name);
811
+ if (value?.[SUBJECT_SUBSCRIBE]) {
812
+ value[SUBJECT_SUBSCRIBE]((value) => {
813
+ params.controller.apply[SUBJECT_NEXT](value);
814
+ });
815
+ } else {
816
+ params.controller.apply[SUBJECT_NEXT](value);
817
+ }
818
+ }
819
+
820
+ /** 关闭 */
821
+ close(name, value) {
822
+ const params = this.appRouter.getParams(name);
823
+ if (value?.[SUBJECT_SUBSCRIBE]) {
824
+ value[SUBJECT_SUBSCRIBE]((value) => {
825
+ this.appRouter.pop();
826
+ setTimeout(() => {
827
+ params.controller.close[SUBJECT_NEXT](value);
828
+ }, 100);
829
+ });
830
+ } else {
831
+ this.appRouter.pop();
832
+ setTimeout(() => {
833
+ params.controller.close[SUBJECT_NEXT](value);
834
+ }, 100);
835
+ }
836
+ }
837
+ }
838
+
839
+ /** 创建fx */
840
+ const createFx = (fx) => {
841
+ return (value, ...args) => {
842
+ const outputs = {};
843
+
844
+ const proxy = new Proxy({}, {
845
+ get(_, key) {
846
+ return outputs[key] || (outputs[key] = new Subject())
847
+ }
848
+ });
849
+
850
+ const next = (value) => {
851
+ const res = fx(value, ...args);
852
+ if (res) {
853
+ Object.entries(res).forEach(([key, value]) => {
854
+ if (!outputs[key]) {
855
+ outputs[key] = new Subject();
856
+ }
857
+ if (value?.[SUBJECT_SUBSCRIBE]) {
858
+ value[SUBJECT_SUBSCRIBE]((value) => {
859
+ outputs[key][SUBJECT_NEXT](value);
860
+ });
861
+ } else {
862
+ outputs[key][SUBJECT_NEXT](value);
863
+ }
864
+ });
865
+ }
866
+ };
867
+
868
+ if (value?.[SUBJECT_SUBSCRIBE]) {
869
+ value[SUBJECT_SUBSCRIBE]((value) => {
870
+ next(value);
871
+ });
872
+ } else {
873
+ next(value);
874
+ }
875
+
876
+ return proxy
877
+ }
878
+ };
879
+
880
+ // @ts-ignore 运行时由宿主项目提供 @tarojs/taro
881
+ /**
882
+ * Taro 路由驱动 (纯粹版)
883
+ * 只负责处理真正的 Taro 页面跳转
884
+ */
885
+ class TaroRouter {
886
+ constructor() {
887
+ this.paramsBackup = {};
888
+ }
889
+ getParams(name) {
890
+ var _a;
891
+ const instance = Taro.getCurrentInstance();
892
+ let params = ((_a = instance.router) === null || _a === void 0 ? void 0 : _a.params) || {};
893
+ // 备份参数,解决某些生命周期下 Taro 获取不到 params 的问题
894
+ if (!params.data && this.paramsBackup[name]) {
895
+ params = { data: this.paramsBackup[name] };
896
+ }
897
+ return { value: params };
898
+ }
899
+ push(name, { value }) {
900
+ const url = `/pages/${name}/index`;
901
+ const dataStr = value ? encodeURIComponent(JSON.stringify(value)) : '';
902
+ if (dataStr) {
903
+ this.paramsBackup[name] = dataStr;
904
+ }
905
+ Taro.navigateTo({
906
+ url: `${url}${dataStr ? `?data=${dataStr}` : ''}`
907
+ });
908
+ }
909
+ replace(name, { value }) {
910
+ const url = `/pages/${name}/index`;
911
+ const dataStr = value ? encodeURIComponent(JSON.stringify(value)) : '';
912
+ if (dataStr) {
913
+ this.paramsBackup[name] = dataStr;
914
+ }
915
+ Taro.redirectTo({
916
+ url: `${url}${dataStr ? `?data=${dataStr}` : ''}`
917
+ });
918
+ }
919
+ pop() {
920
+ Taro.navigateBack();
921
+ }
922
+ }
923
+ const router = new TaroRouter();
924
+ const pageRouter = new Page(router);
925
+
926
+ const ComContext = createContext(undefined);
927
+ const SlotContext = createContext(null);
928
+ function useAppContext() {
929
+ const context = useContext(ComContext);
930
+ if (!context) {
931
+ throw new Error('useAppContext must be used within a ComContext.Provider');
932
+ }
933
+ return context;
934
+ }
935
+ function useParentSlot() {
936
+ return useContext(SlotContext);
937
+ }
938
+ const SlotProvider = SlotContext.Provider;
939
+
940
+ function SlotParamsBridge(props) {
941
+ var _a, _b, _c;
942
+ const parentSlot = useParentSlot();
943
+ const mergedParams = ((_a = props.params) === null || _a === void 0 ? void 0 : _a.inputValues) === undefined && ((_b = parentSlot === null || parentSlot === void 0 ? void 0 : parentSlot.params) === null || _b === void 0 ? void 0 : _b.inputValues)
944
+ ? { ...(props.params || {}), inputValues: parentSlot.params.inputValues }
945
+ : props.params;
946
+ const SlotComp = props.render;
947
+ const content = SlotComp ? jsx(SlotComp, { ...(mergedParams || {}) }) : (_c = props.children) !== null && _c !== void 0 ? _c : null;
948
+ return jsx(SlotProvider, { value: { ...props.state, params: mergedParams }, children: content });
949
+ }
950
+ function createChannelProxy(title) {
951
+ const handlersMap = {};
952
+ return new Proxy({}, {
953
+ get: (_t, pin) => {
954
+ return (arg) => {
955
+ if (typeof arg === "function") {
956
+ handlersMap[pin] = arg;
957
+ return;
958
+ }
959
+ const handler = handlersMap[pin];
960
+ if (typeof handler === "function") {
961
+ return createReactiveInputHandler({
962
+ input: handler,
963
+ value: arg,
964
+ rels: {},
965
+ title,
966
+ });
967
+ }
968
+ };
969
+ },
970
+ });
971
+ }
972
+ /**
973
+ * 参考鸿蒙的 createSlotsIO:
974
+ * - 确保每个 slot 都具备 inputs / outputs / _inputs 三套通道,避免 runtime 访问时报 undefined
975
+ * - render 时通过 SlotProvider 注入 parentSlot(slot 内子组件可 useParentSlot 获取)
976
+ */
977
+ function useEnhancedSlots(rawSlots, id) {
978
+ const slotStoreRef = useRef({});
979
+ return useMemo(() => {
980
+ if (!rawSlots)
981
+ return {};
982
+ const nextSlots = {};
983
+ Object.entries(rawSlots).forEach(([slotKey, slotDef]) => {
984
+ const state = slotStoreRef.current[slotKey] ||
985
+ (slotStoreRef.current[slotKey] = {
986
+ inputs: createChannelProxy(`${id}.${slotKey}.inputs`),
987
+ outputs: createChannelProxy(`${id}.${slotKey}.outputs`),
988
+ _inputs: createChannelProxy(`${id}.${slotKey}._inputs`),
989
+ _scopedComRefs: {},
990
+ _render: undefined,
991
+ render: (params) => {
992
+ var _a, _b, _c, _d, _e;
993
+ var _f;
994
+ const r = state._render;
995
+ // 只有存在 key 或 index 时才认为是“多实例作用域插槽”,需要实例隔离
996
+ const rawScope = (_c = (_a = params === null || params === void 0 ? void 0 : params.key) !== null && _a !== void 0 ? _a : (_b = params === null || params === void 0 ? void 0 : params.inputValues) === null || _b === void 0 ? void 0 : _b.index) !== null && _c !== void 0 ? _c : (_e = (_d = params === null || params === void 0 ? void 0 : params.inputValues) === null || _d === void 0 ? void 0 : _d.itemData) === null || _e === void 0 ? void 0 : _e.id;
997
+ if (rawScope === undefined || rawScope === null) {
998
+ return (jsx(SlotParamsBridge, { state: state, params: params, render: r }));
999
+ }
1000
+ const scopeId = `${id}.${slotKey}::${String(rawScope)}`;
1001
+ const scopedComRefs = ((_f = state._scopedComRefs)[scopeId] || (_f[scopeId] = { current: { $inputs: {}, $outputs: {} } }));
1002
+ return (jsx(SlotProvider, { value: { ...state, params }, children: jsx(ScopedComContextProvider, { comRefs: scopedComRefs, scopeId: scopeId, children: jsx(SlotParamsBridge, { state: state, params: params, render: r }) }) }));
1003
+ },
1004
+ });
1005
+ state._render = slotDef === null || slotDef === void 0 ? void 0 : slotDef.render;
1006
+ nextSlots[slotKey] = {
1007
+ ...(slotDef || {}),
1008
+ render: state.render,
1009
+ inputs: state.inputs,
1010
+ outputs: state.outputs,
1011
+ _inputs: state._inputs,
1012
+ };
1013
+ });
1014
+ return nextSlots;
1015
+ }, [rawSlots, id]);
1016
+ }
1017
+ function ScopedComContextProvider(props) {
1018
+ const parent = useAppContext();
1019
+ const value = useMemo(() => {
1020
+ // $outputs 与 $inputs 一样:在 scoped 下应当隔离(由 scopedComRefs.current.$outputs 提供)
1021
+ // 如果没有显式传 comRefs,则沿用父级的,但依然带上新的 scopeId
1022
+ return {
1023
+ ...parent,
1024
+ comRefs: props.comRefs || parent.comRefs,
1025
+ $scopeId: props.scopeId,
1026
+ };
1027
+ }, [parent, props.comRefs, props.scopeId]);
1028
+ return jsx(ComContext.Provider, { value: value, children: props.children });
1029
+ }
1030
+ /** parentSlot 解析:props 优先,其次用 SlotProvider 注入的 context */
1031
+ function useResolvedParentSlot(parentSlotProp) {
1032
+ const parentSlotFromCtx = useParentSlot();
1033
+ return parentSlotProp !== null && parentSlotProp !== void 0 ? parentSlotProp : parentSlotFromCtx;
1034
+ }
1035
+
1036
+ const WithCom = (props) => {
1037
+ var _a, _b;
1038
+ const { component: Component, id = '', data, className, style, ...rest } = props;
1039
+ const { comRefs, appContext } = useAppContext();
1040
+ const env = appContext; //TODO: 需要根据实际情况修改
1041
+ const isPopup = Component.isPopup;
1042
+ const [show, setShow] = useState(true);
1043
+ const [dynamicStyle, setDynamicStyle] = useState({});
1044
+ //数据模型
1045
+ const _data = useModel(data || {});
1046
+ // 内置通用能力
1047
+ const handlers = {
1048
+ _setStyle: (style) => {
1049
+ setDynamicStyle((prev) => ({ ...prev, ...style }));
1050
+ },
1051
+ _setData: (path, value) => {
1052
+ const paths = path.split('.');
1053
+ let current = _data;
1054
+ for (let i = 0; i < paths.length - 1; i++) {
1055
+ if (!current[paths[i]])
1056
+ current[paths[i]] = {};
1057
+ current = current[paths[i]];
1058
+ }
1059
+ current[paths[paths.length - 1]] = value;
1060
+ }
1061
+ };
1062
+ if (!isPopup) {
1063
+ Object.assign(handlers, {
1064
+ show: () => setShow(true),
1065
+ hide: () => setShow(false),
1066
+ showOrHide: () => setShow((prev) => !prev),
1067
+ });
1068
+ }
1069
+ // 绑定输入,传入初始 handlers
1070
+ const inputProxy = useBindInputs(comRefs, id, handlers);
1071
+ const { slots: rawSlots, parentSlot: parentSlotProp, ...restProps } = rest;
1072
+ const parentSlot = useResolvedParentSlot(parentSlotProp);
1073
+ // 绑定事件,带上上下文(用于事件流自动封装 id/name)
1074
+ const eventProxy = useBindEvents(restProps, {
1075
+ id,
1076
+ name: props.name || id,
1077
+ parentSlot
1078
+ });
1079
+ // 注册 outputs 到注册表(按组件 id)
1080
+ if ((_a = comRefs === null || comRefs === void 0 ? void 0 : comRefs.current) === null || _a === void 0 ? void 0 : _a.$outputs) {
1081
+ comRefs.current.$outputs[id] = eventProxy;
1082
+ }
1083
+ // 鸿蒙规范:确保 comRefs 中挂载的是最新的 inputProxy
1084
+ comRefs.current[id] = inputProxy;
1085
+ const enhancedSlots = useEnhancedSlots(rawSlots, id);
1086
+ const jsx$1 = (jsx(Component, { ...restProps, inputs: inputProxy, outputs: eventProxy, slots: enhancedSlots, parentSlot: parentSlot, data: _data, env: env, id: id, style: style }));
1087
+ // 鸿蒙化处理:支持 itemWrap 协议
1088
+ if ((_b = parentSlot === null || parentSlot === void 0 ? void 0 : parentSlot.params) === null || _b === void 0 ? void 0 : _b.itemWrap) {
1089
+ return parentSlot.params.itemWrap({
1090
+ id,
1091
+ name: props.name || id,
1092
+ jsx: jsx$1,
1093
+ def: Component.def,
1094
+ inputs: inputProxy,
1095
+ outputs: eventProxy,
1096
+ style
1097
+ });
1098
+ }
1099
+ return (show || isPopup ? (jsx(View, { className: className, style: { ...style, ...dynamicStyle }, children: jsx$1 })) : null);
1100
+ };
1101
+ const WithWrapper = (id, Component) => {
1102
+ return function WrappedComponent(props) {
1103
+ const contextStore = useAppCreateContext(id);
1104
+ const { setPopupState } = contextStore;
1105
+ const isPopup = Component.isPopup;
1106
+ // 通过发布订阅模式解耦弹窗状态变化
1107
+ useEffect(() => {
1108
+ return subscribePopupRouter((state) => setPopupState(state));
1109
+ }, [setPopupState]);
1110
+ // 点击 TabBar 时自动关闭弹窗(自定义 TabBar 或原生 TabBar 点击均会触发)
1111
+ useTabItemTap(() => {
1112
+ if (isPopup)
1113
+ return;
1114
+ closeActivePopupRouter();
1115
+ });
1116
+ return (jsx(ComContext.Provider, { value: contextStore, children: jsx(Component, { ...props }) }));
1117
+ };
1118
+ };
1119
+
1120
+ const PopupRenderer = ({ popupMap }) => {
1121
+ const { popupState } = useAppContext();
1122
+ const ActivePopup = popupState.visible && popupMap[popupState.name]
1123
+ ? popupMap[popupState.name]
1124
+ : null;
1125
+ if (!ActivePopup)
1126
+ return jsx(View, {});
1127
+ return (jsx(View, { className: "global-popup-container", style: {
1128
+ position: 'fixed',
1129
+ top: 0,
1130
+ left: 0,
1131
+ right: 0,
1132
+ bottom: 0,
1133
+ zIndex: 999999,
1134
+ pointerEvents: 'auto',
1135
+ }, children: jsx(View, { style: { width: '100%', height: '100%' }, children: jsx(ActivePopup, {}) }) }));
1136
+ };
1137
+
1138
+ /**
1139
+ * 弹窗状态管理(解耦版)
1140
+ * 弹窗在 Taro 中被视为组件,不走路由栈
1141
+ */
1142
+ class PopupStore {
1143
+ constructor() {
1144
+ this.activePopup = null;
1145
+ this.listeners = new Set();
1146
+ }
1147
+ /** 订阅弹窗状态变化 */
1148
+ subscribe(listener) {
1149
+ this.listeners.add(listener);
1150
+ // 返回取消订阅函数
1151
+ return () => {
1152
+ this.listeners.delete(listener);
1153
+ };
1154
+ }
1155
+ notify() {
1156
+ this.listeners.forEach((l) => l(this.activePopup || {
1157
+ visible: false,
1158
+ name: '',
1159
+ value: null,
1160
+ controller: null,
1161
+ }));
1162
+ }
1163
+ /** 获取弹窗参数 */
1164
+ getParams(name) {
1165
+ if (this.activePopup && this.activePopup.name === name) {
1166
+ return {
1167
+ value: this.activePopup.value,
1168
+ controller: this.activePopup.controller,
1169
+ };
1170
+ }
1171
+ return { value: null };
1172
+ }
1173
+ /** 获取当前激活的弹窗名称 */
1174
+ getActiveName() {
1175
+ var _a;
1176
+ return (_a = this.activePopup) === null || _a === void 0 ? void 0 : _a.name;
1177
+ }
1178
+ /** 打开弹窗 */
1179
+ push(name, { value, controller }) {
1180
+ this.activePopup = { visible: true, name, value, controller };
1181
+ this.notify();
1182
+ }
1183
+ /** 行为同 push */
1184
+ replace(name, params) {
1185
+ this.push(name, params);
1186
+ }
1187
+ /** 关闭弹窗 */
1188
+ pop() {
1189
+ this.activePopup = null;
1190
+ this.notify();
1191
+ }
1192
+ }
1193
+ const popupStore = new PopupStore();
1194
+ /**
1195
+ * 订阅弹窗状态变化(统一入口,避免外部依赖内部实现细节)
1196
+ */
1197
+ const subscribePopupRouter = (listener) => {
1198
+ return popupStore.subscribe(listener);
1199
+ };
1200
+ /** 弹窗控制器(命名与文件名保持一致) */
1201
+ const popupRouter = new Page(popupStore);
1202
+ /**
1203
+ * 关闭当前激活的弹窗(用于 TabBar 点击等场景)
1204
+ * 不需要知道弹窗 id
1205
+ */
1206
+ const closeActivePopupRouter = () => {
1207
+ const name = popupStore.getActiveName();
1208
+ if (!name)
1209
+ return;
1210
+ // 走 Page.close,保证 close/commit/cancel 等控制器语义保持一致
1211
+ popupRouter.close(name);
1212
+ };
1213
+
1214
+ var _ShowToast = (context) => {
1215
+ var _a;
1216
+ const data = context.data;
1217
+ const inputs = context.inputs;
1218
+ const outputs = context.outputs;
1219
+ (_a = inputs.showToast) === null || _a === void 0 ? void 0 : _a.call(inputs, (val) => {
1220
+ try {
1221
+ // 构建 Toast 配置
1222
+ const toastConfig = {
1223
+ title: typeof val === 'string' ? val : (val === null || val === void 0 ? void 0 : val.title) || data.title || '',
1224
+ duration: Number(typeof val === 'object' && (val === null || val === void 0 ? void 0 : val.duration) ? val.duration : data.duration || 1000),
1225
+ mask: typeof val === 'object' && (val === null || val === void 0 ? void 0 : val.mask) !== undefined ? val.mask : data.mask || false,
1226
+ };
1227
+ // 图标配置
1228
+ if (typeof val === 'object' && (val === null || val === void 0 ? void 0 : val.icon)) {
1229
+ toastConfig.icon = val.icon;
1230
+ }
1231
+ else if (data.icon) {
1232
+ toastConfig.icon = data.icon;
1233
+ }
1234
+ // 图片配置
1235
+ if (typeof val === 'object' && (val === null || val === void 0 ? void 0 : val.image)) {
1236
+ toastConfig.image = val.image;
1237
+ }
1238
+ else if (data.image) {
1239
+ toastConfig.image = data.image;
1240
+ }
1241
+ Taro.showToast(toastConfig);
1242
+ // 处理输出回调
1243
+ const triggerOutput = () => outputs.afterShowToast(val);
1244
+ if (data.asynchronous) {
1245
+ setTimeout(triggerOutput, toastConfig.duration);
1246
+ }
1247
+ else {
1248
+ triggerOutput();
1249
+ }
1250
+ }
1251
+ catch (error) {
1252
+ console.error('显示 Toast 失败:', error);
1253
+ }
1254
+ });
1255
+ };
1256
+
1257
+ var _ScanQrcode = (context) => {
1258
+ var _a;
1259
+ const data = context.data;
1260
+ const inputs = context.inputs;
1261
+ const outputs = context.outputs;
1262
+ (_a = inputs.scan) === null || _a === void 0 ? void 0 : _a.call(inputs, (val) => {
1263
+ var _a, _b, _c, _d;
1264
+ try {
1265
+ const scanConfig = {
1266
+ onlyFromCamera: (_b = (_a = val === null || val === void 0 ? void 0 : val.onlyFromCamera) !== null && _a !== void 0 ? _a : data.onlyFromCamera) !== null && _b !== void 0 ? _b : false,
1267
+ scanType: (_d = (_c = val === null || val === void 0 ? void 0 : val.scanType) !== null && _c !== void 0 ? _c : data.scanType) !== null && _d !== void 0 ? _d : ['barCode', 'qrCode'],
1268
+ success: (res) => {
1269
+ outputs.onSuccess(res.result || res);
1270
+ },
1271
+ fail: (err) => {
1272
+ outputs.onFail(err.errMsg || '扫码失败');
1273
+ },
1274
+ };
1275
+ Taro.scanCode(scanConfig);
1276
+ }
1277
+ catch (error) {
1278
+ console.error('扫码失败:', error);
1279
+ outputs.onFail((error === null || error === void 0 ? void 0 : error.message) || '扫码失败');
1280
+ }
1281
+ });
1282
+ };
1283
+
1284
+ var _SetStorage = (context) => {
1285
+ var _a;
1286
+ const data = context.data;
1287
+ const inputs = context.inputs;
1288
+ const outputs = context.outputs;
1289
+ (_a = inputs.setStorage) === null || _a === void 0 ? void 0 : _a.call(inputs, (val) => {
1290
+ try {
1291
+ const key = (val === null || val === void 0 ? void 0 : val.key) || data.key;
1292
+ const value = (val === null || val === void 0 ? void 0 : val.value) !== undefined ? val.value : data.value;
1293
+ const useSync = (val === null || val === void 0 ? void 0 : val.sync) !== undefined ? val.sync : data.sync || false;
1294
+ if (!key) {
1295
+ outputs.onFail('存储 key 不能为空');
1296
+ return;
1297
+ }
1298
+ const result = { key, value };
1299
+ if (useSync) {
1300
+ Taro.setStorageSync(key, value);
1301
+ outputs.onSuccess(result);
1302
+ }
1303
+ else {
1304
+ Taro.setStorage({
1305
+ key,
1306
+ data: value,
1307
+ success: () => outputs.onSuccess(result),
1308
+ fail: (err) => outputs.onFail(err.errMsg || '写入本地缓存失败'),
1309
+ });
1310
+ }
1311
+ }
1312
+ catch (error) {
1313
+ console.error('写入本地缓存失败:', error);
1314
+ outputs.onFail((error === null || error === void 0 ? void 0 : error.message) || '写入本地缓存失败');
1315
+ }
1316
+ });
1317
+ };
1318
+
1319
+ var _GetStorage = (context) => {
1320
+ var _a;
1321
+ const data = context.data;
1322
+ const inputs = context.inputs;
1323
+ const outputs = context.outputs;
1324
+ (_a = inputs.getStorage) === null || _a === void 0 ? void 0 : _a.call(inputs, (val) => {
1325
+ try {
1326
+ const key = (val === null || val === void 0 ? void 0 : val.key) || data.key;
1327
+ const useSync = (val === null || val === void 0 ? void 0 : val.sync) !== undefined ? val.sync : data.sync || false;
1328
+ if (!key) {
1329
+ outputs.onFail('存储 key 不能为空');
1330
+ return;
1331
+ }
1332
+ if (useSync) {
1333
+ try {
1334
+ const value = Taro.getStorageSync(key);
1335
+ outputs.onSuccess({ key, value });
1336
+ }
1337
+ catch (error) {
1338
+ outputs.onFail((error === null || error === void 0 ? void 0 : error.message) || '读取本地缓存失败');
1339
+ }
1340
+ }
1341
+ else {
1342
+ Taro.getStorage({
1343
+ key,
1344
+ success: (res) => outputs.onSuccess({ key, value: res.data }),
1345
+ fail: (err) => outputs.onFail(err.errMsg || '读取本地缓存失败'),
1346
+ });
1347
+ }
1348
+ }
1349
+ catch (error) {
1350
+ console.error('读取本地缓存失败:', error);
1351
+ outputs.onFail((error === null || error === void 0 ? void 0 : error.message) || '读取本地缓存失败');
1352
+ }
1353
+ });
1354
+ };
1355
+
1356
+ var _RemoveStorage = (context) => {
1357
+ var _a;
1358
+ const data = context.data;
1359
+ const inputs = context.inputs;
1360
+ const outputs = context.outputs;
1361
+ (_a = inputs.removeStorage) === null || _a === void 0 ? void 0 : _a.call(inputs, (val) => {
1362
+ try {
1363
+ const key = (val === null || val === void 0 ? void 0 : val.key) || data.key;
1364
+ const useSync = (val === null || val === void 0 ? void 0 : val.sync) !== undefined ? val.sync : data.sync || false;
1365
+ if (!key) {
1366
+ outputs.onFail('存储 key 不能为空');
1367
+ return;
1368
+ }
1369
+ if (useSync) {
1370
+ try {
1371
+ Taro.removeStorageSync(key);
1372
+ outputs.onSuccess({ key });
1373
+ }
1374
+ catch (error) {
1375
+ outputs.onFail((error === null || error === void 0 ? void 0 : error.message) || '移除本地缓存失败');
1376
+ }
1377
+ }
1378
+ else {
1379
+ Taro.removeStorage({
1380
+ key,
1381
+ success: () => outputs.onSuccess({ key }),
1382
+ fail: (err) => outputs.onFail(err.errMsg || '移除本地缓存失败'),
1383
+ });
1384
+ }
1385
+ }
1386
+ catch (error) {
1387
+ console.error('移除本地缓存失败:', error);
1388
+ outputs.onFail((error === null || error === void 0 ? void 0 : error.message) || '移除本地缓存失败');
1389
+ }
1390
+ });
1391
+ };
1392
+
1393
+ var _GetLocation = (context) => {
1394
+ var _a;
1395
+ const data = context.data;
1396
+ const inputs = context.inputs;
1397
+ const outputs = context.outputs;
1398
+ (_a = inputs.getLocation) === null || _a === void 0 ? void 0 : _a.call(inputs, (val) => {
1399
+ try {
1400
+ const locationConfig = {
1401
+ type: (val === null || val === void 0 ? void 0 : val.type) || data.type || 'wgs84',
1402
+ altitude: (val === null || val === void 0 ? void 0 : val.altitude) !== undefined ? val.altitude : data.altitude || false,
1403
+ timeout: (val === null || val === void 0 ? void 0 : val.timeout) || data.timeout || 30000,
1404
+ success: (res) => {
1405
+ outputs.onSuccess(res);
1406
+ },
1407
+ fail: (err) => {
1408
+ outputs.onFail(err.errMsg || '获取地理位置失败');
1409
+ },
1410
+ };
1411
+ Taro.getLocation(locationConfig);
1412
+ }
1413
+ catch (error) {
1414
+ console.error('获取地理位置失败:', error);
1415
+ outputs.onFail((error === null || error === void 0 ? void 0 : error.message) || '获取地理位置失败');
1416
+ }
1417
+ });
1418
+ };
1419
+
1420
+ var _Vibrate = (context) => {
1421
+ var _a;
1422
+ const data = context.data;
1423
+ const inputs = context.inputs;
1424
+ const outputs = context.outputs;
1425
+ (_a = inputs.vibrate) === null || _a === void 0 ? void 0 : _a.call(inputs, (val) => {
1426
+ try {
1427
+ const type = (val === null || val === void 0 ? void 0 : val.type) || data.type || 'short';
1428
+ if (type === 'long') {
1429
+ Taro.vibrateLong({
1430
+ success: () => outputs.onSuccess('长振动成功'),
1431
+ fail: (err) => outputs.onFail(err.errMsg || '长振动失败'),
1432
+ });
1433
+ }
1434
+ else {
1435
+ Taro.vibrateShort({
1436
+ success: () => outputs.onSuccess('短振动成功'),
1437
+ fail: (err) => outputs.onFail(err.errMsg || '短振动失败'),
1438
+ });
1439
+ }
1440
+ }
1441
+ catch (error) {
1442
+ console.error('设备振动失败:', error);
1443
+ outputs.onFail((error === null || error === void 0 ? void 0 : error.message) || '设备振动失败');
1444
+ }
1445
+ });
1446
+ };
1447
+
1448
+ var _CallPhone = (context) => {
1449
+ var _a;
1450
+ const data = context.data;
1451
+ const inputs = context.inputs;
1452
+ const outputs = context.outputs;
1453
+ (_a = inputs.callPhone) === null || _a === void 0 ? void 0 : _a.call(inputs, (val) => {
1454
+ try {
1455
+ const phoneNumber = typeof val === 'string' ? val : (val === null || val === void 0 ? void 0 : val.phoneNumber) || data.phoneNumber;
1456
+ if (!phoneNumber) {
1457
+ outputs.onFail('电话号码不能为空');
1458
+ return;
1459
+ }
1460
+ Taro.makePhoneCall({
1461
+ phoneNumber,
1462
+ success: () => outputs.onSuccess({ phoneNumber }),
1463
+ fail: (err) => outputs.onFail(err.errMsg || '拨打电话失败'),
1464
+ });
1465
+ }
1466
+ catch (error) {
1467
+ console.error('拨打电话失败:', error);
1468
+ outputs.onFail((error === null || error === void 0 ? void 0 : error.message) || '拨打电话失败');
1469
+ }
1470
+ });
1471
+ };
1472
+
1473
+ var _OpenCamera = (context) => {
1474
+ var _a;
1475
+ const data = context.data;
1476
+ const inputs = context.inputs;
1477
+ const outputs = context.outputs;
1478
+ (_a = inputs.openCamera) === null || _a === void 0 ? void 0 : _a.call(inputs, (val) => {
1479
+ try {
1480
+ const config = {
1481
+ camera: (val === null || val === void 0 ? void 0 : val.camera) || data.camera || 'back',
1482
+ flash: (val === null || val === void 0 ? void 0 : val.flash) || data.flash || 'auto',
1483
+ quality: (val === null || val === void 0 ? void 0 : val.quality) || data.quality || 'normal',
1484
+ };
1485
+ // Taro没有直接的打开相机API,我们可以:
1486
+ // 1. 使用chooseImage并设置sourceType为camera
1487
+ // 2. 或者提示用户使用系统相机
1488
+ Taro.chooseImage({
1489
+ count: 1,
1490
+ sourceType: ['camera'],
1491
+ success: (res) => {
1492
+ outputs.onSuccess({
1493
+ type: 'camera',
1494
+ tempFilePath: res.tempFilePaths[0],
1495
+ tempFile: res.tempFiles[0],
1496
+ config,
1497
+ });
1498
+ },
1499
+ fail: (err) => {
1500
+ var _a;
1501
+ if ((_a = err.errMsg) === null || _a === void 0 ? void 0 : _a.includes('cancel')) {
1502
+ outputs.onFail('用户取消拍照');
1503
+ }
1504
+ else {
1505
+ outputs.onFail(err.errMsg || '打开相机失败');
1506
+ }
1507
+ },
1508
+ });
1509
+ }
1510
+ catch (error) {
1511
+ console.error('打开相机失败:', error);
1512
+ outputs.onFail((error === null || error === void 0 ? void 0 : error.message) || '打开相机失败');
1513
+ }
1514
+ });
1515
+ };
1516
+
1517
+ var _OpenUrl = (context) => {
1518
+ var _a;
1519
+ const data = context.data;
1520
+ const inputs = context.inputs;
1521
+ const outputs = context.outputs;
1522
+ (_a = inputs.openUrl) === null || _a === void 0 ? void 0 : _a.call(inputs, (val) => {
1523
+ try {
1524
+ const url = typeof val === 'string' ? val : (val === null || val === void 0 ? void 0 : val.url) || data.url;
1525
+ if (!url) {
1526
+ outputs.onFail('URL 地址不能为空');
1527
+ return;
1528
+ }
1529
+ // 检查是否为有效的 URL
1530
+ if (!/^https?:\/\//.test(url)) {
1531
+ outputs.onFail('URL 格式不正确,请以 http:// 或 https:// 开头');
1532
+ return;
1533
+ }
1534
+ Taro.navigateTo({
1535
+ url: `/pages/webview/index?url=${encodeURIComponent(url)}`,
1536
+ success: () => outputs.onSuccess({ url }),
1537
+ fail: (err) => outputs.onFail(err.errMsg || '打开链接失败'),
1538
+ });
1539
+ }
1540
+ catch (error) {
1541
+ console.error('打开链接失败:', error);
1542
+ outputs.onFail((error === null || error === void 0 ? void 0 : error.message) || '打开链接失败');
1543
+ }
1544
+ });
1545
+ };
1546
+
1547
+ var _Share = (context) => {
1548
+ var _a;
1549
+ const data = context.data;
1550
+ const inputs = context.inputs;
1551
+ const outputs = context.outputs;
1552
+ (_a = inputs.share) === null || _a === void 0 ? void 0 : _a.call(inputs, (val) => {
1553
+ try {
1554
+ const shareData = {
1555
+ title: (val === null || val === void 0 ? void 0 : val.title) || data.title || '分享',
1556
+ path: (val === null || val === void 0 ? void 0 : val.path) || data.path || '/pages/index/index',
1557
+ imageUrl: (val === null || val === void 0 ? void 0 : val.imageUrl) || data.imageUrl,
1558
+ };
1559
+ Taro.showShareMenu({
1560
+ withShareTicket: true,
1561
+ success: () => outputs.onSuccess(shareData),
1562
+ fail: (err) => outputs.onFail(err.errMsg || '分享失败'),
1563
+ });
1564
+ }
1565
+ catch (error) {
1566
+ console.error('分享失败:', error);
1567
+ outputs.onFail((error === null || error === void 0 ? void 0 : error.message) || '分享失败');
1568
+ }
1569
+ });
1570
+ };
1571
+
1572
+ var _GetSystemInfo = (context) => {
1573
+ var _a;
1574
+ const data = context.data;
1575
+ const inputs = context.inputs;
1576
+ const outputs = context.outputs;
1577
+ (_a = inputs.getSystemInfo) === null || _a === void 0 ? void 0 : _a.call(inputs, (val) => {
1578
+ try {
1579
+ const useSync = (val === null || val === void 0 ? void 0 : val.sync) !== undefined ? val.sync : data.sync || false;
1580
+ if (useSync) {
1581
+ try {
1582
+ const systemInfo = Taro.getSystemInfoSync();
1583
+ outputs.onSuccess(systemInfo);
1584
+ }
1585
+ catch (error) {
1586
+ outputs.onFail((error === null || error === void 0 ? void 0 : error.message) || '获取系统信息失败');
1587
+ }
1588
+ }
1589
+ else {
1590
+ Taro.getSystemInfo({
1591
+ success: (res) => outputs.onSuccess(res),
1592
+ fail: (err) => outputs.onFail(err.errMsg || '获取系统信息失败'),
1593
+ });
1594
+ }
1595
+ }
1596
+ catch (error) {
1597
+ console.error('获取系统信息失败:', error);
1598
+ outputs.onFail((error === null || error === void 0 ? void 0 : error.message) || '获取系统信息失败');
1599
+ }
1600
+ });
1601
+ };
1602
+
1603
+ var _AesEncode = (context) => {
1604
+ var _a, _b;
1605
+ const data = context.data;
1606
+ const inputs = context.inputs;
1607
+ const outputs = context.outputs;
1608
+ // 模式映射
1609
+ const modeMap = {
1610
+ CBC: CryptoJS.mode.CBC,
1611
+ ECB: CryptoJS.mode.ECB,
1612
+ CFB: CryptoJS.mode.CFB,
1613
+ OFB: CryptoJS.mode.OFB,
1614
+ CTR: CryptoJS.mode.CTR,
1615
+ };
1616
+ // 填充方式映射
1617
+ const paddingMap = {
1618
+ Pkcs7: CryptoJS.pad.Pkcs7,
1619
+ Iso97971: CryptoJS.pad.Iso97971,
1620
+ AnsiX923: CryptoJS.pad.AnsiX923,
1621
+ Iso10126: CryptoJS.pad.Iso10126,
1622
+ ZeroPadding: CryptoJS.pad.ZeroPadding,
1623
+ NoPadding: CryptoJS.pad.NoPadding,
1624
+ };
1625
+ (_a = inputs.encrypt) === null || _a === void 0 ? void 0 : _a.call(inputs, (val) => {
1626
+ try {
1627
+ const text = val.text || '';
1628
+ const key = val.key || data.key || 'defaultKey1234567890123456';
1629
+ const iv = val.iv || data.iv;
1630
+ const mode = modeMap[val.mode || data.mode || 'CBC'];
1631
+ const padding = paddingMap[val.padding || data.padding || 'Pkcs7'];
1632
+ if (!text) {
1633
+ outputs.onFail('待加密文本不能为空');
1634
+ return;
1635
+ }
1636
+ const keyBytes = CryptoJS.enc.Utf8.parse(key);
1637
+ const ivBytes = iv ? CryptoJS.enc.Utf8.parse(iv) : undefined;
1638
+ const encrypted = CryptoJS.AES.encrypt(text, keyBytes, {
1639
+ mode,
1640
+ padding,
1641
+ iv: ivBytes,
1642
+ });
1643
+ outputs.onEncryptSuccess({
1644
+ encryptedText: encrypted.toString(),
1645
+ originalText: text,
1646
+ });
1647
+ }
1648
+ catch (error) {
1649
+ console.error('AES加密失败:', error);
1650
+ outputs.onFail((error === null || error === void 0 ? void 0 : error.message) || 'AES加密失败');
1651
+ }
1652
+ });
1653
+ (_b = inputs.decrypt) === null || _b === void 0 ? void 0 : _b.call(inputs, (val) => {
1654
+ try {
1655
+ const encryptedText = val.encryptedText || '';
1656
+ const key = val.key || data.key || 'defaultKey1234567890123456';
1657
+ const iv = val.iv || data.iv;
1658
+ const mode = modeMap[val.mode || data.mode || 'CBC'];
1659
+ const padding = paddingMap[val.padding || data.padding || 'Pkcs7'];
1660
+ if (!encryptedText) {
1661
+ outputs.onFail('待解密文本不能为空');
1662
+ return;
1663
+ }
1664
+ const keyBytes = CryptoJS.enc.Utf8.parse(key);
1665
+ const ivBytes = iv ? CryptoJS.enc.Utf8.parse(iv) : undefined;
1666
+ const decrypted = CryptoJS.AES.decrypt(encryptedText, keyBytes, {
1667
+ mode,
1668
+ padding,
1669
+ iv: ivBytes,
1670
+ });
1671
+ const decryptedText = decrypted.toString(CryptoJS.enc.Utf8);
1672
+ if (!decryptedText) {
1673
+ outputs.onFail('解密失败,可能密钥或参数不正确');
1674
+ return;
1675
+ }
1676
+ outputs.onDecryptSuccess({
1677
+ decryptedText,
1678
+ encryptedText,
1679
+ });
1680
+ }
1681
+ catch (error) {
1682
+ console.error('AES解密失败:', error);
1683
+ outputs.onFail((error === null || error === void 0 ? void 0 : error.message) || 'AES解密失败');
1684
+ }
1685
+ });
1686
+ };
1687
+
1688
+ var _Modal = (context) => {
1689
+ var _a;
1690
+ const data = context.data;
1691
+ const inputs = context.inputs;
1692
+ const outputs = context.outputs;
1693
+ (_a = inputs.show) === null || _a === void 0 ? void 0 : _a.call(inputs, async (val) => {
1694
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q;
1695
+ try {
1696
+ const cfg = typeof val === 'string'
1697
+ ? { content: val }
1698
+ : (val || {});
1699
+ const modalConfig = {
1700
+ title: (_b = (_a = cfg.title) !== null && _a !== void 0 ? _a : data.title) !== null && _b !== void 0 ? _b : '',
1701
+ content: (_d = (_c = cfg.content) !== null && _c !== void 0 ? _c : data.content) !== null && _d !== void 0 ? _d : '',
1702
+ showCancel: (_f = (_e = cfg.showCancel) !== null && _e !== void 0 ? _e : data.showCancel) !== null && _f !== void 0 ? _f : true,
1703
+ cancelText: (_h = (_g = cfg.cancelText) !== null && _g !== void 0 ? _g : data.cancelText) !== null && _h !== void 0 ? _h : '取消',
1704
+ cancelColor: (_j = cfg.cancelColor) !== null && _j !== void 0 ? _j : data.cancelColor,
1705
+ confirmText: (_l = (_k = cfg.confirmText) !== null && _k !== void 0 ? _k : data.confirmText) !== null && _l !== void 0 ? _l : '确认',
1706
+ confirmColor: (_m = cfg.confirmColor) !== null && _m !== void 0 ? _m : data.confirmColor,
1707
+ };
1708
+ // editable 不是所有端都支持,按存在即传
1709
+ if (cfg.editable !== undefined)
1710
+ modalConfig.editable = cfg.editable;
1711
+ else if (data.editable !== undefined)
1712
+ modalConfig.editable = data.editable;
1713
+ const res = await Taro.showModal(modalConfig);
1714
+ if (res === null || res === void 0 ? void 0 : res.confirm)
1715
+ (_o = outputs.onConfirm) === null || _o === void 0 ? void 0 : _o.call(outputs, res);
1716
+ else
1717
+ (_p = outputs.onCancel) === null || _p === void 0 ? void 0 : _p.call(outputs, res);
1718
+ }
1719
+ catch (error) {
1720
+ console.error('显示 Modal 失败:', error);
1721
+ (_q = outputs.onCancel) === null || _q === void 0 ? void 0 : _q.call(outputs, error);
1722
+ }
1723
+ });
1724
+ };
1725
+
1726
+ var _Format = (context) => {
1727
+ var _a;
1728
+ const data = context.data;
1729
+ const inputs = context.inputs;
1730
+ const outputs = context.outputs;
1731
+ (_a = inputs.format) === null || _a === void 0 ? void 0 : _a.call(inputs, (val) => {
1732
+ try {
1733
+ const input = (val === null || val === void 0 ? void 0 : val.input) !== undefined ? val.input : data.input;
1734
+ const format = (val === null || val === void 0 ? void 0 : val.format) || data.format || 'string';
1735
+ const options = (val === null || val === void 0 ? void 0 : val.options) || data.options || {};
1736
+ if (input === undefined || input === null) {
1737
+ outputs.onFail('输入值不能为空');
1738
+ return;
1739
+ }
1740
+ let result;
1741
+ switch (format) {
1742
+ case 'json':
1743
+ if (typeof input === 'string') {
1744
+ try {
1745
+ result = JSON.parse(input);
1746
+ }
1747
+ catch (error) {
1748
+ outputs.onFail('JSON解析失败');
1749
+ return;
1750
+ }
1751
+ }
1752
+ else {
1753
+ result = JSON.stringify(input, null, 2);
1754
+ }
1755
+ break;
1756
+ case 'string':
1757
+ result = String(input);
1758
+ break;
1759
+ case 'number':
1760
+ const num = Number(input);
1761
+ if (isNaN(num)) {
1762
+ outputs.onFail('无法转换为有效数字');
1763
+ return;
1764
+ }
1765
+ result = options.precision !== undefined ? Number(num.toFixed(options.precision)) : num;
1766
+ break;
1767
+ case 'boolean':
1768
+ result = Boolean(input);
1769
+ break;
1770
+ case 'date':
1771
+ const date = new Date(input);
1772
+ if (isNaN(date.getTime())) {
1773
+ outputs.onFail('无效的日期格式');
1774
+ return;
1775
+ }
1776
+ if (options.dateFormat) {
1777
+ // 简单的日期格式化
1778
+ const year = date.getFullYear();
1779
+ const month = String(date.getMonth() + 1).padStart(2, '0');
1780
+ const day = String(date.getDate()).padStart(2, '0');
1781
+ const hours = String(date.getHours()).padStart(2, '0');
1782
+ const minutes = String(date.getMinutes()).padStart(2, '0');
1783
+ const seconds = String(date.getSeconds()).padStart(2, '0');
1784
+ result = options.dateFormat
1785
+ .replace('YYYY', year.toString())
1786
+ .replace('MM', month)
1787
+ .replace('DD', day)
1788
+ .replace('HH', hours)
1789
+ .replace('mm', minutes)
1790
+ .replace('ss', seconds);
1791
+ }
1792
+ else {
1793
+ result = date.toISOString();
1794
+ }
1795
+ break;
1796
+ case 'base64':
1797
+ if (typeof input === 'string') {
1798
+ try {
1799
+ // 尝试解码Base64
1800
+ result = decodeURIComponent(escape(atob(input)));
1801
+ }
1802
+ catch {
1803
+ // 如果解码失败,则编码为Base64
1804
+ result = btoa(unescape(encodeURIComponent(input)));
1805
+ }
1806
+ }
1807
+ else {
1808
+ outputs.onFail('Base64转换需要字符串输入');
1809
+ return;
1810
+ }
1811
+ break;
1812
+ case 'urlEncode':
1813
+ result = encodeURIComponent(String(input));
1814
+ break;
1815
+ case 'urlDecode':
1816
+ try {
1817
+ result = decodeURIComponent(String(input));
1818
+ }
1819
+ catch (error) {
1820
+ outputs.onFail('URL解码失败');
1821
+ return;
1822
+ }
1823
+ break;
1824
+ default:
1825
+ outputs.onFail(`不支持的格式类型: ${format}`);
1826
+ return;
1827
+ }
1828
+ outputs.onSuccess({
1829
+ input,
1830
+ output: result,
1831
+ format,
1832
+ options,
1833
+ });
1834
+ }
1835
+ catch (error) {
1836
+ console.error('格式化失败:', error);
1837
+ outputs.onFail((error === null || error === void 0 ? void 0 : error.message) || '格式化失败');
1838
+ }
1839
+ });
1840
+ };
1841
+
1842
+ var _ChooseFile = (context) => {
1843
+ var _a;
1844
+ const data = context.data;
1845
+ const inputs = context.inputs;
1846
+ const outputs = context.outputs;
1847
+ (_a = inputs.chooseFile) === null || _a === void 0 ? void 0 : _a.call(inputs, (val) => {
1848
+ var _a, _b, _c;
1849
+ try {
1850
+ const config = {
1851
+ accept: (val === null || val === void 0 ? void 0 : val.accept) || data.accept || 'image/*',
1852
+ multiple: (val === null || val === void 0 ? void 0 : val.multiple) !== undefined ? val.multiple : data.multiple || false,
1853
+ capture: (val === null || val === void 0 ? void 0 : val.capture) || data.capture,
1854
+ compressed: (val === null || val === void 0 ? void 0 : val.compressed) !== undefined ? val.compressed : data.compressed,
1855
+ maxDuration: (val === null || val === void 0 ? void 0 : val.maxDuration) || data.maxDuration,
1856
+ camera: (val === null || val === void 0 ? void 0 : val.camera) || data.camera,
1857
+ };
1858
+ // 根据文件类型选择不同的API
1859
+ if ((_a = config.accept) === null || _a === void 0 ? void 0 : _a.startsWith('image/')) {
1860
+ // 选择图片
1861
+ Taro.chooseImage({
1862
+ count: config.multiple ? 9 : 1,
1863
+ sourceType: config.capture === 'album' ? ['album'] : config.capture === 'camera' ? ['camera'] : ['album', 'camera'],
1864
+ success: (res) => {
1865
+ outputs.onSuccess({
1866
+ type: 'image',
1867
+ files: res.tempFiles,
1868
+ tempFilePaths: res.tempFilePaths,
1869
+ });
1870
+ },
1871
+ fail: (err) => outputs.onFail(err.errMsg || '选择图片失败'),
1872
+ });
1873
+ }
1874
+ else if ((_b = config.accept) === null || _b === void 0 ? void 0 : _b.startsWith('video/')) {
1875
+ // 选择视频
1876
+ Taro.chooseVideo({
1877
+ sourceType: config.capture === 'album' ? ['album'] : config.capture === 'camera' ? ['camera'] : ['album', 'camera'],
1878
+ compressed: config.compressed,
1879
+ maxDuration: config.maxDuration,
1880
+ camera: config.camera,
1881
+ success: (res) => {
1882
+ outputs.onSuccess({
1883
+ type: 'video',
1884
+ file: res,
1885
+ });
1886
+ },
1887
+ fail: (err) => outputs.onFail(err.errMsg || '选择视频失败'),
1888
+ });
1889
+ }
1890
+ else if ((_c = config.accept) === null || _c === void 0 ? void 0 : _c.startsWith('audio/')) {
1891
+ // 选择音频(小程序暂不支持直接选择音频文件,这里返回提示)
1892
+ outputs.onFail('小程序暂不支持直接选择音频文件');
1893
+ }
1894
+ else {
1895
+ // 其他文件类型,使用文件选择器(如果支持)
1896
+ if (Taro.chooseMessageFile) {
1897
+ Taro.chooseMessageFile({
1898
+ count: config.multiple ? 10 : 1,
1899
+ type: 'file',
1900
+ success: (res) => {
1901
+ outputs.onSuccess({
1902
+ type: 'file',
1903
+ files: res.tempFiles,
1904
+ });
1905
+ },
1906
+ fail: (err) => outputs.onFail(err.errMsg || '选择文件失败'),
1907
+ });
1908
+ }
1909
+ else {
1910
+ outputs.onFail('当前环境不支持文件选择');
1911
+ }
1912
+ }
1913
+ }
1914
+ catch (error) {
1915
+ console.error('文件选择失败:', error);
1916
+ outputs.onFail((error === null || error === void 0 ? void 0 : error.message) || '文件选择失败');
1917
+ }
1918
+ });
1919
+ };
1920
+
1921
+ var _ChooseMedia = (context) => {
1922
+ var _a;
1923
+ const data = context.data;
1924
+ const inputs = context.inputs;
1925
+ const outputs = context.outputs;
1926
+ (_a = inputs.chooseMedia) === null || _a === void 0 ? void 0 : _a.call(inputs, (val) => {
1927
+ try {
1928
+ const config = {
1929
+ mediaType: (val === null || val === void 0 ? void 0 : val.mediaType) || data.mediaType || ['image', 'video'],
1930
+ sourceType: (val === null || val === void 0 ? void 0 : val.sourceType) || data.sourceType || ['album', 'camera'],
1931
+ count: (val === null || val === void 0 ? void 0 : val.count) || data.count || 9,
1932
+ sizeType: (val === null || val === void 0 ? void 0 : val.sizeType) || data.sizeType || ['original', 'compressed'],
1933
+ maxDuration: (val === null || val === void 0 ? void 0 : val.maxDuration) || data.maxDuration || 10,
1934
+ camera: (val === null || val === void 0 ? void 0 : val.camera) || data.camera,
1935
+ };
1936
+ Taro.chooseMedia({
1937
+ ...config,
1938
+ success: (res) => {
1939
+ var _a;
1940
+ outputs.onSuccess({
1941
+ type: res.type,
1942
+ tempFiles: res.tempFiles,
1943
+ tempFilePaths: res.tempFilePaths || ((_a = res.tempFiles) === null || _a === void 0 ? void 0 : _a.map(file => file.tempFilePath)),
1944
+ });
1945
+ },
1946
+ fail: (err) => {
1947
+ outputs.onFail(err.errMsg || '选择媒体失败');
1948
+ },
1949
+ });
1950
+ }
1951
+ catch (error) {
1952
+ console.error('选择媒体失败:', error);
1953
+ outputs.onFail((error === null || error === void 0 ? void 0 : error.message) || '选择媒体失败');
1954
+ }
1955
+ });
1956
+ };
1957
+
1958
+ var _Connector = (context) => {
1959
+ var _a;
1960
+ const data = context.data;
1961
+ const inputs = context.inputs;
1962
+ const outputs = context.outputs;
1963
+ (_a = inputs.request) === null || _a === void 0 ? void 0 : _a.call(inputs, (val) => {
1964
+ try {
1965
+ const config = {
1966
+ method: (val === null || val === void 0 ? void 0 : val.method) || data.method || 'GET',
1967
+ url: (val === null || val === void 0 ? void 0 : val.url) || data.url,
1968
+ header: (val === null || val === void 0 ? void 0 : val.headers) || data.headers || {},
1969
+ data: (val === null || val === void 0 ? void 0 : val.data) || data.data,
1970
+ timeout: (val === null || val === void 0 ? void 0 : val.timeout) || data.timeout,
1971
+ dataType: (val === null || val === void 0 ? void 0 : val.dataType) || data.dataType || 'json',
1972
+ responseType: (val === null || val === void 0 ? void 0 : val.responseType) || data.responseType || 'text',
1973
+ };
1974
+ if (!config.url) {
1975
+ outputs.onFail('请求URL不能为空');
1976
+ return;
1977
+ }
1978
+ // 检查URL格式
1979
+ if (!/^https?:\/\//.test(config.url)) {
1980
+ outputs.onFail('URL格式不正确,请以http://或https://开头');
1981
+ return;
1982
+ }
1983
+ Taro.request({
1984
+ ...config,
1985
+ success: (res) => {
1986
+ if (res.statusCode >= 200 && res.statusCode < 300) {
1987
+ outputs.onSuccess({
1988
+ data: res.data,
1989
+ statusCode: res.statusCode,
1990
+ header: res.header,
1991
+ });
1992
+ }
1993
+ else {
1994
+ outputs.onFail({
1995
+ message: `请求失败: ${res.statusCode}`,
1996
+ statusCode: res.statusCode,
1997
+ data: res.data,
1998
+ });
1999
+ }
2000
+ },
2001
+ fail: (err) => {
2002
+ outputs.onFail({
2003
+ message: err.errMsg || '网络请求失败',
2004
+ error: err,
2005
+ });
2006
+ },
2007
+ });
2008
+ }
2009
+ catch (error) {
2010
+ console.error('网络请求失败:', error);
2011
+ outputs.onFail({
2012
+ message: (error === null || error === void 0 ? void 0 : error.message) || '网络请求失败',
2013
+ error,
2014
+ });
2015
+ }
2016
+ });
2017
+ };
2018
+
2019
+ // 全局请求头存储
2020
+ let globalHeaders = {};
2021
+ var _ConnectorGlobalHeaders = (context) => {
2022
+ var _a, _b, _c;
2023
+ const data = context.data;
2024
+ const inputs = context.inputs;
2025
+ const outputs = context.outputs;
2026
+ (_a = inputs.setGlobalHeaders) === null || _a === void 0 ? void 0 : _a.call(inputs, (val) => {
2027
+ try {
2028
+ const headers = (val === null || val === void 0 ? void 0 : val.headers) || data.headers || {};
2029
+ if (Object.keys(headers).length === 0) {
2030
+ outputs.onFail('请求头不能为空');
2031
+ return;
2032
+ }
2033
+ // 合并到全局请求头
2034
+ globalHeaders = { ...globalHeaders, ...headers };
2035
+ outputs.onSuccess({
2036
+ globalHeaders: { ...globalHeaders },
2037
+ addedHeaders: headers,
2038
+ });
2039
+ }
2040
+ catch (error) {
2041
+ console.error('设置全局请求头失败:', error);
2042
+ outputs.onFail((error === null || error === void 0 ? void 0 : error.message) || '设置全局请求头失败');
2043
+ }
2044
+ });
2045
+ (_b = inputs.getGlobalHeaders) === null || _b === void 0 ? void 0 : _b.call(inputs, () => {
2046
+ try {
2047
+ outputs.onSuccess({
2048
+ globalHeaders: { ...globalHeaders },
2049
+ });
2050
+ }
2051
+ catch (error) {
2052
+ console.error('获取全局请求头失败:', error);
2053
+ outputs.onFail((error === null || error === void 0 ? void 0 : error.message) || '获取全局请求头失败');
2054
+ }
2055
+ });
2056
+ (_c = inputs.clearGlobalHeaders) === null || _c === void 0 ? void 0 : _c.call(inputs, () => {
2057
+ try {
2058
+ const oldHeaders = { ...globalHeaders };
2059
+ globalHeaders = {};
2060
+ outputs.onSuccess({
2061
+ clearedHeaders: oldHeaders,
2062
+ globalHeaders: {},
2063
+ });
2064
+ }
2065
+ catch (error) {
2066
+ console.error('清除全局请求头失败:', error);
2067
+ outputs.onFail((error === null || error === void 0 ? void 0 : error.message) || '清除全局请求头失败');
2068
+ }
2069
+ });
2070
+ };
2071
+
2072
+ var _BackTo = (context) => {
2073
+ var _a;
2074
+ const data = context.data;
2075
+ const inputs = context.inputs;
2076
+ const outputs = context.outputs;
2077
+ (_a = inputs.back) === null || _a === void 0 ? void 0 : _a.call(inputs, (val) => {
2078
+ var _a, _b, _c;
2079
+ try {
2080
+ const delta = (_b = (_a = val === null || val === void 0 ? void 0 : val.delta) !== null && _a !== void 0 ? _a : data.delta) !== null && _b !== void 0 ? _b : 1;
2081
+ const animation = (val === null || val === void 0 ? void 0 : val.animation) !== undefined ? val.animation : (_c = data.animation) !== null && _c !== void 0 ? _c : true;
2082
+ // 获取当前页面栈信息
2083
+ const pages = Taro.getCurrentPages();
2084
+ const currentIndex = pages.length - 1;
2085
+ if (currentIndex === 0) {
2086
+ // 如果是首页,返回失败
2087
+ outputs.onFail('已经是首页,无法返回');
2088
+ return;
2089
+ }
2090
+ if (delta > currentIndex) {
2091
+ // 如果返回层数超过页面栈深度,返回失败
2092
+ outputs.onFail(`页面栈深度不足,无法返回${delta}层`);
2093
+ return;
2094
+ }
2095
+ if (delta === 1) {
2096
+ // 返回上一页
2097
+ Taro.navigateBack({
2098
+ delta: 1,
2099
+ animation,
2100
+ success: () => outputs.onSuccess({ delta: 1 }),
2101
+ fail: (err) => outputs.onFail(err.errMsg || '返回失败'),
2102
+ });
2103
+ }
2104
+ else {
2105
+ // 多层返回,需要先获取目标页面信息
2106
+ const targetPage = pages[currentIndex - delta];
2107
+ if (targetPage) {
2108
+ Taro.navigateBack({
2109
+ delta,
2110
+ animation,
2111
+ success: () => outputs.onSuccess({ delta, targetPage: targetPage.route }),
2112
+ fail: (err) => outputs.onFail(err.errMsg || '返回失败'),
2113
+ });
2114
+ }
2115
+ else {
2116
+ outputs.onFail('目标页面不存在');
2117
+ }
2118
+ }
2119
+ }
2120
+ catch (error) {
2121
+ console.error('返回操作失败:', error);
2122
+ outputs.onFail((error === null || error === void 0 ? void 0 : error.message) || '返回操作失败');
2123
+ }
2124
+ });
2125
+ };
2126
+
2127
+ var _Router = (context) => {
2128
+ var _a;
2129
+ const data = context.data;
2130
+ const inputs = context.inputs;
2131
+ const outputs = context.outputs;
2132
+ (_a = inputs.navigate) === null || _a === void 0 ? void 0 : _a.call(inputs, (val) => {
2133
+ try {
2134
+ const type = (val === null || val === void 0 ? void 0 : val.type) || data.type || 'navigateTo';
2135
+ const path = (val === null || val === void 0 ? void 0 : val.path) || data.path;
2136
+ const params = (val === null || val === void 0 ? void 0 : val.params) || data.params || {};
2137
+ const delta = (val === null || val === void 0 ? void 0 : val.delta) || data.delta || 1;
2138
+ if (!path && type !== 'navigateBack') {
2139
+ outputs.onFail('路由路径不能为空');
2140
+ return;
2141
+ }
2142
+ // 构建完整的URL
2143
+ let url = path;
2144
+ if (params && Object.keys(params).length > 0) {
2145
+ const queryString = Object.entries(params)
2146
+ .map(([key, value]) => `${key}=${encodeURIComponent(String(value))}`)
2147
+ .join('&');
2148
+ url += (url.includes('?') ? '&' : '?') + queryString;
2149
+ }
2150
+ switch (type) {
2151
+ case 'navigateTo':
2152
+ Taro.navigateTo({
2153
+ url,
2154
+ success: () => outputs.onSuccess({ type, path: url, params }),
2155
+ fail: (err) => outputs.onFail(err.errMsg || '页面跳转失败'),
2156
+ });
2157
+ break;
2158
+ case 'redirectTo':
2159
+ Taro.redirectTo({
2160
+ url,
2161
+ success: () => outputs.onSuccess({ type, path: url, params }),
2162
+ fail: (err) => outputs.onFail(err.errMsg || '页面重定向失败'),
2163
+ });
2164
+ break;
2165
+ case 'switchTab':
2166
+ Taro.switchTab({
2167
+ url,
2168
+ success: () => outputs.onSuccess({ type, path: url, params }),
2169
+ fail: (err) => outputs.onFail(err.errMsg || '切换Tab失败'),
2170
+ });
2171
+ break;
2172
+ case 'reLaunch':
2173
+ Taro.reLaunch({
2174
+ url,
2175
+ success: () => outputs.onSuccess({ type, path: url, params }),
2176
+ fail: (err) => outputs.onFail(err.errMsg || '重启应用失败'),
2177
+ });
2178
+ break;
2179
+ case 'navigateBack':
2180
+ Taro.navigateBack({
2181
+ delta,
2182
+ success: () => outputs.onSuccess({ type, delta }),
2183
+ fail: (err) => outputs.onFail(err.errMsg || '返回失败'),
2184
+ });
2185
+ break;
2186
+ default:
2187
+ outputs.onFail(`不支持的路由类型: ${type}`);
2188
+ }
2189
+ }
2190
+ catch (error) {
2191
+ console.error('路由跳转失败:', error);
2192
+ outputs.onFail((error === null || error === void 0 ? void 0 : error.message) || '路由跳转失败');
2193
+ }
2194
+ });
2195
+ };
2196
+
2197
+ var _OpenPetalMap = (context) => {
2198
+ var _a;
2199
+ const data = context.data;
2200
+ const inputs = context.inputs;
2201
+ const outputs = context.outputs;
2202
+ (_a = inputs.openMap) === null || _a === void 0 ? void 0 : _a.call(inputs, (val) => {
2203
+ try {
2204
+ const config = {
2205
+ latitude: (val === null || val === void 0 ? void 0 : val.latitude) || data.latitude || 39.9093,
2206
+ longitude: (val === null || val === void 0 ? void 0 : val.longitude) || data.longitude || 116.3974,
2207
+ scale: (val === null || val === void 0 ? void 0 : val.scale) || data.scale || 16,
2208
+ markers: (val === null || val === void 0 ? void 0 : val.markers) || data.markers || [],
2209
+ showLocation: (val === null || val === void 0 ? void 0 : val.showLocation) !== undefined ? val.showLocation : data.showLocation || true,
2210
+ };
2211
+ // 小程序环境下,使用Taro的地图组件
2212
+ // 这里可以导航到地图页面或直接显示地图
2213
+ outputs.onSuccess({
2214
+ type: 'map',
2215
+ config,
2216
+ message: '地图配置已准备就绪,请在页面中使用Map组件显示',
2217
+ });
2218
+ }
2219
+ catch (error) {
2220
+ console.error('打开地图失败:', error);
2221
+ outputs.onFail((error === null || error === void 0 ? void 0 : error.message) || '打开地图失败');
2222
+ }
2223
+ });
2224
+ };
2225
+
2226
+ // 检查浏览器是否支持Web Speech API
2227
+ const speechSupported = typeof window !== 'undefined' && 'speechSynthesis' in window;
2228
+ let currentUtterance = null;
2229
+ var _TextToSpeech = (context) => {
2230
+ var _a, _b, _c, _d;
2231
+ const data = context.data;
2232
+ const inputs = context.inputs;
2233
+ const outputs = context.outputs;
2234
+ if (!speechSupported) {
2235
+ console.warn('当前环境不支持语音合成功能');
2236
+ }
2237
+ (_a = inputs.speak) === null || _a === void 0 ? void 0 : _a.call(inputs, (val) => {
2238
+ try {
2239
+ const text = (val === null || val === void 0 ? void 0 : val.text) || data.text;
2240
+ const lang = (val === null || val === void 0 ? void 0 : val.lang) || data.lang || 'zh-CN';
2241
+ const rate = (val === null || val === void 0 ? void 0 : val.rate) || data.rate || 1;
2242
+ const pitch = (val === null || val === void 0 ? void 0 : val.pitch) || data.pitch || 1;
2243
+ const volume = (val === null || val === void 0 ? void 0 : val.volume) || data.volume || 1;
2244
+ if (!text) {
2245
+ outputs.onFail('待合成的文本不能为空');
2246
+ return;
2247
+ }
2248
+ if (!speechSupported) {
2249
+ outputs.onFail('当前环境不支持语音合成功能');
2250
+ return;
2251
+ }
2252
+ // 如果有正在播放的语音,先停止
2253
+ if (currentUtterance && window.speechSynthesis.speaking) {
2254
+ window.speechSynthesis.cancel();
2255
+ }
2256
+ currentUtterance = new SpeechSynthesisUtterance(text);
2257
+ currentUtterance.lang = lang;
2258
+ currentUtterance.rate = Math.max(0.1, Math.min(10, rate));
2259
+ currentUtterance.pitch = Math.max(0, Math.min(2, pitch));
2260
+ currentUtterance.volume = Math.max(0, Math.min(1, volume));
2261
+ currentUtterance.onstart = () => {
2262
+ outputs.onStart({ text, lang, rate, pitch, volume });
2263
+ };
2264
+ currentUtterance.onend = () => {
2265
+ outputs.onEnd({ text, lang, rate, pitch, volume });
2266
+ currentUtterance = null;
2267
+ };
2268
+ currentUtterance.onerror = (event) => {
2269
+ outputs.onError({
2270
+ error: event.error,
2271
+ text,
2272
+ message: '语音合成失败',
2273
+ });
2274
+ currentUtterance = null;
2275
+ };
2276
+ window.speechSynthesis.speak(currentUtterance);
2277
+ outputs.onSuccess({ text, lang, rate, pitch, volume });
2278
+ }
2279
+ catch (error) {
2280
+ console.error('语音合成失败:', error);
2281
+ outputs.onFail((error === null || error === void 0 ? void 0 : error.message) || '语音合成失败');
2282
+ }
2283
+ });
2284
+ (_b = inputs.stop) === null || _b === void 0 ? void 0 : _b.call(inputs, () => {
2285
+ try {
2286
+ if (speechSupported && currentUtterance) {
2287
+ window.speechSynthesis.cancel();
2288
+ currentUtterance = null;
2289
+ outputs.onSuccess('已停止语音播放');
2290
+ }
2291
+ else {
2292
+ outputs.onFail('没有正在播放的语音');
2293
+ }
2294
+ }
2295
+ catch (error) {
2296
+ console.error('停止语音失败:', error);
2297
+ outputs.onFail((error === null || error === void 0 ? void 0 : error.message) || '停止语音失败');
2298
+ }
2299
+ });
2300
+ (_c = inputs.pause) === null || _c === void 0 ? void 0 : _c.call(inputs, () => {
2301
+ try {
2302
+ if (speechSupported && window.speechSynthesis.pause) {
2303
+ window.speechSynthesis.pause();
2304
+ outputs.onSuccess('已暂停语音播放');
2305
+ }
2306
+ else {
2307
+ outputs.onFail('当前环境不支持暂停功能');
2308
+ }
2309
+ }
2310
+ catch (error) {
2311
+ console.error('暂停语音失败:', error);
2312
+ outputs.onFail((error === null || error === void 0 ? void 0 : error.message) || '暂停语音失败');
2313
+ }
2314
+ });
2315
+ (_d = inputs.resume) === null || _d === void 0 ? void 0 : _d.call(inputs, () => {
2316
+ try {
2317
+ if (speechSupported && window.speechSynthesis.resume) {
2318
+ window.speechSynthesis.resume();
2319
+ outputs.onSuccess('已恢复语音播放');
2320
+ }
2321
+ else {
2322
+ outputs.onFail('当前环境不支持恢复功能');
2323
+ }
2324
+ }
2325
+ catch (error) {
2326
+ console.error('恢复语音失败:', error);
2327
+ outputs.onFail((error === null || error === void 0 ? void 0 : error.message) || '恢复语音失败');
2328
+ }
2329
+ });
2330
+ };
2331
+
2332
+ // 防抖函数实现
2333
+ function debounce(func, delay, options = {}) {
2334
+ let timeoutId = null;
2335
+ let lastExecTime = 0;
2336
+ const { leading = false, trailing = true } = options;
2337
+ return function (...args) {
2338
+ const currentTime = Date.now();
2339
+ if (!timeoutId && leading) {
2340
+ func.apply(null, args);
2341
+ lastExecTime = currentTime;
2342
+ }
2343
+ if (timeoutId) {
2344
+ clearTimeout(timeoutId);
2345
+ }
2346
+ timeoutId = setTimeout(() => {
2347
+ if (trailing && (!leading || currentTime - lastExecTime >= delay)) {
2348
+ func.apply(null, args);
2349
+ }
2350
+ timeoutId = null;
2351
+ }, delay);
2352
+ };
2353
+ }
2354
+ var _TimerDebounce = (context) => {
2355
+ var _a;
2356
+ const data = context.data;
2357
+ const inputs = context.inputs;
2358
+ const outputs = context.outputs;
2359
+ let debouncedFn = null;
2360
+ (_a = inputs.debounce) === null || _a === void 0 ? void 0 : _a.call(inputs, (val) => {
2361
+ try {
2362
+ const delay = (val === null || val === void 0 ? void 0 : val.delay) || data.delay || 300;
2363
+ const leading = (val === null || val === void 0 ? void 0 : val.leading) !== undefined ? val.leading : data.leading || false;
2364
+ const trailing = (val === null || val === void 0 ? void 0 : val.trailing) !== undefined ? val.trailing : data.trailing || true;
2365
+ if (!debouncedFn) {
2366
+ debouncedFn = debounce(() => {
2367
+ outputs.onExecute({ delay, leading, trailing, timestamp: Date.now() });
2368
+ }, delay, { leading, trailing });
2369
+ }
2370
+ // 执行防抖函数
2371
+ debouncedFn();
2372
+ outputs.onComplete({ delay, leading, trailing });
2373
+ }
2374
+ catch (error) {
2375
+ console.error('防抖执行失败:', error);
2376
+ }
2377
+ });
2378
+ };
2379
+
2380
+ var _TimerDelay = (context) => {
2381
+ var _a, _b, _c;
2382
+ const data = context.data;
2383
+ const inputs = context.inputs;
2384
+ const outputs = context.outputs;
2385
+ let timeoutId = null;
2386
+ const inputPins = new Set(Object.keys(inputs));
2387
+ const outputPins = new Set(Object.keys(outputs));
2388
+ const hasIn = (pin) => inputPins.has(pin);
2389
+ const hasOut = (pin) => outputPins.has(pin);
2390
+ const clear = () => {
2391
+ if (timeoutId) {
2392
+ clearTimeout(timeoutId);
2393
+ timeoutId = null;
2394
+ }
2395
+ };
2396
+ // 兼容:inputs.trigger(payload) -> 延迟后 outputs.trigger(payload)
2397
+ if (hasIn("trigger"))
2398
+ (_a = inputs.trigger) === null || _a === void 0 ? void 0 : _a.call(inputs, (payload) => {
2399
+ var _a;
2400
+ try {
2401
+ // 允许 payload 自带 delay 覆盖;否则用 data.delay;再否则 1000
2402
+ const delay = (payload === null || payload === void 0 ? void 0 : payload.delay) || data.delay || 1000;
2403
+ clear();
2404
+ (_a = outputs.onStart) === null || _a === void 0 ? void 0 : _a.call(outputs, { delay, timestamp: Date.now() });
2405
+ timeoutId = setTimeout(() => {
2406
+ var _a, _b;
2407
+ if (hasOut("trigger"))
2408
+ (_a = outputs.trigger) === null || _a === void 0 ? void 0 : _a.call(outputs, payload);
2409
+ (_b = outputs.onExecute) === null || _b === void 0 ? void 0 : _b.call(outputs, { delay, timestamp: Date.now() });
2410
+ timeoutId = null;
2411
+ }, delay);
2412
+ }
2413
+ catch (error) {
2414
+ console.error('延迟执行失败:', error);
2415
+ clear();
2416
+ }
2417
+ });
2418
+ if (hasIn("delay"))
2419
+ (_b = inputs.delay) === null || _b === void 0 ? void 0 : _b.call(inputs, (val) => {
2420
+ try {
2421
+ const delay = (val === null || val === void 0 ? void 0 : val.delay) || data.delay || 1000;
2422
+ clear();
2423
+ outputs.onStart({ delay, timestamp: Date.now() });
2424
+ timeoutId = setTimeout(() => {
2425
+ outputs.onExecute({ delay, timestamp: Date.now() });
2426
+ timeoutId = null;
2427
+ }, delay);
2428
+ }
2429
+ catch (error) {
2430
+ console.error('延迟执行失败:', error);
2431
+ clear();
2432
+ }
2433
+ });
2434
+ if (hasIn("cancel"))
2435
+ (_c = inputs.cancel) === null || _c === void 0 ? void 0 : _c.call(inputs, () => {
2436
+ try {
2437
+ if (timeoutId) {
2438
+ clear();
2439
+ outputs.onCancel('延迟任务已取消');
2440
+ }
2441
+ else {
2442
+ outputs.onCancel('没有正在执行的延迟任务');
2443
+ }
2444
+ }
2445
+ catch (error) {
2446
+ console.error('取消延迟失败:', error);
2447
+ }
2448
+ });
2449
+ };
2450
+
2451
+ // 节流函数实现
2452
+ function throttle(func, delay, options = {}) {
2453
+ let timeoutId = null;
2454
+ let lastExecTime = 0;
2455
+ const { leading = true, trailing = true } = options;
2456
+ return function (...args) {
2457
+ const currentTime = Date.now();
2458
+ if (currentTime - lastExecTime > delay) {
2459
+ if (leading) {
2460
+ func.apply(null, args);
2461
+ lastExecTime = currentTime;
2462
+ }
2463
+ if (timeoutId) {
2464
+ clearTimeout(timeoutId);
2465
+ timeoutId = null;
2466
+ }
2467
+ }
2468
+ else if (trailing && !timeoutId) {
2469
+ timeoutId = setTimeout(() => {
2470
+ func.apply(null, args);
2471
+ lastExecTime = Date.now();
2472
+ timeoutId = null;
2473
+ }, delay - (currentTime - lastExecTime));
2474
+ }
2475
+ };
2476
+ }
2477
+ var _TimerThrottle = (context) => {
2478
+ var _a;
2479
+ const data = context.data;
2480
+ const inputs = context.inputs;
2481
+ const outputs = context.outputs;
2482
+ let throttledFn = null;
2483
+ (_a = inputs.throttle) === null || _a === void 0 ? void 0 : _a.call(inputs, (val) => {
2484
+ try {
2485
+ const interval = (val === null || val === void 0 ? void 0 : val.interval) || data.interval || 1000;
2486
+ const leading = (val === null || val === void 0 ? void 0 : val.leading) !== undefined ? val.leading : data.leading || true;
2487
+ const trailing = (val === null || val === void 0 ? void 0 : val.trailing) !== undefined ? val.trailing : data.trailing || true;
2488
+ if (!throttledFn) {
2489
+ throttledFn = throttle(() => {
2490
+ outputs.onExecute({ interval, leading, trailing, timestamp: Date.now() });
2491
+ }, interval, { leading, trailing });
2492
+ }
2493
+ // 执行节流函数
2494
+ throttledFn();
2495
+ outputs.onComplete({ interval, leading, trailing });
2496
+ }
2497
+ catch (error) {
2498
+ console.error('节流执行失败:', error);
2499
+ }
2500
+ });
2501
+ };
2502
+
2503
+ export { PopupRenderer, SUBJECT_SUBSCRIBE, SUBJECT_VALUE, ScopedComContextProvider, SlotProvider, WithCom, WithWrapper, closeActivePopupRouter, createFx, createJSHandle, createVariable, deepProxy, merge, _AesEncode as mybricks_taro_aesEncode, _BackTo as mybricks_taro_backTo, _CallPhone as mybricks_taro_callPhone, _ChooseFile as mybricks_taro_chooseFile, _ChooseMedia as mybricks_taro_chooseMedia, _Connector as mybricks_taro_connector, _ConnectorGlobalHeaders as mybricks_taro_connectorGlobalHeaders, _Format as mybricks_taro_format, _GetLocation as mybricks_taro_getLocation, _GetStorage as mybricks_taro_getStorage, _GetSystemInfo as mybricks_taro_getSystemInfo, _Modal as mybricks_taro_modal, _OpenCamera as mybricks_taro_openCamera, _OpenPetalMap as mybricks_taro_openPetalMap, _OpenUrl as mybricks_taro_openUrl, _RemoveStorage as mybricks_taro_removeStorage, _Router as mybricks_taro_router, _ScanQrcode as mybricks_taro_scanQrcode, _SetStorage as mybricks_taro_setStorage, _Share as mybricks_taro_share, _ShowToast as mybricks_taro_showToast, _TextToSpeech as mybricks_taro_textToSpeech, _TimerDebounce as mybricks_taro_timerDebounce, _TimerDelay as mybricks_taro_timerDelay, _TimerThrottle as mybricks_taro_timerThrottle, _Vibrate as mybricks_taro_vibrate, pageRouter, popupRouter, router, subscribePopupRouter, useAppContext, useAppCreateContext, useBindEvents, useBindInputs, useEnhancedSlots, useModel, useResolvedParentSlot };
2504
+ //# sourceMappingURL=index.esm.js.map