clickgo 3.1.2-dev11 → 3.1.3-dev12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (103) hide show
  1. package/dist/app/demo/app.js +0 -73
  2. package/dist/app/demo/config.json +109 -0
  3. package/dist/app/demo/form/control/button/button.js +12 -11
  4. package/dist/app/demo/form/control/button/button.xml +6 -6
  5. package/dist/app/demo/form/control/check/check.js +14 -10
  6. package/dist/app/demo/form/control/file/file.js +15 -13
  7. package/dist/app/demo/form/control/{overflow/overflow.css → flow/flow.css} +0 -0
  8. package/dist/app/demo/form/control/flow/flow.js +64 -0
  9. package/dist/app/demo/form/control/{overflow/overflow.scss → flow/flow.scss} +0 -0
  10. package/dist/app/demo/form/control/flow/flow.xml +101 -0
  11. package/dist/app/demo/form/control/form/form.js +1 -1
  12. package/dist/app/demo/form/control/form/form.xml +3 -3
  13. package/dist/app/demo/form/control/img/img.xml +2 -2
  14. package/dist/app/demo/form/control/list/list.js +95 -75
  15. package/dist/app/demo/form/control/list/list.xml +15 -11
  16. package/dist/app/demo/form/control/marquee/marquee.js +12 -10
  17. package/dist/app/demo/form/control/menu/menu.js +10 -6
  18. package/dist/app/demo/form/control/monaco/monaco.js +50 -60
  19. package/dist/app/demo/form/control/monaco/monaco.xml +6 -5
  20. package/dist/app/demo/form/control/property/property.js +131 -127
  21. package/dist/app/demo/form/control/radio/radio.js +9 -5
  22. package/dist/app/demo/form/control/scroll/scroll.js +16 -12
  23. package/dist/app/demo/form/control/scroll/scroll.xml +10 -10
  24. package/dist/app/demo/form/control/select/select.js +132 -71
  25. package/dist/app/demo/form/control/select/select.xml +69 -67
  26. package/dist/app/demo/form/control/tab/tab.js +21 -20
  27. package/dist/app/demo/form/control/tab/tab.xml +2 -2
  28. package/dist/app/demo/form/control/text/text.js +53 -45
  29. package/dist/app/demo/form/control/text/text.xml +3 -3
  30. package/dist/app/demo/form/control/{greatview/greatview.css → vflow/vflow.css} +0 -0
  31. package/dist/app/demo/form/control/vflow/vflow.js +79 -0
  32. package/dist/app/demo/form/control/{greatview/greatview.scss → vflow/vflow.scss} +0 -0
  33. package/dist/app/demo/form/control/{greatview/greatview.xml → vflow/vflow.xml} +25 -25
  34. package/dist/app/demo/form/event/form/form.js +58 -56
  35. package/dist/app/demo/form/event/form/form.xml +3 -3
  36. package/dist/app/demo/form/event/screen/screen.js +30 -28
  37. package/dist/app/demo/form/event/screen/screen.xml +2 -2
  38. package/dist/app/demo/form/event/task/task.js +31 -31
  39. package/dist/app/demo/form/event/task/task.xml +3 -3
  40. package/dist/app/demo/form/main.js +161 -5
  41. package/dist/app/demo/form/main.xml +36 -35
  42. package/dist/app/demo/form/method/aform/aform.xml +3 -2
  43. package/dist/app/demo/form/method/core/core.js +11 -8
  44. package/dist/app/demo/form/method/core/core.xml +2 -1
  45. package/dist/app/demo/form/method/dom/dom.js +91 -99
  46. package/dist/app/demo/form/method/dom/dom.xml +6 -7
  47. package/dist/app/demo/form/method/form/form.js +8 -8
  48. package/dist/app/demo/form/method/form/form.xml +4 -4
  49. package/dist/app/demo/form/method/fs/fs.js +34 -33
  50. package/dist/app/demo/form/method/fs/fs.xml +1 -1
  51. package/dist/app/demo/form/method/fs/text.js +12 -12
  52. package/dist/app/demo/form/method/native/native.js +50 -0
  53. package/dist/app/demo/form/method/native/native.xml +12 -0
  54. package/dist/app/demo/form/method/system/system.js +50 -0
  55. package/dist/app/demo/form/method/system/system.xml +11 -0
  56. package/dist/app/demo/form/method/task/task.js +59 -61
  57. package/dist/app/demo/form/method/task/task.xml +4 -6
  58. package/dist/app/demo/form/method/theme/theme.js +14 -14
  59. package/dist/app/demo/form/method/tool/tool.js +29 -28
  60. package/dist/app/demo/form/method/tool/tool.xml +3 -3
  61. package/dist/app/demo/form/method/zip/zip.js +46 -41
  62. package/dist/app/demo/form/method/zip/zip.xml +1 -1
  63. package/dist/app/task/app.js +0 -25
  64. package/dist/app/task/config.json +29 -0
  65. package/dist/app/task/form/bar/bar.js +1 -1
  66. package/dist/app/task/form/bar/bar.xml +1 -1
  67. package/dist/clickgo.js +1 -1
  68. package/dist/clickgo.ts +1 -1
  69. package/dist/control/common.cgc +0 -0
  70. package/dist/control/form.cgc +0 -0
  71. package/dist/control/monaco.cgc +0 -0
  72. package/dist/control/property.cgc +0 -0
  73. package/dist/control/task.cgc +0 -0
  74. package/dist/global.css +1 -1
  75. package/dist/index.js +3 -3
  76. package/dist/index.ts +3 -3
  77. package/dist/lib/control.js +70 -104
  78. package/dist/lib/control.ts +97 -123
  79. package/dist/lib/core.js +108 -252
  80. package/dist/lib/core.ts +122 -268
  81. package/dist/lib/dom.js +564 -483
  82. package/dist/lib/dom.ts +703 -546
  83. package/dist/lib/form.js +146 -138
  84. package/dist/lib/form.ts +108 -86
  85. package/dist/lib/fs.js +1 -1
  86. package/dist/lib/fs.ts +1 -1
  87. package/dist/lib/native.js +135 -8
  88. package/dist/lib/native.ts +175 -11
  89. package/dist/lib/task.js +294 -158
  90. package/dist/lib/task.ts +326 -172
  91. package/dist/lib/tool.js +48 -1
  92. package/dist/lib/tool.ts +61 -0
  93. package/dist/lib/zip.ts +2 -0
  94. package/dist/theme/familiar.cgt +0 -0
  95. package/package.json +1 -1
  96. package/types/index.d.ts +23 -24
  97. package/dist/app/demo/form/control/greatview/greatview.js +0 -92
  98. package/dist/app/demo/form/control/overflow/overflow.js +0 -70
  99. package/dist/app/demo/form/control/overflow/overflow.xml +0 -98
  100. package/dist/app/demo/form/control/view/view.css +0 -1
  101. package/dist/app/demo/form/control/view/view.js +0 -73
  102. package/dist/app/demo/form/control/view/view.scss +0 -18
  103. package/dist/app/demo/form/control/view/view.xml +0 -94
package/dist/lib/task.ts CHANGED
@@ -21,6 +21,7 @@ import * as tool from './tool';
21
21
  import * as form from './form';
22
22
  import * as control from './control';
23
23
  import * as fs from './fs';
24
+ import * as theme from './theme';
24
25
  import * as native from './native';
25
26
 
26
27
  /** --- 当前运行的程序,App 模式下无效 --- */
@@ -29,6 +30,22 @@ export const list: Record<number, types.ITask> = {};
29
30
  /** --- 最后一个 task id,App 模式下无效 --- */
30
31
  export let lastId: number = 0;
31
32
 
33
+ /** --- 当前有焦点的任务 ID --- */
34
+ let focusId: number | null = null;
35
+
36
+ /**
37
+ * --- 设置 task focus id ---
38
+ * @param id id 或 null
39
+ */
40
+ export function setFocus(id?: number): void {
41
+ focusId = id ?? null;
42
+ }
43
+
44
+ /** --- 获取当前有焦点的任务 ID --- */
45
+ export function getFocus(): number | null {
46
+ return focusId;
47
+ }
48
+
32
49
  /** --- task lib 用到的语言包 --- */
33
50
  const localeData: Record<string, {
34
51
  'loading': string;
@@ -54,7 +71,7 @@ const frameMaps: Record<string, number> = {};
54
71
  /**
55
72
  * --- 创建 frame 监听,formId 存在则为窗体范围,否则为任务级范围 ---
56
73
  * @param fun 监听回调
57
- * @param opt 选项,count:执行次数,默认无限次,taskId:APP模式下无效,formId:APP模式下无效
74
+ * @param opt 选项,count:执行次数,默认无限次,formId:限定在当前任务的某个窗体,taskId:APP模式下无效
58
75
  */
59
76
  export function onFrame(fun: () => void | Promise<void>, opt: {
60
77
  'count'?: number;
@@ -167,7 +184,7 @@ export function get(tid: number): types.ITaskInfo | null {
167
184
  return null;
168
185
  }
169
186
  return {
170
- 'name': list[tid].config.name,
187
+ 'name': list[tid].app.config.name,
171
188
  'locale': list[tid].locale.lang,
172
189
  'customTheme': list[tid].customTheme,
173
190
  'formCount': Object.keys(list[tid].forms).length,
@@ -185,7 +202,7 @@ export function getList(): Record<string, types.ITaskInfo> {
185
202
  for (const tid in list) {
186
203
  const item = list[tid];
187
204
  rtn[tid] = {
188
- 'name': item.config.name,
205
+ 'name': item.app.config.name,
189
206
  'locale': item.locale.lang,
190
207
  'customTheme': item.customTheme,
191
208
  'formCount': Object.keys(item.forms).length,
@@ -233,33 +250,46 @@ export async function run(url: string, opt: types.ITaskRunOptions = {}): Promise
233
250
  'current': ntask ? ntask.current : undefined,
234
251
  'progress': opt.progress
235
252
  });
236
- if (!app) {
237
- // --- fetch 失败,则返回错误,隐藏 notify ---
238
- if (notifyId) {
239
- setTimeout(function(): void {
240
- form.hideNotify(notifyId);
241
- }, 2000);
242
- }
243
- return -1;
244
- }
245
- if (notifyId && !app.net) {
246
- // --- 仅 app 模式隐藏,net 模式还要在 config 当中加载 xml 等非 js 资源文件 ---
253
+ // --- 无论是否成功,都可以先隐藏 notify 了 ---
254
+ if (notifyId) {
247
255
  setTimeout(function(): void {
248
256
  form.hideNotify(notifyId);
249
257
  }, 2000);
250
258
  }
259
+ if (!app) {
260
+ return -1;
261
+ }
251
262
  // --- 申请任务ID ---
252
263
  const taskId = ++lastId;
253
264
  // --- 注入的参数,屏蔽浏览器全局对象,注入新的对象 ---
254
265
  /** --- 不屏蔽的全局对象 --- */
255
- const unblock = opt.unblock ?? [];
266
+ const unblock = opt.unblock ? tool.clone(opt.unblock) : [];
267
+ const unblockSys = [
268
+ 'require',
269
+ '__awaiter', 'eval', 'Math', 'Array', 'Blob', 'Error', 'Infinity', 'parseInt', 'parseFloat', 'Promise', 'Date', 'JSON', 'fetch'
270
+ ];
271
+ for (const name of unblockSys) {
272
+ if (unblock.includes(name)) {
273
+ continue;
274
+ }
275
+ unblock.push(name);
276
+ }
256
277
  /** --- 最终注入的对象 --- */
257
278
  const invoke: Record<string, any> = {};
258
279
  if (!unblock.includes('window')) {
259
- invoke.window = undefined;
280
+ invoke.window = {};
281
+ for (const name of unblock) {
282
+ if (window[name] === undefined) {
283
+ continue;
284
+ }
285
+ invoke.window[name] = window[name];
286
+ }
260
287
  }
261
288
  const ks = Object.getOwnPropertyNames(window);
262
289
  for (const k of ks) {
290
+ if (k.includes('window')) {
291
+ continue;
292
+ }
263
293
  if (k.includes('Event')) {
264
294
  continue;
265
295
  }
@@ -269,11 +299,6 @@ export async function run(url: string, opt: types.ITaskRunOptions = {}): Promise
269
299
  if (/^[0-9]+$/.test(k)) {
270
300
  continue;
271
301
  }
272
- if ([
273
- 'require',
274
- '__awaiter', 'eval', 'Math', 'Array', 'Blob', 'Infinity', 'parseInt', 'parseFloat', 'Promise', 'Date', 'JSON', 'fetch'].includes(k)) {
275
- continue;
276
- }
277
302
  if (unblock.includes(k)) {
278
303
  continue;
279
304
  }
@@ -361,101 +386,109 @@ export async function run(url: string, opt: types.ITaskRunOptions = {}): Promise
361
386
  getCdn: function() {
362
387
  return core.getCdn();
363
388
  },
364
- initModules: function(names: string | string[]): Promise<number> {
365
- return clickgo.core.initModules(names);
366
- },
367
389
  getModule: function(name: string): null | any {
368
- return clickgo.core.getModule(name);
390
+ return core.getModule(name);
369
391
  },
370
392
  readApp: function(blob: Blob): Promise<false | types.IApp> {
371
- return clickgo.core.readApp(blob);
393
+ return core.readApp(blob);
372
394
  },
373
395
  getAvailArea: function(): types.IAvailArea {
374
- return clickgo.core.getAvailArea();
396
+ return core.getAvailArea();
375
397
  }
376
398
  },
377
399
  'dom': {
378
400
  setGlobalCursor: function(type?: string): void {
379
- clickgo.dom.setGlobalCursor(type);
401
+ dom.setGlobalCursor(type);
380
402
  },
381
403
  hasTouchButMouse: function(e: MouseEvent | TouchEvent | PointerEvent): boolean {
382
- return clickgo.dom.hasTouchButMouse(e);
404
+ return dom.hasTouchButMouse(e);
383
405
  },
384
406
  getStyleCount: function(taskId: number, type: 'theme' | 'control' | 'form'): number {
385
- return clickgo.dom.getStyleCount(taskId, type);
386
- },
387
- getSize: function(el: HTMLElement): types.IDomSize {
388
- return clickgo.dom.getSize(el);
407
+ return dom.getStyleCount(taskId, type);
389
408
  },
390
409
  watchSize: function(
391
410
  el: HTMLElement,
392
- cb: (size: types.IDomSize) => Promise<void> | void,
411
+ cb: () => void | Promise<void>,
393
412
  immediate: boolean = false
394
- ): types.IDomSize {
395
- return clickgo.dom.watchSize(el, cb, immediate, taskId);
413
+ ): boolean {
414
+ return dom.watchSize(el, cb, immediate, taskId);
396
415
  },
397
416
  unwatchSize: function(el: HTMLElement): void {
398
- clickgo.dom.unwatchSize(el, taskId);
417
+ dom.unwatchSize(el, taskId);
399
418
  },
400
- clearWatchSize(): void {
401
- clickgo.dom.clearWatchSize(taskId);
419
+ isWatchSize(el: HTMLElement): boolean {
420
+ return dom.isWatchSize(el);
402
421
  },
403
422
  watch: function(el: HTMLElement, cb: () => void, mode: 'child' | 'childsub' | 'style' | 'default' = 'default', immediate: boolean = false): void {
404
- clickgo.dom.watch(el, cb, mode, immediate, taskId);
423
+ dom.watch(el, cb, mode, immediate, taskId);
405
424
  },
406
425
  unwatch: function(el: HTMLElement): void {
407
- clickgo.dom.unwatch(el, taskId);
426
+ dom.unwatch(el, taskId);
408
427
  },
409
- clearWatch: function(): void {
410
- clickgo.dom.clearWatch(taskId);
428
+ isWatch(el: HTMLElement): boolean {
429
+ return dom.isWatch(el);
411
430
  },
412
431
  watchStyle: function(
413
432
  el: HTMLElement,
414
433
  name: string | string[],
415
- cb: (name: string, value: string) => void,
434
+ cb: (name: string, value: string, old: string) => void,
416
435
  immediate: boolean = false
417
436
  ): void {
418
- clickgo.dom.watchStyle(el, name, cb, immediate);
437
+ dom.watchStyle(el, name, cb, immediate);
419
438
  },
420
439
  isWatchStyle: function(el: HTMLElement): boolean {
421
- return clickgo.dom.isWatchStyle(el);
440
+ return dom.isWatchStyle(el);
441
+ },
442
+ watchProperty(
443
+ el: HTMLElement,
444
+ name: string | string[],
445
+ cb: (name: string, value: string) => void,
446
+ immediate: boolean = false
447
+ ): void {
448
+ dom.watchProperty(el, name, cb, immediate);
449
+ },
450
+ isWatchProperty(el: HTMLElement): boolean {
451
+ return dom.isWatchProperty(el);
452
+ },
453
+ bindClick(e: MouseEvent | TouchEvent, handler: () => void): void {
454
+ dom.bindClick(e, handler);
422
455
  },
423
456
  bindDown: function(oe: MouseEvent | TouchEvent, opt: types.IBindDownOptions) {
424
- clickgo.dom.bindDown(oe, opt);
457
+ dom.bindDown(oe, opt);
425
458
  },
426
- bindGesture: function(e: MouseEvent | TouchEvent | WheelEvent | { 'x'?: number; 'y'?: number; }, opt: types.IBindGestureOptions): void {
427
- clickgo.dom.bindGesture(e, opt);
459
+ bindGesture: function(oe: MouseEvent | TouchEvent | WheelEvent, before: (e: MouseEvent | TouchEvent | WheelEvent, dir: 'top' | 'right' | 'bottom' | 'left') => boolean, handler: (dir: 'top' | 'right' | 'bottom' | 'left') => void): void {
460
+ dom.bindGesture(oe, before, handler);
428
461
  },
429
462
  bindLong: function(
430
463
  e: MouseEvent | TouchEvent,
431
464
  long: (e: MouseEvent | TouchEvent) => void | Promise<void>
432
465
  ): void {
433
- clickgo.dom.bindLong(e, long);
466
+ dom.bindLong(e, long);
434
467
  },
435
468
  bindDrag: function(e: MouseEvent | TouchEvent, opt: { 'el': HTMLElement; 'data'?: any; }): void {
436
- clickgo.dom.bindDrag(e, opt);
469
+ dom.bindDrag(e, opt);
437
470
  },
438
- 'is': clickgo.dom.is,
471
+ 'is': dom.is,
439
472
  bindMove: function(e: MouseEvent | TouchEvent, opt: types.IBindMoveOptions): types.IBindMoveResult {
440
- return clickgo.dom.bindMove(e, opt);
473
+ return dom.bindMove(e, opt);
441
474
  },
442
475
  bindResize: function(e: MouseEvent | TouchEvent, opt: types.IBindResizeOptions): void {
443
- clickgo.dom.bindResize(e, opt);
476
+ dom.bindResize(e, opt);
444
477
  },
445
478
  findParentByData: function(el: HTMLElement, name: string): HTMLElement | null {
446
- return clickgo.dom.findParentByData(el, name);
479
+ return dom.findParentByData(el, name);
447
480
  },
448
481
  findParentByClass: function(el: HTMLElement, name: string): HTMLElement | null {
449
- return clickgo.dom.findParentByClass(el, name);
482
+ return dom.findParentByClass(el, name);
450
483
  },
451
484
  siblings: function(el: HTMLElement): HTMLElement[] {
452
- return clickgo.dom.siblings(el);
485
+ return dom.siblings(el);
453
486
  },
454
487
  siblingsData: function(el: HTMLElement, name: string): HTMLElement[] {
455
- return clickgo.dom.siblingsData(el, name);
488
+ return dom.siblingsData(el, name);
456
489
  },
457
490
  fullscreen: function(): boolean {
458
- return clickgo.dom.fullscreen();
491
+ return dom.fullscreen();
459
492
  }
460
493
  },
461
494
  'form': {
@@ -465,76 +498,79 @@ export async function run(url: string, opt: types.ITaskRunOptions = {}): Promise
465
498
  }
466
499
  },
467
500
  min: function(fid: number): boolean {
468
- return clickgo.form.min(fid);
501
+ return form.min(fid);
469
502
  },
470
503
  max: function max(fid: number): boolean {
471
- return clickgo.form.max(fid);
504
+ return form.max(fid);
472
505
  },
473
506
  close: function(fid: number): boolean {
474
- return clickgo.form.close(fid);
507
+ return form.close(fid);
475
508
  },
476
509
  bindResize: function(e: MouseEvent | TouchEvent, border: types.TDomBorder): void {
477
- clickgo.form.bindResize(e, border);
510
+ form.bindResize(e, border);
478
511
  },
479
512
  bindDrag: function(e: MouseEvent | TouchEvent): void {
480
- clickgo.form.bindDrag(e);
513
+ form.bindDrag(e);
481
514
  },
482
515
  getTaskId: function(fid: number): number {
483
- return clickgo.form.getTaskId(fid);
516
+ return form.getTaskId(fid);
484
517
  },
485
518
  get: function(fid: number): types.IFormInfo | null {
486
- return clickgo.form.get(fid);
519
+ return form.get(fid);
487
520
  },
488
521
  getList: function(tid: number): Record<string, types.IFormInfo> {
489
- return clickgo.form.getList(tid);
522
+ return form.getList(tid);
523
+ },
524
+ getFocus: function(): number | null {
525
+ return form.getFocus();
490
526
  },
491
527
  changeFocus: function(fid: number = 0): void {
492
- clickgo.form.changeFocus(fid);
528
+ form.changeFocus(fid);
493
529
  },
494
530
  getMaxZIndexID: function(out?: {
495
531
  'taskIds'?: number[];
496
532
  'formIds'?: number[];
497
533
  }): number | null {
498
- return clickgo.form.getMaxZIndexID(out);
534
+ return form.getMaxZIndexID(out);
499
535
  },
500
536
  getRectByBorder: function(border: types.TDomBorder): { 'width': number; 'height': number; 'left': number; 'top': number; } {
501
- return clickgo.form.getRectByBorder(border);
537
+ return form.getRectByBorder(border);
502
538
  },
503
539
  showCircular: function(x: number, y: number): void {
504
- clickgo.form.showCircular(x, y);
540
+ form.showCircular(x, y);
505
541
  },
506
542
  moveRectangle: function(border: types.TDomBorder): void {
507
- clickgo.form.moveRectangle(border);
543
+ form.moveRectangle(border);
508
544
  },
509
545
  showRectangle: function(x: number, y: number, border: types.TDomBorder): void {
510
- clickgo.form.showRectangle(x, y, border);
546
+ form.showRectangle(x, y, border);
511
547
  },
512
548
  hideRectangle: function(): void {
513
- clickgo.form.hideRectangle();
549
+ form.hideRectangle();
514
550
  },
515
551
  showDrag: function(): void {
516
- clickgo.form.showDrag();
552
+ form.showDrag();
517
553
  },
518
554
  moveDrag: function(opt: types.IMoveDragOptions): void {
519
- clickgo.form.moveDrag(opt);
555
+ form.moveDrag(opt);
520
556
  },
521
557
  hideDrag: function(): void {
522
- clickgo.form.hideDrag();
558
+ form.hideDrag();
523
559
  },
524
560
  notify: function(opt: types.INotifyOptions): number {
525
- return clickgo.form.notify(opt);
561
+ return form.notify(opt);
526
562
  },
527
563
  notifyProgress: function(notifyId: number, per: number): void {
528
- clickgo.form.notifyProgress(notifyId, per);
564
+ form.notifyProgress(notifyId, per);
529
565
  },
530
566
  hideNotify: function(notifyId: number): void {
531
- clickgo.form.hideNotify(notifyId);
567
+ form.hideNotify(notifyId);
532
568
  },
533
569
  showPop: function(el: HTMLElement, pop: HTMLElement | undefined, direction: 'h' | 'v' | MouseEvent | TouchEvent | { x: number; y: number; }, opt: { 'size'?: { width?: number; height?: number; }; 'null'?: boolean; } = {}): void {
534
- clickgo.form.showPop(el, pop, direction, opt);
570
+ form.showPop(el, pop, direction, opt);
535
571
  },
536
572
  hidePop: function(pop?: HTMLElement): void {
537
- clickgo.form.hidePop(pop);
573
+ form.hidePop(pop);
538
574
  },
539
575
  dialog: function(opt: string | types.IFormDialogOptions): Promise<string> {
540
576
  if (typeof opt === 'string') {
@@ -543,7 +579,7 @@ export async function run(url: string, opt: types.ITaskRunOptions = {}): Promise
543
579
  };
544
580
  }
545
581
  opt.taskId = taskId;
546
- return clickgo.form.dialog(opt);
582
+ return form.dialog(opt);
547
583
  },
548
584
  confirm: function(opt: string | types.IFormConfirmOptions): Promise<boolean | number> {
549
585
  if (typeof opt === 'string') {
@@ -552,16 +588,16 @@ export async function run(url: string, opt: types.ITaskRunOptions = {}): Promise
552
588
  };
553
589
  }
554
590
  opt.taskId = taskId;
555
- return clickgo.form.confirm(opt);
591
+ return form.confirm(opt);
556
592
  },
557
593
  flash: function(fid: number): void {
558
- clickgo.form.flash(fid, taskId);
594
+ form.flash(fid, taskId);
559
595
  },
560
596
  showLauncher: function(): void {
561
- clickgo.form.showLauncher();
597
+ form.showLauncher();
562
598
  },
563
599
  hideLauncher: function(): void {
564
- clickgo.form.hideLauncher();
600
+ form.hideLauncher();
565
601
  }
566
602
  },
567
603
  'fs': {
@@ -575,31 +611,31 @@ export async function run(url: string, opt: types.ITaskRunOptions = {}): Promise
575
611
  if (!options.current) {
576
612
  options.current = list[taskId].current;
577
613
  }
578
- return clickgo.fs.getContent(path, options);
614
+ return fs.getContent(path, options);
579
615
  },
580
616
  putContent: function(path: string, data: string | Buffer, options: any = {}) {
581
617
  if (!options.current) {
582
618
  options.current = list[taskId].current;
583
619
  }
584
- return clickgo.fs.putContent(path, data, options);
620
+ return fs.putContent(path, data, options);
585
621
  },
586
622
  readLink: function(path: string, options: any = {}): Promise<string | null> {
587
623
  if (!options.current) {
588
624
  options.current = list[taskId].current;
589
625
  }
590
- return clickgo.fs.readLink(path, options);
626
+ return fs.readLink(path, options);
591
627
  },
592
628
  symlink: function(fPath: string, linkPath: string, options: any = {}): Promise<boolean> {
593
629
  if (!options.current) {
594
630
  options.current = list[taskId].current;
595
631
  }
596
- return clickgo.fs.symlink(fPath, linkPath, options);
632
+ return fs.symlink(fPath, linkPath, options);
597
633
  },
598
634
  unlink: function(path: string, options: any = {}): Promise<boolean> {
599
635
  if (!options.current) {
600
636
  options.current = list[taskId].current;
601
637
  }
602
- return clickgo.fs.unlink(path, options);
638
+ return fs.unlink(path, options);
603
639
  },
604
640
  stats: function(path: string, options: any = {}): Promise<types.IStats | null> {
605
641
  if (!options.files) {
@@ -608,7 +644,7 @@ export async function run(url: string, opt: types.ITaskRunOptions = {}): Promise
608
644
  if (!options.current) {
609
645
  options.current = list[taskId].current;
610
646
  }
611
- return clickgo.fs.stats(path, options);
647
+ return fs.stats(path, options);
612
648
  },
613
649
  isDir: function(path: string, options: any = {}): Promise<types.IStats | false> {
614
650
  if (!options.files) {
@@ -617,7 +653,7 @@ export async function run(url: string, opt: types.ITaskRunOptions = {}): Promise
617
653
  if (!options.current) {
618
654
  options.current = list[taskId].current;
619
655
  }
620
- return clickgo.fs.isDir(path, options);
656
+ return fs.isDir(path, options);
621
657
  },
622
658
  isFile: function(path: string, options: any = {}): Promise<types.IStats | false> {
623
659
  if (!options.files) {
@@ -626,37 +662,37 @@ export async function run(url: string, opt: types.ITaskRunOptions = {}): Promise
626
662
  if (!options.current) {
627
663
  options.current = list[taskId].current;
628
664
  }
629
- return clickgo.fs.isFile(path, options);
665
+ return fs.isFile(path, options);
630
666
  },
631
667
  mkdir: function(path: string, mode?: number, options: any = {}): Promise<boolean> {
632
668
  if (!options.current) {
633
669
  options.current = list[taskId].current;
634
670
  }
635
- return clickgo.fs.mkdir(path, mode, options);
671
+ return fs.mkdir(path, mode, options);
636
672
  },
637
673
  rmdir: function(path: string, options: any = {}): Promise<boolean> {
638
674
  if (!options.current) {
639
675
  options.current = list[taskId].current;
640
676
  }
641
- return clickgo.fs.rmdir(path, options);
677
+ return fs.rmdir(path, options);
642
678
  },
643
679
  rmdirDeep: function(path: string, options: any = {}): Promise<boolean> {
644
680
  if (!options.current) {
645
681
  options.current = list[taskId].current;
646
682
  }
647
- return clickgo.fs.rmdirDeep(path, options);
683
+ return fs.rmdirDeep(path, options);
648
684
  },
649
685
  chmod: function(path: string, mod: string | number, options: any = {}): Promise<boolean> {
650
686
  if (!options.current) {
651
687
  options.current = list[taskId].current;
652
688
  }
653
- return clickgo.fs.chmod(path, mod, options);
689
+ return fs.chmod(path, mod, options);
654
690
  },
655
691
  rename(oldPath: string, newPath: string, options: any = {}): Promise<boolean> {
656
692
  if (!options.current) {
657
693
  options.current = list[taskId].current;
658
694
  }
659
- return clickgo.fs.rename(oldPath, newPath, options);
695
+ return fs.rename(oldPath, newPath, options);
660
696
  },
661
697
  readDir(path: string, options: any = {}): Promise<types.IDirent[]> {
662
698
  if (!options.files) {
@@ -665,79 +701,123 @@ export async function run(url: string, opt: types.ITaskRunOptions = {}): Promise
665
701
  if (!options.current) {
666
702
  options.current = list[taskId].current;
667
703
  }
668
- return clickgo.fs.readDir(path, options);
704
+ return fs.readDir(path, options);
669
705
  },
670
706
  copyFolder(from: string, to: string, options: any = {}): Promise<number> {
671
707
  if (!options.current) {
672
708
  options.current = list[taskId].current;
673
709
  }
674
- return clickgo.fs.copyFolder(from, to, options);
710
+ return fs.copyFolder(from, to, options);
675
711
  },
676
712
  copyFile(src: string, dest: string, options: any = {}): Promise<boolean> {
677
713
  if (!options.current) {
678
714
  options.current = list[taskId].current;
679
715
  }
680
- return clickgo.fs.copyFile(src, dest, options);
716
+ return fs.copyFile(src, dest, options);
681
717
  }
682
718
  },
683
719
  'native': {
684
- invoke: function(name: string, ...param: any[]): any {
685
- return clickgo.native.invoke(name, ...param);
720
+ on(
721
+ name: string,
722
+ handler: (...param: any[]) => any | Promise<any>,
723
+ once: boolean = false,
724
+ formId?: number
725
+ ): void {
726
+ native.on(name, handler, once, formId, taskId);
727
+ },
728
+ once(
729
+ name: string,
730
+ handler: (...param: any[]) => any | Promise<any>,
731
+ formId?: number
732
+ ): void {
733
+ native.once(name, handler, formId, taskId);
734
+ },
735
+ off(name: string, formId?: number): void {
736
+ native.off(name, formId, taskId);
737
+ },
738
+ clear(formId?: number, taskId?: number): void {
739
+ native.clear(formId, taskId);
686
740
  },
687
- max: function(): void {
688
- clickgo.native.max();
741
+ getListenerList(taskId?: number): Record<string, Record<string, Record<string, number>>> {
742
+ return native.getListenerList(taskId);
689
743
  },
690
- min: function(): void {
691
- clickgo.native.min();
744
+ invoke: function(name: string, ...param: any[]): Promise<any> {
745
+ return native.invoke(name, ...param);
692
746
  },
693
- restore: function(): void {
694
- clickgo.native.restore();
747
+ max: async function(): Promise<void> {
748
+ await native.max();
695
749
  },
696
- size: function(width: number, height: number): void {
697
- clickgo.native.size(width, height);
750
+ min: async function(): Promise<void> {
751
+ await native.min();
752
+ },
753
+ restore: async function(): Promise<void> {
754
+ await native.restore();
755
+ },
756
+ size: async function(width: number, height: number): Promise<void> {
757
+ await native.size(width, height);
758
+ },
759
+ ping: function(val: string): Promise<string> {
760
+ return native.ping(val);
761
+ },
762
+ isMax: function(): Promise<boolean> {
763
+ return native.isMax();
698
764
  }
699
765
  },
700
766
  'task': {
767
+ getFocus(): number | null {
768
+ return focusId;
769
+ },
701
770
  onFrame: function(fun: () => void | Promise<void>, opt: any = {}): number {
702
771
  opt.taskId = taskId;
703
- return clickgo.task.onFrame(fun, opt);
772
+ return onFrame(fun, opt);
704
773
  },
705
774
  offFrame: function(ft: number, opt: {
706
775
  'taskId'?: number;
707
776
  } = {}): void {
708
777
  opt.taskId = taskId;
709
- clickgo.task.offFrame(ft, opt);
778
+ offFrame(ft, opt);
710
779
  },
711
780
  get: function(tid: number): types.ITaskInfo | null {
712
- return clickgo.task.get(tid);
781
+ return get(tid);
713
782
  },
714
783
  getList: function(): Record<string, types.ITaskInfo> {
715
- return clickgo.task.getList();
784
+ return getList();
716
785
  },
717
786
  run: function(url: string, opt: types.ITaskRunOptions = {}): Promise<number> {
718
787
  opt.taskId = taskId;
719
- return clickgo.task.run(url, opt);
788
+ if (opt.unblock) {
789
+ const inUnblock: string[] = [];
790
+ // --- 只能解除屏蔽当前函数里面被解除的变量 ---
791
+ for (const item of opt.unblock) {
792
+ if (!unblock.includes(item)) {
793
+ continue;
794
+ }
795
+ inUnblock.push(item);
796
+ }
797
+ opt.unblock = inUnblock;
798
+ }
799
+ return run(url, opt);
720
800
  },
721
801
  end: function(tid: number): boolean {
722
- return clickgo.task.end(tid ?? taskId);
802
+ return end(tid ?? taskId);
723
803
  },
724
804
  loadLocaleData: function(lang: string, data: Record<string, any>, pre: string = ''): void {
725
- clickgo.task.loadLocaleData(lang, data, pre, taskId);
805
+ loadLocaleData(lang, data, pre, taskId);
726
806
  },
727
807
  loadLocale: function(lang: string, path: string): Promise<boolean> {
728
- return clickgo.task.loadLocale(lang, path, taskId);
808
+ return loadLocale(lang, path, taskId);
729
809
  },
730
810
  clearLocale: function(): void {
731
- clickgo.task.clearLocale(taskId);
811
+ clearLocale(taskId);
732
812
  },
733
813
  setLocale: function(lang: string, path: string): Promise<boolean> {
734
- return clickgo.task.setLocale(lang, path, taskId);
814
+ return setLocale(lang, path, taskId);
735
815
  },
736
816
  setLocaleLang: function(lang: string): void {
737
- clickgo.task.setLocaleLang(lang, taskId);
817
+ setLocaleLang(lang, taskId);
738
818
  },
739
819
  clearLocaleLang: function(): void {
740
- clickgo.task.clearLocaleLang(taskId);
820
+ clearLocaleLang(taskId);
741
821
  },
742
822
  createTimer: function(
743
823
  fun: () => void | Promise<void>,
@@ -745,20 +825,20 @@ export async function run(url: string, opt: types.ITaskRunOptions = {}): Promise
745
825
  opt: types.ICreateTimerOptions = {}
746
826
  ): number {
747
827
  opt.taskId = taskId;
748
- return clickgo.task.createTimer(fun, delay, opt);
828
+ return createTimer(fun, delay, opt);
749
829
  },
750
830
  removeTimer: function(timer: number): void {
751
- clickgo.task.removeTimer(timer, taskId);
831
+ removeTimer(timer, taskId);
752
832
  },
753
833
  sleep: function(fun: () => void | Promise<void>, delay: number): number {
754
- return clickgo.task.sleep(fun, delay, taskId);
834
+ return sleep(fun, delay, taskId);
755
835
  },
756
- systemTaskInfo: clickgo.task.systemTaskInfo,
836
+ 'systemTaskInfo': clickgo.task.systemTaskInfo,
757
837
  setSystem: function(fid: number): boolean {
758
- return clickgo.task.setSystem(fid, taskId);
838
+ return setSystem(fid, taskId);
759
839
  },
760
840
  clearSystem: function(): boolean {
761
- return clickgo.task.clearSystem(taskId);
841
+ return clearSystem(taskId);
762
842
  }
763
843
  },
764
844
  'theme': {
@@ -786,58 +866,67 @@ export async function run(url: string, opt: types.ITaskRunOptions = {}): Promise
786
866
  },
787
867
  'tool': {
788
868
  blob2ArrayBuffer: function(blob: Blob): Promise<ArrayBuffer> {
789
- return clickgo.tool.blob2ArrayBuffer(blob);
869
+ return tool.blob2ArrayBuffer(blob);
790
870
  },
791
871
  clone: function(obj: Record<string, any> | any[]): any[] | any {
792
- return clickgo.tool.clone(obj);
872
+ return tool.clone(obj);
793
873
  },
794
874
  sleep: function(ms: number = 0): Promise<boolean> {
795
- return clickgo.tool.sleep(ms);
875
+ return tool.sleep(ms);
876
+ },
877
+ nextFrame(): Promise<void> {
878
+ return tool.nextFrame();
879
+ },
880
+ sleepFrame(count: number): Promise<void> {
881
+ return tool.sleepFrame(count);
796
882
  },
797
883
  purify: function(text: string): string {
798
- return clickgo.tool.purify(text);
884
+ return tool.purify(text);
799
885
  },
800
886
  rand: function(min: number, max: number): number {
801
- return clickgo.tool.rand(min, max);
802
- },
803
- 'RANDOM_N': clickgo.tool.RANDOM_N,
804
- 'RANDOM_U': clickgo.tool.RANDOM_U,
805
- 'RANDOM_L': clickgo.tool.RANDOM_L,
806
- 'RANDOM_UN': clickgo.tool.RANDOM_UN,
807
- 'RANDOM_LN': clickgo.tool.RANDOM_LN,
808
- 'RANDOM_LU': clickgo.tool.RANDOM_LU,
809
- 'RANDOM_LUN': clickgo.tool.RANDOM_LUN,
810
- 'RANDOM_V': clickgo.tool.RANDOM_V,
811
- 'RANDOM_LUNS': clickgo.tool.RANDOM_LUNS,
812
- random: function(length: number = 8, source: string = clickgo.tool.RANDOM_LN, block: string = ''): string {
813
- return clickgo.tool.random(length, source, block);
887
+ return tool.rand(min, max);
888
+ },
889
+ 'RANDOM_N': tool.RANDOM_N,
890
+ 'RANDOM_U': tool.RANDOM_U,
891
+ 'RANDOM_L': tool.RANDOM_L,
892
+ 'RANDOM_UN': tool.RANDOM_UN,
893
+ 'RANDOM_LN': tool.RANDOM_LN,
894
+ 'RANDOM_LU': tool.RANDOM_LU,
895
+ 'RANDOM_LUN': tool.RANDOM_LUN,
896
+ 'RANDOM_V': tool.RANDOM_V,
897
+ 'RANDOM_LUNS': tool.RANDOM_LUNS,
898
+ random: function(length: number = 8, source: string = tool.RANDOM_LN, block: string = ''): string {
899
+ return tool.random(length, source, block);
814
900
  },
815
901
  getBoolean: function(param: boolean | string | number): boolean {
816
- return clickgo.tool.getBoolean(param);
902
+ return tool.getBoolean(param);
817
903
  },
818
904
  getNumber: function(param: string | number): number {
819
- return clickgo.tool.getNumber(param);
905
+ return tool.getNumber(param);
906
+ },
907
+ getArray(param: string | any[]): any[] {
908
+ return tool.getArray(param);
820
909
  },
821
910
  escapeHTML: function(html: string): string {
822
- return clickgo.tool.escapeHTML(html);
911
+ return tool.escapeHTML(html);
823
912
  },
824
913
  request: function(url: string, opt: types.IRequestOptions): Promise<null | any> {
825
- return clickgo.tool.request(url, opt);
914
+ return tool.request(url, opt);
826
915
  },
827
916
  parseUrl: function(url: string): ILoaderUrl {
828
- return clickgo.tool.parseUrl(url);
917
+ return tool.parseUrl(url);
829
918
  },
830
919
  urlResolve: function(from: string, to: string): string {
831
- return clickgo.tool.urlResolve(from, to);
920
+ return tool.urlResolve(from, to);
832
921
  },
833
922
  blob2Text: function(blob: Blob): Promise<string> {
834
- return clickgo.tool.blob2Text(blob);
923
+ return tool.blob2Text(blob);
835
924
  },
836
925
  blob2DataUrl: function(blob: Blob): Promise<string> {
837
- return clickgo.tool.blob2DataUrl(blob);
926
+ return tool.blob2DataUrl(blob);
838
927
  },
839
928
  execCommand: function(ac: string): void {
840
- clickgo.tool.execCommand(ac);
929
+ tool.execCommand(ac);
841
930
  }
842
931
  },
843
932
  'zip': {
@@ -869,12 +958,11 @@ export async function run(url: string, opt: types.ITaskRunOptions = {}): Promise
869
958
  const path = url;
870
959
  const lio = path.endsWith('.cga') ? path.lastIndexOf('/') : path.slice(0, -1).lastIndexOf('/');
871
960
  const current = path.slice(0, lio);
872
- // --- 创建任务对象 task.IRT ---
961
+ // --- 创建任务对象 ---
873
962
  list[taskId] = {
874
963
  'id': taskId,
875
964
  'app': app,
876
965
  // 'class': null,
877
- // 'config': {},
878
966
  'customTheme': false,
879
967
  'locale': clickgo.vue.reactive({
880
968
  'lang': '',
@@ -892,6 +980,30 @@ export async function run(url: string, opt: types.ITaskRunOptions = {}): Promise
892
980
  'timers': {},
893
981
  'invoke': invoke
894
982
  } as any;
983
+ // --- locale ---
984
+ if (app.config.locales) {
985
+ for (let path in app.config.locales) {
986
+ const locale = app.config.locales[path];
987
+ if (!path.endsWith('.json')) {
988
+ path += '.json';
989
+ }
990
+ const lcontent = await fs.getContent(path, {
991
+ 'encoding': 'utf8',
992
+ 'files': app.files,
993
+ 'current': current
994
+ });
995
+ if (!lcontent) {
996
+ continue;
997
+ }
998
+ try {
999
+ const data = JSON.parse(lcontent);
1000
+ loadLocaleData(locale, data, '', taskId);
1001
+ }
1002
+ catch {
1003
+ // --- 无所谓 ---
1004
+ }
1005
+ }
1006
+ }
895
1007
  let expo: any = [];
896
1008
  try {
897
1009
  expo = loader.require('/app.js', app.files, {
@@ -914,23 +1026,58 @@ export async function run(url: string, opt: types.ITaskRunOptions = {}): Promise
914
1026
  }
915
1027
  // --- 创建 Task 总 style ---
916
1028
  dom.createToStyleList(taskId);
1029
+ // --- 加载 control ---
1030
+ const r = await control.init(taskId, invoke);
1031
+ if (r < 0) {
1032
+ dom.removeFromStyleList(taskId);
1033
+ delete list[taskId];
1034
+ return -400 + r;
1035
+ }
1036
+ // --- 加载 theme ---
1037
+ if (app.config.themes?.length) {
1038
+ for (let path of app.config.themes) {
1039
+ path += '.cgt';
1040
+ path = tool.urlResolve('/', path);
1041
+ const file = await fs.getContent(path, {
1042
+ 'files': app.files,
1043
+ 'current': current
1044
+ });
1045
+ if (file && typeof file !== 'string') {
1046
+ const th = await theme.read(file);
1047
+ if (th) {
1048
+ await theme.load(th, taskId);
1049
+ }
1050
+ }
1051
+ }
1052
+ }
1053
+ else {
1054
+ // --- 加载全局主题 ---
1055
+ if (theme.global) {
1056
+ await theme.load(undefined, taskId);
1057
+ }
1058
+ }
1059
+ // --- 加载任务级全局样式 ---
1060
+ if (app.config.style) {
1061
+ const style = await fs.getContent(app.config.style + '.css', {
1062
+ 'encoding': 'utf8',
1063
+ 'files': app.files,
1064
+ 'current': current
1065
+ });
1066
+ if (style) {
1067
+ const r = tool.stylePrepend(style, 'cg-task' + taskId.toString() + '_');
1068
+ dom.pushStyle(taskId, await tool.styleUrl2DataUrl(app.config.style, r.style, app.files));
1069
+ }
1070
+ }
917
1071
  // --- 触发 taskStarted 事件 ---
918
1072
  core.trigger('taskStarted', taskId);
919
1073
  // --- 第一个任务给 native 发送任务启动成功的消息 ---
920
1074
  if (taskId === 1) {
921
- native.invoke('cg-init', native.getToken());
1075
+ await native.invoke('cg-init', native.getToken());
922
1076
  }
923
1077
  // --- 执行 app ---
924
1078
  const appCls: core.AbstractApp = new expo.default();
1079
+ list[taskId].class = appCls;
925
1080
  await appCls.main();
926
- if (!list[taskId].class) {
927
- // --- 创建任务失败,也可能没设置 config,报弹窗错误,清理启动应用并返回错误 ---
928
- // --- 结束任务 ---
929
- delete list[taskId];
930
- dom.removeFromStyleList(taskId);
931
- core.trigger('taskEnded', taskId);
932
- return -4;
933
- }
934
1081
  return taskId;
935
1082
  }
936
1083
 
@@ -945,7 +1092,7 @@ export function end(taskId: number): boolean {
945
1092
  }
946
1093
  // --- 如果是 native 模式 ---
947
1094
  if (clickgo.isNative() && (taskId === 1)) {
948
- native.invoke('cg-close', native.getToken());
1095
+ native.invoke('cg-close', native.getToken()) as any;
949
1096
  }
950
1097
  // --- 获取最大的 z index 窗体,并让他获取焦点 ---
951
1098
  const fid = form.getMaxZIndexID({
@@ -959,6 +1106,7 @@ export function end(taskId: number): boolean {
959
1106
  }
960
1107
  // --- 移除窗体 list ---
961
1108
  for (const fid in task.forms) {
1109
+ // --- 结束任务挨个关闭窗体 ---
962
1110
  const f = task.forms[fid];
963
1111
  core.trigger('formRemoved', taskId, f.id, f.vroot.$refs.form.title, f.vroot.$refs.form.iconDataUrl);
964
1112
  try {
@@ -967,15 +1115,19 @@ export function end(taskId: number): boolean {
967
1115
  catch (err: any) {
968
1116
  const msg = `Message: ${err.message}\nTask id: ${task.id}\nForm id: ${fid}\nFunction: task.end, unmount.`;
969
1117
  form.notify({
970
- 'title': 'Runtime Error',
1118
+ 'title': 'Form Unmount Error',
971
1119
  'content': msg,
972
1120
  'type': 'danger'
973
1121
  });
974
- console.log('Runtime Error', msg, err);
1122
+ console.log('Form Unmount Error', msg, err);
975
1123
  }
976
1124
  f.vapp._container.remove();
1125
+ form.elements.popList.querySelector('[data-form-id="' + f.id.toString() + '"]')?.remove();
1126
+ dom.clearWatchStyle(fid);
1127
+ dom.clearWatchProperty(fid);
977
1128
  }
978
- const flist = document.querySelectorAll('#cg-form-list > [data-task-id="' + taskId.toString() + '"]');
1129
+ // --- 移除可能残留的 form wrap ---
1130
+ const flist = form.elements.list.querySelectorAll('.cg-form-wrap[data-task-id="' + taskId.toString() + '"]');
979
1131
  for (const f of flist) {
980
1132
  f.remove();
981
1133
  }
@@ -994,6 +1146,8 @@ export function end(taskId: number): boolean {
994
1146
  }
995
1147
  // --- 移除各类监听 ---
996
1148
  dom.clearWatchSize(taskId);
1149
+ dom.clearWatch(taskId);
1150
+ native.clear(undefined, taskId);
997
1151
  // --- 移除 task ---
998
1152
  delete list[taskId];
999
1153
  // --- 触发 taskEnded 事件 ---