clickgo 3.0.6-dev7 → 3.1.0-dev9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/app/demo/app.js +93 -0
- package/dist/app/demo/form/control/form/form.js +21 -20
- package/dist/app/demo/form/control/form/form.xml +3 -3
- package/dist/app/demo/form/main.js +20 -10
- package/dist/app/demo/form/main.xml +1 -1
- package/dist/app/task/app.js +46 -0
- package/dist/app/task/form/bar/bar.js +85 -86
- package/dist/app/task/form/bar/bar.xml +5 -6
- package/dist/clickgo.js +1 -10
- package/dist/clickgo.ts +0 -8
- package/dist/control/common.cgc +0 -0
- package/dist/control/form.cgc +0 -0
- package/dist/control/monaco.cgc +0 -0
- package/dist/control/property.cgc +0 -0
- package/dist/control/task.cgc +0 -0
- package/dist/global.css +1 -1
- package/dist/index.js +105 -56
- package/dist/index.ts +164 -59
- package/dist/lib/control.js +363 -240
- package/dist/lib/control.ts +497 -284
- package/dist/lib/core.js +331 -217
- package/dist/lib/core.ts +418 -244
- package/dist/lib/dom.js +6 -3
- package/dist/lib/dom.ts +7 -6
- package/dist/lib/form.js +635 -980
- package/dist/lib/form.ts +817 -1072
- package/dist/lib/fs.js +42 -39
- package/dist/lib/fs.ts +45 -41
- package/dist/lib/native.js +8 -148
- package/dist/lib/native.ts +9 -211
- package/dist/lib/task.js +707 -191
- package/dist/lib/task.ts +778 -210
- package/dist/lib/theme.ts +2 -2
- package/dist/lib/tool.js +58 -48
- package/dist/lib/tool.ts +79 -64
- package/dist/theme/familiar.cgt +0 -0
- package/package.json +5 -7
- package/types/index.d.ts +286 -324
- package/dist/app/demo/config.json +0 -106
- package/dist/app/task/config.json +0 -32
package/dist/lib/task.ts
CHANGED
|
@@ -16,19 +16,42 @@
|
|
|
16
16
|
import * as types from '../../types';
|
|
17
17
|
import * as clickgo from '../clickgo';
|
|
18
18
|
import * as core from './core';
|
|
19
|
-
import * as control from './control';
|
|
20
19
|
import * as dom from './dom';
|
|
21
20
|
import * as tool from './tool';
|
|
22
21
|
import * as form from './form';
|
|
23
|
-
import * as
|
|
22
|
+
import * as control from './control';
|
|
24
23
|
import * as fs from './fs';
|
|
25
24
|
import * as native from './native';
|
|
26
25
|
|
|
27
|
-
/** ---
|
|
26
|
+
/** --- 当前运行的程序,App 模式下无效 --- */
|
|
28
27
|
export const list: Record<number, types.ITask> = {};
|
|
29
|
-
|
|
28
|
+
|
|
29
|
+
/** --- 最后一个 task id,App 模式下无效 --- */
|
|
30
30
|
export let lastId: number = 0;
|
|
31
31
|
|
|
32
|
+
/** --- 当前是否设置的主任务的任务 ID,全局只可设置一次 --- */
|
|
33
|
+
let mainTaskId: number = 0;
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* --- 将一个任务设置为主任务,全局只可设置一次 ---
|
|
37
|
+
* @param taskId 任务 ID
|
|
38
|
+
*/
|
|
39
|
+
export function setMain(taskId: number): boolean {
|
|
40
|
+
if (mainTaskId > 0) {
|
|
41
|
+
return false;
|
|
42
|
+
}
|
|
43
|
+
mainTaskId = taskId;
|
|
44
|
+
return true;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* --- 判断一个任务 ID 是不是主任务 ---
|
|
49
|
+
* @param taskId 任务 ID
|
|
50
|
+
*/
|
|
51
|
+
export function isMain(taskId: number): boolean {
|
|
52
|
+
return taskId === mainTaskId;
|
|
53
|
+
}
|
|
54
|
+
|
|
32
55
|
/** --- task lib 用到的语言包 --- */
|
|
33
56
|
const localeData: Record<string, {
|
|
34
57
|
'loading': string;
|
|
@@ -52,24 +75,28 @@ let frameTimer: number = 0;
|
|
|
52
75
|
const frameMaps: Record<string, number> = {};
|
|
53
76
|
|
|
54
77
|
/**
|
|
55
|
-
* --- 创建 frame
|
|
78
|
+
* --- 创建 frame 监听,formId 存在则为窗体范围,否则为任务级范围 ---
|
|
56
79
|
* @param fun 监听回调
|
|
57
|
-
* @param opt 选项,
|
|
80
|
+
* @param opt 选项,count:执行次数,默认无限次,taskId:APP模式下无效,formId:APP模式下无效
|
|
58
81
|
*/
|
|
59
82
|
export function onFrame(fun: () => void | Promise<void>, opt: {
|
|
60
|
-
'scope'?: 'form' | 'task';
|
|
61
83
|
'count'?: number;
|
|
62
84
|
'taskId'?: number;
|
|
63
85
|
'formId'?: number;
|
|
64
86
|
} = {}): number {
|
|
65
87
|
const taskId = opt.taskId;
|
|
66
88
|
const formId = opt.formId;
|
|
67
|
-
if (!taskId
|
|
89
|
+
if (!taskId) {
|
|
90
|
+
return 0;
|
|
91
|
+
}
|
|
92
|
+
const task = list[taskId];
|
|
93
|
+
if (!task) {
|
|
94
|
+
return 0;
|
|
95
|
+
}
|
|
96
|
+
if (formId && !task.forms[formId]) {
|
|
68
97
|
return 0;
|
|
69
98
|
}
|
|
70
99
|
const ft = ++frameTimer;
|
|
71
|
-
/** --- 作用域 --- */
|
|
72
|
-
const scope = opt.scope ?? 'form';
|
|
73
100
|
/** --- 执行几次,0 代表无限次 --- */
|
|
74
101
|
const count = opt.count ?? 0;
|
|
75
102
|
/** --- 当前已经执行的次数 --- */
|
|
@@ -77,22 +104,20 @@ export function onFrame(fun: () => void | Promise<void>, opt: {
|
|
|
77
104
|
let timer: number;
|
|
78
105
|
const timerHandler = async (): Promise<void> => {
|
|
79
106
|
++c;
|
|
80
|
-
if (
|
|
107
|
+
if (formId && task.forms[formId] === undefined) {
|
|
81
108
|
// --- form 已经没了 ---
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
return;
|
|
86
|
-
}
|
|
109
|
+
delete task.timers['1x' + ft.toString()];
|
|
110
|
+
delete frameMaps[ft];
|
|
111
|
+
return;
|
|
87
112
|
}
|
|
88
113
|
await fun();
|
|
89
|
-
if (
|
|
114
|
+
if (task.timers['1x' + ft.toString()] == undefined) {
|
|
90
115
|
return;
|
|
91
116
|
}
|
|
92
117
|
if (count > 1) {
|
|
93
118
|
if (c === count) {
|
|
94
119
|
// --- 终止循环 ---
|
|
95
|
-
delete
|
|
120
|
+
delete task.timers['1x' + ft.toString()];
|
|
96
121
|
delete frameMaps[ft];
|
|
97
122
|
return;
|
|
98
123
|
}
|
|
@@ -108,7 +133,7 @@ export function onFrame(fun: () => void | Promise<void>, opt: {
|
|
|
108
133
|
}
|
|
109
134
|
else if (count === 1) {
|
|
110
135
|
// --- 不循环 ---
|
|
111
|
-
delete
|
|
136
|
+
delete task.timers['1x' + ft.toString()];
|
|
112
137
|
delete frameMaps[ft];
|
|
113
138
|
}
|
|
114
139
|
else {
|
|
@@ -128,7 +153,7 @@ export function onFrame(fun: () => void | Promise<void>, opt: {
|
|
|
128
153
|
});
|
|
129
154
|
});
|
|
130
155
|
frameMaps[ft] = timer;
|
|
131
|
-
|
|
156
|
+
task.timers['1x' + ft.toString()] = formId ?? 0;
|
|
132
157
|
return ft;
|
|
133
158
|
}
|
|
134
159
|
|
|
@@ -144,6 +169,9 @@ export function offFrame(ft: number, opt: {
|
|
|
144
169
|
if (!taskId) {
|
|
145
170
|
return;
|
|
146
171
|
}
|
|
172
|
+
if (!list[taskId]) {
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
147
175
|
const formId = list[taskId].timers['1x' + ft.toString()];
|
|
148
176
|
if (formId === undefined) {
|
|
149
177
|
return;
|
|
@@ -162,12 +190,13 @@ export function get(tid: number): types.ITaskInfo | null {
|
|
|
162
190
|
return null;
|
|
163
191
|
}
|
|
164
192
|
return {
|
|
165
|
-
'name': list[tid].
|
|
193
|
+
'name': list[tid].config.name,
|
|
166
194
|
'locale': list[tid].locale.lang,
|
|
167
195
|
'customTheme': list[tid].customTheme,
|
|
168
196
|
'formCount': Object.keys(list[tid].forms).length,
|
|
169
|
-
'icon': list[tid].icon,
|
|
170
|
-
'path': list[tid].path
|
|
197
|
+
'icon': list[tid].app.icon,
|
|
198
|
+
'path': list[tid].path,
|
|
199
|
+
'current': list[tid].current
|
|
171
200
|
};
|
|
172
201
|
}
|
|
173
202
|
|
|
@@ -179,21 +208,22 @@ export function getList(): Record<string, types.ITaskInfo> {
|
|
|
179
208
|
for (const tid in list) {
|
|
180
209
|
const item = list[tid];
|
|
181
210
|
rtn[tid] = {
|
|
182
|
-
'name': item.
|
|
211
|
+
'name': item.config.name,
|
|
183
212
|
'locale': item.locale.lang,
|
|
184
213
|
'customTheme': item.customTheme,
|
|
185
214
|
'formCount': Object.keys(item.forms).length,
|
|
186
|
-
'icon': item.icon,
|
|
187
|
-
'path': item.path
|
|
215
|
+
'icon': item.app.icon,
|
|
216
|
+
'path': item.path,
|
|
217
|
+
'current': item.current
|
|
188
218
|
};
|
|
189
219
|
}
|
|
190
220
|
return rtn;
|
|
191
221
|
}
|
|
192
222
|
|
|
193
223
|
/**
|
|
194
|
-
* ---
|
|
224
|
+
* --- 运行一个应用,cga 直接文件全部正常加载,url 则静态文件需要去 config 里加载 ---
|
|
195
225
|
* @param url app 路径(以 / 为结尾的路径或以 .cga 结尾的文件)
|
|
196
|
-
* @param opt
|
|
226
|
+
* @param opt 选项
|
|
197
227
|
*/
|
|
198
228
|
export async function run(url: string, opt: types.ITaskRunOptions = {}): Promise<number> {
|
|
199
229
|
/** --- 是否是在任务当中启动的任务 --- */
|
|
@@ -220,174 +250,716 @@ export async function run(url: string, opt: types.ITaskRunOptions = {}): Promise
|
|
|
220
250
|
'timeout': 0,
|
|
221
251
|
'progress': true
|
|
222
252
|
}) : undefined;
|
|
223
|
-
|
|
253
|
+
// --- 获取并加载 app 对象 ---
|
|
254
|
+
const app = await core.fetchApp(url, {
|
|
224
255
|
'notifyId': notifyId,
|
|
225
|
-
'current': ntask ? ntask.
|
|
256
|
+
'current': ntask ? ntask.current : undefined,
|
|
226
257
|
'progress': opt.progress
|
|
227
258
|
});
|
|
228
|
-
if (
|
|
259
|
+
if (!app) {
|
|
260
|
+
// --- fetch 失败,则返回错误,隐藏 notify ---
|
|
261
|
+
if (notifyId) {
|
|
262
|
+
setTimeout(function(): void {
|
|
263
|
+
form.hideNotify(notifyId);
|
|
264
|
+
}, 2000);
|
|
265
|
+
}
|
|
266
|
+
return -1;
|
|
267
|
+
}
|
|
268
|
+
if (notifyId && !app.net) {
|
|
269
|
+
// --- 仅 app 模式隐藏,net 模式还要在 config 当中加载 xml 等非 js 资源文件 ---
|
|
229
270
|
setTimeout(function(): void {
|
|
230
271
|
form.hideNotify(notifyId);
|
|
231
272
|
}, 2000);
|
|
232
273
|
}
|
|
233
|
-
|
|
234
|
-
|
|
274
|
+
// --- 申请任务ID ---
|
|
275
|
+
const taskId = ++lastId;
|
|
276
|
+
// --- 注入的参数,屏蔽浏览器全局对象,注入新的对象 ---
|
|
277
|
+
/** --- 不屏蔽的全局对象 --- */
|
|
278
|
+
const unblock = opt.unblock ?? [];
|
|
279
|
+
/** --- 最终注入的对象 --- */
|
|
280
|
+
const invoke: Record<string, any> = {};
|
|
281
|
+
if (!unblock.includes('window')) {
|
|
282
|
+
invoke.window = undefined;
|
|
283
|
+
}
|
|
284
|
+
const ks = Object.getOwnPropertyNames(window);
|
|
285
|
+
for (const k of ks) {
|
|
286
|
+
if (k.includes('Event')) {
|
|
287
|
+
continue;
|
|
288
|
+
}
|
|
289
|
+
if (k.includes('-')) {
|
|
290
|
+
continue;
|
|
291
|
+
}
|
|
292
|
+
if (/^[0-9]+$/.test(k)) {
|
|
293
|
+
continue;
|
|
294
|
+
}
|
|
295
|
+
if ([
|
|
296
|
+
'require',
|
|
297
|
+
'__awaiter', 'eval', 'Math', 'Array', 'Blob', 'Infinity', 'parseInt', 'parseFloat', 'Promise', 'Date', 'JSON', 'fetch'].includes(k)) {
|
|
298
|
+
continue;
|
|
299
|
+
}
|
|
300
|
+
if (unblock.includes(k)) {
|
|
301
|
+
continue;
|
|
302
|
+
}
|
|
303
|
+
invoke[k] = undefined;
|
|
235
304
|
}
|
|
236
|
-
// ---
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
305
|
+
// --- console ---
|
|
306
|
+
invoke.console = {
|
|
307
|
+
log: function(message?: any, ...optionalParams: any[]) {
|
|
308
|
+
console.log(message, ...optionalParams);
|
|
309
|
+
}
|
|
310
|
+
};
|
|
311
|
+
// --- loader ---
|
|
312
|
+
invoke.loader = {
|
|
313
|
+
require: function(paths: string | string[], files: Record<string, Blob | string>, opt?: {
|
|
314
|
+
'executed'?: Record<string, any>;
|
|
315
|
+
'map'?: Record<string, string>;
|
|
316
|
+
'dir'?: string;
|
|
317
|
+
'style'?: string;
|
|
318
|
+
'invoke'?: Record<string, any>;
|
|
319
|
+
'preprocess'?: (code: string, path: string) => string;
|
|
320
|
+
}): any[] {
|
|
321
|
+
return loader.require(paths, files, opt);
|
|
322
|
+
}
|
|
323
|
+
};
|
|
324
|
+
// --- Object ---
|
|
325
|
+
if (!unblock.includes('Object')) {
|
|
326
|
+
invoke.Object = {
|
|
327
|
+
defineProperty: function(): void {
|
|
328
|
+
return;
|
|
329
|
+
},
|
|
330
|
+
keys: function(o: any): string[] {
|
|
331
|
+
return Object.keys(o);
|
|
332
|
+
},
|
|
333
|
+
assign: function(o: any, o2: any): any {
|
|
334
|
+
if (o.controlName !== undefined) {
|
|
335
|
+
return o;
|
|
336
|
+
}
|
|
337
|
+
return Object.assign(o, o2);
|
|
338
|
+
}
|
|
339
|
+
};
|
|
240
340
|
}
|
|
241
|
-
|
|
242
|
-
|
|
341
|
+
invoke.navigator = {};
|
|
342
|
+
if (navigator.clipboard) {
|
|
343
|
+
invoke.navigator.clipboard = navigator.clipboard;
|
|
344
|
+
}
|
|
345
|
+
// --- ClickGo 相关 ---
|
|
346
|
+
invoke.invokeClickgo = {
|
|
347
|
+
getVersion: function(): string {
|
|
348
|
+
return clickgo.getVersion();
|
|
349
|
+
},
|
|
350
|
+
getNative(): boolean {
|
|
351
|
+
return clickgo.getNative();
|
|
352
|
+
},
|
|
353
|
+
getPlatform(): string {
|
|
354
|
+
return clickgo.getPlatform();
|
|
355
|
+
},
|
|
356
|
+
'control': {
|
|
357
|
+
'AbstractControl': class extends control.AbstractControl {
|
|
358
|
+
public get taskId(): number {
|
|
359
|
+
return taskId;
|
|
360
|
+
}
|
|
361
|
+
},
|
|
362
|
+
read: function(blob: Blob): Promise<false | types.TControlPackage> {
|
|
363
|
+
return control.read(blob);
|
|
364
|
+
}
|
|
365
|
+
},
|
|
366
|
+
'core': {
|
|
367
|
+
'config': clickgo.core.config,
|
|
368
|
+
'AbstractApp': class extends core.AbstractApp {
|
|
369
|
+
// eslint-disable-next-line @typescript-eslint/require-await
|
|
370
|
+
public async main(): Promise<void> {
|
|
371
|
+
return;
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
public get taskId(): number {
|
|
375
|
+
return taskId;
|
|
376
|
+
}
|
|
377
|
+
},
|
|
378
|
+
getCdn: function() {
|
|
379
|
+
return core.getCdn();
|
|
380
|
+
},
|
|
381
|
+
initModules: function(names: string | string[]): Promise<number> {
|
|
382
|
+
return clickgo.core.initModules(names);
|
|
383
|
+
},
|
|
384
|
+
getModule: function(name: string): null | any {
|
|
385
|
+
return clickgo.core.getModule(name);
|
|
386
|
+
},
|
|
387
|
+
readApp: function(blob: Blob): Promise<false | types.IApp> {
|
|
388
|
+
return clickgo.core.readApp(blob);
|
|
389
|
+
},
|
|
390
|
+
getAvailArea: function(): types.IAvailArea {
|
|
391
|
+
return clickgo.core.getAvailArea();
|
|
392
|
+
}
|
|
393
|
+
},
|
|
394
|
+
'dom': {
|
|
395
|
+
setGlobalCursor: function(type?: string): void {
|
|
396
|
+
clickgo.dom.setGlobalCursor(type);
|
|
397
|
+
},
|
|
398
|
+
hasTouchButMouse: function(e: MouseEvent | TouchEvent | PointerEvent): boolean {
|
|
399
|
+
return clickgo.dom.hasTouchButMouse(e);
|
|
400
|
+
},
|
|
401
|
+
getStyleCount: function(taskId: number, type: 'theme' | 'control' | 'form'): number {
|
|
402
|
+
return clickgo.dom.getStyleCount(taskId, type);
|
|
403
|
+
},
|
|
404
|
+
getSize: function(el: HTMLElement): types.IDomSize {
|
|
405
|
+
return clickgo.dom.getSize(el);
|
|
406
|
+
},
|
|
407
|
+
watchSize: function(
|
|
408
|
+
el: HTMLElement,
|
|
409
|
+
cb: (size: types.IDomSize) => Promise<void> | void,
|
|
410
|
+
immediate: boolean = false
|
|
411
|
+
): types.IDomSize {
|
|
412
|
+
return clickgo.dom.watchSize(el, cb, immediate, taskId);
|
|
413
|
+
},
|
|
414
|
+
unwatchSize: function(el: HTMLElement): void {
|
|
415
|
+
clickgo.dom.unwatchSize(el, taskId);
|
|
416
|
+
},
|
|
417
|
+
clearWatchSize(): void {
|
|
418
|
+
clickgo.dom.clearWatchSize(taskId);
|
|
419
|
+
},
|
|
420
|
+
watch: function(el: HTMLElement, cb: () => void, mode: 'child' | 'childsub' | 'style' | 'default' = 'default', immediate: boolean = false): void {
|
|
421
|
+
clickgo.dom.watch(el, cb, mode, immediate, taskId);
|
|
422
|
+
},
|
|
423
|
+
unwatch: function(el: HTMLElement): void {
|
|
424
|
+
clickgo.dom.unwatch(el, taskId);
|
|
425
|
+
},
|
|
426
|
+
clearWatch: function(): void {
|
|
427
|
+
clickgo.dom.clearWatch(taskId);
|
|
428
|
+
},
|
|
429
|
+
watchStyle: function(
|
|
430
|
+
el: HTMLElement,
|
|
431
|
+
name: string | string[],
|
|
432
|
+
cb: (name: string, value: string) => void,
|
|
433
|
+
immediate: boolean = false
|
|
434
|
+
): void {
|
|
435
|
+
clickgo.dom.watchStyle(el, name, cb, immediate);
|
|
436
|
+
},
|
|
437
|
+
isWatchStyle: function(el: HTMLElement): boolean {
|
|
438
|
+
return clickgo.dom.isWatchStyle(el);
|
|
439
|
+
},
|
|
440
|
+
bindDown: function(oe: MouseEvent | TouchEvent, opt: types.IBindDownOptions) {
|
|
441
|
+
clickgo.dom.bindDown(oe, opt);
|
|
442
|
+
},
|
|
443
|
+
bindGesture: function(e: MouseEvent | TouchEvent | WheelEvent | { 'x'?: number; 'y'?: number; }, opt: types.IBindGestureOptions): void {
|
|
444
|
+
clickgo.dom.bindGesture(e, opt);
|
|
445
|
+
},
|
|
446
|
+
bindLong: function(
|
|
447
|
+
e: MouseEvent | TouchEvent,
|
|
448
|
+
long: (e: MouseEvent | TouchEvent) => void | Promise<void>
|
|
449
|
+
): void {
|
|
450
|
+
clickgo.dom.bindLong(e, long);
|
|
451
|
+
},
|
|
452
|
+
bindDrag: function(e: MouseEvent | TouchEvent, opt: { 'el': HTMLElement; 'data'?: any; }): void {
|
|
453
|
+
clickgo.dom.bindDrag(e, opt);
|
|
454
|
+
},
|
|
455
|
+
'is': clickgo.dom.is,
|
|
456
|
+
bindMove: function(e: MouseEvent | TouchEvent, opt: types.IBindMoveOptions): types.IBindMoveResult {
|
|
457
|
+
return clickgo.dom.bindMove(e, opt);
|
|
458
|
+
},
|
|
459
|
+
bindResize: function(e: MouseEvent | TouchEvent, opt: types.IBindResizeOptions): void {
|
|
460
|
+
clickgo.dom.bindResize(e, opt);
|
|
461
|
+
},
|
|
462
|
+
findParentByData: function(el: HTMLElement, name: string): HTMLElement | null {
|
|
463
|
+
return clickgo.dom.findParentByData(el, name);
|
|
464
|
+
},
|
|
465
|
+
findParentByClass: function(el: HTMLElement, name: string): HTMLElement | null {
|
|
466
|
+
return clickgo.dom.findParentByClass(el, name);
|
|
467
|
+
},
|
|
468
|
+
siblings: function(el: HTMLElement): HTMLElement[] {
|
|
469
|
+
return clickgo.dom.siblings(el);
|
|
470
|
+
},
|
|
471
|
+
siblingsData: function(el: HTMLElement, name: string): HTMLElement[] {
|
|
472
|
+
return clickgo.dom.siblingsData(el, name);
|
|
473
|
+
},
|
|
474
|
+
fullscreen: function(): boolean {
|
|
475
|
+
return clickgo.dom.fullscreen();
|
|
476
|
+
}
|
|
477
|
+
},
|
|
478
|
+
'form': {
|
|
479
|
+
'AbstractForm': class extends form.AbstractForm {
|
|
480
|
+
public get taskId(): number {
|
|
481
|
+
return taskId;
|
|
482
|
+
}
|
|
483
|
+
},
|
|
484
|
+
min: function(fid: number): boolean {
|
|
485
|
+
return clickgo.form.min(fid);
|
|
486
|
+
},
|
|
487
|
+
max: function max(fid: number): boolean {
|
|
488
|
+
return clickgo.form.max(fid);
|
|
489
|
+
},
|
|
490
|
+
close: function(fid: number): boolean {
|
|
491
|
+
return clickgo.form.close(fid);
|
|
492
|
+
},
|
|
493
|
+
bindResize: function(e: MouseEvent | TouchEvent, border: types.TDomBorder): void {
|
|
494
|
+
clickgo.form.bindResize(e, border);
|
|
495
|
+
},
|
|
496
|
+
bindDrag: function(e: MouseEvent | TouchEvent): void {
|
|
497
|
+
clickgo.form.bindDrag(e);
|
|
498
|
+
},
|
|
499
|
+
getTaskId: function(fid: number): number {
|
|
500
|
+
return clickgo.form.getTaskId(fid);
|
|
501
|
+
},
|
|
502
|
+
get: function(fid: number): types.IFormInfo | null {
|
|
503
|
+
return clickgo.form.get(fid);
|
|
504
|
+
},
|
|
505
|
+
getList: function(tid: number): Record<string, types.IFormInfo> {
|
|
506
|
+
return clickgo.form.getList(tid);
|
|
507
|
+
},
|
|
508
|
+
changeFocus: function(fid: number = 0): void {
|
|
509
|
+
clickgo.form.changeFocus(fid);
|
|
510
|
+
},
|
|
511
|
+
getMaxZIndexID: function(out?: {
|
|
512
|
+
'taskIds'?: number[];
|
|
513
|
+
'formIds'?: number[];
|
|
514
|
+
}): number | null {
|
|
515
|
+
return clickgo.form.getMaxZIndexID(out);
|
|
516
|
+
},
|
|
517
|
+
getRectByBorder: function(border: types.TDomBorder): { 'width': number; 'height': number; 'left': number; 'top': number; } {
|
|
518
|
+
return clickgo.form.getRectByBorder(border);
|
|
519
|
+
},
|
|
520
|
+
showCircular: function(x: number, y: number): void {
|
|
521
|
+
clickgo.form.showCircular(x, y);
|
|
522
|
+
},
|
|
523
|
+
moveRectangle: function(border: types.TDomBorder): void {
|
|
524
|
+
clickgo.form.moveRectangle(border);
|
|
525
|
+
},
|
|
526
|
+
showRectangle: function(x: number, y: number, border: types.TDomBorder): void {
|
|
527
|
+
clickgo.form.showRectangle(x, y, border);
|
|
528
|
+
},
|
|
529
|
+
hideRectangle: function(): void {
|
|
530
|
+
clickgo.form.hideRectangle();
|
|
531
|
+
},
|
|
532
|
+
showDrag: function(): void {
|
|
533
|
+
clickgo.form.showDrag();
|
|
534
|
+
},
|
|
535
|
+
moveDrag: function(opt: types.IMoveDragOptions): void {
|
|
536
|
+
clickgo.form.moveDrag(opt);
|
|
537
|
+
},
|
|
538
|
+
hideDrag: function(): void {
|
|
539
|
+
clickgo.form.hideDrag();
|
|
540
|
+
},
|
|
541
|
+
notify: function(opt: types.INotifyOptions): number {
|
|
542
|
+
return clickgo.form.notify(opt);
|
|
543
|
+
},
|
|
544
|
+
notifyProgress: function(notifyId: number, per: number): void {
|
|
545
|
+
clickgo.form.notifyProgress(notifyId, per);
|
|
546
|
+
},
|
|
547
|
+
hideNotify: function(notifyId: number): void {
|
|
548
|
+
clickgo.form.hideNotify(notifyId);
|
|
549
|
+
},
|
|
550
|
+
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 {
|
|
551
|
+
clickgo.form.showPop(el, pop, direction, opt);
|
|
552
|
+
},
|
|
553
|
+
hidePop: function(pop?: HTMLElement): void {
|
|
554
|
+
clickgo.form.hidePop(pop);
|
|
555
|
+
},
|
|
556
|
+
dialog: function(opt: string | types.IFormDialogOptions): Promise<string> {
|
|
557
|
+
if (typeof opt === 'string') {
|
|
558
|
+
opt = {
|
|
559
|
+
'content': opt
|
|
560
|
+
};
|
|
561
|
+
}
|
|
562
|
+
opt.taskId = taskId;
|
|
563
|
+
return clickgo.form.dialog(opt);
|
|
564
|
+
},
|
|
565
|
+
confirm: function(opt: string | types.IFormConfirmOptions): Promise<boolean | number> {
|
|
566
|
+
if (typeof opt === 'string') {
|
|
567
|
+
opt = {
|
|
568
|
+
'content': opt
|
|
569
|
+
};
|
|
570
|
+
}
|
|
571
|
+
opt.taskId = taskId;
|
|
572
|
+
return clickgo.form.confirm(opt);
|
|
573
|
+
},
|
|
574
|
+
flash: function(fid: number): void {
|
|
575
|
+
clickgo.form.flash(fid, taskId);
|
|
576
|
+
},
|
|
577
|
+
showLauncher: function(): void {
|
|
578
|
+
clickgo.form.showLauncher();
|
|
579
|
+
},
|
|
580
|
+
hideLauncher: function(): void {
|
|
581
|
+
clickgo.form.hideLauncher();
|
|
582
|
+
}
|
|
583
|
+
},
|
|
584
|
+
'fs': {
|
|
585
|
+
getContent: function(
|
|
586
|
+
path: string,
|
|
587
|
+
options: any = {}
|
|
588
|
+
): Promise<Blob | string | null> {
|
|
589
|
+
if (!options.files) {
|
|
590
|
+
options.files = list[taskId].app.files;
|
|
591
|
+
}
|
|
592
|
+
if (!options.current) {
|
|
593
|
+
options.current = list[taskId].current;
|
|
594
|
+
}
|
|
595
|
+
return clickgo.fs.getContent(path, options);
|
|
596
|
+
},
|
|
597
|
+
putContent: function(path: string, data: string | Buffer, options: any = {}) {
|
|
598
|
+
if (!options.current) {
|
|
599
|
+
options.current = list[taskId].current;
|
|
600
|
+
}
|
|
601
|
+
return clickgo.fs.putContent(path, data, options);
|
|
602
|
+
},
|
|
603
|
+
readLink: function(path: string, options: any = {}): Promise<string | null> {
|
|
604
|
+
if (!options.current) {
|
|
605
|
+
options.current = list[taskId].current;
|
|
606
|
+
}
|
|
607
|
+
return clickgo.fs.readLink(path, options);
|
|
608
|
+
},
|
|
609
|
+
symlink: function(fPath: string, linkPath: string, options: any = {}): Promise<boolean> {
|
|
610
|
+
if (!options.current) {
|
|
611
|
+
options.current = list[taskId].current;
|
|
612
|
+
}
|
|
613
|
+
return clickgo.fs.symlink(fPath, linkPath, options);
|
|
614
|
+
},
|
|
615
|
+
unlink: function(path: string, options: any = {}): Promise<boolean> {
|
|
616
|
+
if (!options.current) {
|
|
617
|
+
options.current = list[taskId].current;
|
|
618
|
+
}
|
|
619
|
+
return clickgo.fs.unlink(path, options);
|
|
620
|
+
},
|
|
621
|
+
stats: function(path: string, options: any = {}): Promise<types.IStats | null> {
|
|
622
|
+
if (!options.files) {
|
|
623
|
+
options.files = list[taskId].app.files;
|
|
624
|
+
}
|
|
625
|
+
if (!options.current) {
|
|
626
|
+
options.current = list[taskId].current;
|
|
627
|
+
}
|
|
628
|
+
return clickgo.fs.stats(path, options);
|
|
629
|
+
},
|
|
630
|
+
isDir: function(path: string, options: any = {}): Promise<types.IStats | false> {
|
|
631
|
+
if (!options.files) {
|
|
632
|
+
options.files = list[taskId].app.files;
|
|
633
|
+
}
|
|
634
|
+
if (!options.current) {
|
|
635
|
+
options.current = list[taskId].current;
|
|
636
|
+
}
|
|
637
|
+
return clickgo.fs.isDir(path, options);
|
|
638
|
+
},
|
|
639
|
+
isFile: function(path: string, options: any = {}): Promise<types.IStats | false> {
|
|
640
|
+
if (!options.files) {
|
|
641
|
+
options.files = list[taskId].app.files;
|
|
642
|
+
}
|
|
643
|
+
if (!options.current) {
|
|
644
|
+
options.current = list[taskId].current;
|
|
645
|
+
}
|
|
646
|
+
return clickgo.fs.isFile(path, options);
|
|
647
|
+
},
|
|
648
|
+
mkdir: function(path: string, mode?: number, options: any = {}): Promise<boolean> {
|
|
649
|
+
if (!options.current) {
|
|
650
|
+
options.current = list[taskId].current;
|
|
651
|
+
}
|
|
652
|
+
return clickgo.fs.mkdir(path, mode, options);
|
|
653
|
+
},
|
|
654
|
+
rmdir: function(path: string, options: any = {}): Promise<boolean> {
|
|
655
|
+
if (!options.current) {
|
|
656
|
+
options.current = list[taskId].current;
|
|
657
|
+
}
|
|
658
|
+
return clickgo.fs.rmdir(path, options);
|
|
659
|
+
},
|
|
660
|
+
rmdirDeep: function(path: string, options: any = {}): Promise<boolean> {
|
|
661
|
+
if (!options.current) {
|
|
662
|
+
options.current = list[taskId].current;
|
|
663
|
+
}
|
|
664
|
+
return clickgo.fs.rmdirDeep(path, options);
|
|
665
|
+
},
|
|
666
|
+
chmod: function(path: string, mod: string | number, options: any = {}): Promise<boolean> {
|
|
667
|
+
if (!options.current) {
|
|
668
|
+
options.current = list[taskId].current;
|
|
669
|
+
}
|
|
670
|
+
return clickgo.fs.chmod(path, mod, options);
|
|
671
|
+
},
|
|
672
|
+
rename(oldPath: string, newPath: string, options: any = {}): Promise<boolean> {
|
|
673
|
+
if (!options.current) {
|
|
674
|
+
options.current = list[taskId].current;
|
|
675
|
+
}
|
|
676
|
+
return clickgo.fs.rename(oldPath, newPath, options);
|
|
677
|
+
},
|
|
678
|
+
readDir(path: string, options: any = {}): Promise<types.IDirent[]> {
|
|
679
|
+
if (!options.files) {
|
|
680
|
+
options.files = list[taskId].app.files;
|
|
681
|
+
}
|
|
682
|
+
if (!options.current) {
|
|
683
|
+
options.current = list[taskId].current;
|
|
684
|
+
}
|
|
685
|
+
return clickgo.fs.readDir(path, options);
|
|
686
|
+
},
|
|
687
|
+
copyFolder(from: string, to: string, options: any = {}): Promise<number> {
|
|
688
|
+
if (!options.current) {
|
|
689
|
+
options.current = list[taskId].current;
|
|
690
|
+
}
|
|
691
|
+
return clickgo.fs.copyFolder(from, to, options);
|
|
692
|
+
},
|
|
693
|
+
copyFile(src: string, dest: string, options: any = {}): Promise<boolean> {
|
|
694
|
+
if (!options.current) {
|
|
695
|
+
options.current = list[taskId].current;
|
|
696
|
+
}
|
|
697
|
+
return clickgo.fs.copyFile(src, dest, options);
|
|
698
|
+
}
|
|
699
|
+
},
|
|
700
|
+
'native': {
|
|
701
|
+
invoke: function(name: string, ...param: any[]): any {
|
|
702
|
+
return clickgo.native.invoke(name, ...param);
|
|
703
|
+
},
|
|
704
|
+
max: function(): void {
|
|
705
|
+
clickgo.native.max();
|
|
706
|
+
},
|
|
707
|
+
min: function(): void {
|
|
708
|
+
clickgo.native.min();
|
|
709
|
+
},
|
|
710
|
+
restore: function(): void {
|
|
711
|
+
clickgo.native.restore();
|
|
712
|
+
},
|
|
713
|
+
size: function(width: number, height: number): void {
|
|
714
|
+
clickgo.native.size(width, height);
|
|
715
|
+
}
|
|
716
|
+
},
|
|
717
|
+
'task': {
|
|
718
|
+
isMain(taskId: number): boolean {
|
|
719
|
+
return isMain(taskId);
|
|
720
|
+
},
|
|
721
|
+
onFrame: function(fun: () => void | Promise<void>, opt: any = {}): number {
|
|
722
|
+
opt.taskId = taskId;
|
|
723
|
+
return clickgo.task.onFrame(fun, opt);
|
|
724
|
+
},
|
|
725
|
+
offFrame: function(ft: number, opt: {
|
|
726
|
+
'taskId'?: number;
|
|
727
|
+
} = {}): void {
|
|
728
|
+
opt.taskId = taskId;
|
|
729
|
+
clickgo.task.offFrame(ft, opt);
|
|
730
|
+
},
|
|
731
|
+
get: function(tid: number): types.ITaskInfo | null {
|
|
732
|
+
return clickgo.task.get(tid);
|
|
733
|
+
},
|
|
734
|
+
getList: function(): Record<string, types.ITaskInfo> {
|
|
735
|
+
return clickgo.task.getList();
|
|
736
|
+
},
|
|
737
|
+
run: function(url: string, opt: types.ITaskRunOptions = {}): Promise<number> {
|
|
738
|
+
opt.taskId = taskId;
|
|
739
|
+
opt.main = false;
|
|
740
|
+
return clickgo.task.run(url, opt);
|
|
741
|
+
},
|
|
742
|
+
end: function(tid: number): boolean {
|
|
743
|
+
return clickgo.task.end(tid ?? taskId);
|
|
744
|
+
},
|
|
745
|
+
loadLocaleData: function(lang: string, data: Record<string, any>, pre: string = ''): void {
|
|
746
|
+
clickgo.task.loadLocaleData(lang, data, pre, taskId);
|
|
747
|
+
},
|
|
748
|
+
loadLocale: function(lang: string, path: string): Promise<boolean> {
|
|
749
|
+
return clickgo.task.loadLocale(lang, path, taskId);
|
|
750
|
+
},
|
|
751
|
+
clearLocale: function(): void {
|
|
752
|
+
clickgo.task.clearLocale(taskId);
|
|
753
|
+
},
|
|
754
|
+
setLocale: function(lang: string, path: string): Promise<boolean> {
|
|
755
|
+
return clickgo.task.setLocale(lang, path, taskId);
|
|
756
|
+
},
|
|
757
|
+
setLocaleLang: function(lang: string): void {
|
|
758
|
+
clickgo.task.setLocaleLang(lang, taskId);
|
|
759
|
+
},
|
|
760
|
+
clearLocaleLang: function(): void {
|
|
761
|
+
clickgo.task.clearLocaleLang(taskId);
|
|
762
|
+
},
|
|
763
|
+
createTimer: function(
|
|
764
|
+
fun: () => void | Promise<void>,
|
|
765
|
+
delay: number,
|
|
766
|
+
opt: types.ICreateTimerOptions = {}
|
|
767
|
+
): number {
|
|
768
|
+
opt.taskId = taskId;
|
|
769
|
+
return clickgo.task.createTimer(fun, delay, opt);
|
|
770
|
+
},
|
|
771
|
+
removeTimer: function(timer: number): void {
|
|
772
|
+
clickgo.task.removeTimer(timer, taskId);
|
|
773
|
+
},
|
|
774
|
+
sleep: function(fun: () => void | Promise<void>, delay: number): number {
|
|
775
|
+
return clickgo.task.sleep(fun, delay, taskId);
|
|
776
|
+
},
|
|
777
|
+
systemTaskInfo: clickgo.task.systemTaskInfo,
|
|
778
|
+
setSystem: function(fid: number): boolean {
|
|
779
|
+
return clickgo.task.setSystem(fid, taskId);
|
|
780
|
+
},
|
|
781
|
+
clearSystem: function(): boolean {
|
|
782
|
+
return clickgo.task.clearSystem(taskId);
|
|
783
|
+
}
|
|
784
|
+
},
|
|
785
|
+
'theme': {
|
|
786
|
+
read: function(blob: Blob): Promise<types.ITheme | false> {
|
|
787
|
+
return clickgo.theme.read(blob);
|
|
788
|
+
},
|
|
789
|
+
load: async function(theme?: types.ITheme): Promise<boolean> {
|
|
790
|
+
if (!theme) {
|
|
791
|
+
return false;
|
|
792
|
+
}
|
|
793
|
+
return clickgo.theme.load(theme, taskId);
|
|
794
|
+
},
|
|
795
|
+
remove: function(name: string): Promise<void> {
|
|
796
|
+
return clickgo.theme.remove(name, taskId);
|
|
797
|
+
},
|
|
798
|
+
clear: function(): Promise<void> {
|
|
799
|
+
return clickgo.theme.clear(taskId);
|
|
800
|
+
},
|
|
801
|
+
setGlobal: function(theme: types.ITheme): Promise<void> {
|
|
802
|
+
return clickgo.theme.setGlobal(theme);
|
|
803
|
+
},
|
|
804
|
+
clearGlobal: function(): void {
|
|
805
|
+
clickgo.theme.clearGlobal();
|
|
806
|
+
}
|
|
807
|
+
},
|
|
808
|
+
'tool': {
|
|
809
|
+
blob2ArrayBuffer: function(blob: Blob): Promise<ArrayBuffer> {
|
|
810
|
+
return clickgo.tool.blob2ArrayBuffer(blob);
|
|
811
|
+
},
|
|
812
|
+
clone: function(obj: Record<string, any> | any[]): any[] | any {
|
|
813
|
+
return clickgo.tool.clone(obj);
|
|
814
|
+
},
|
|
815
|
+
sleep: function(ms: number = 0): Promise<boolean> {
|
|
816
|
+
return clickgo.tool.sleep(ms);
|
|
817
|
+
},
|
|
818
|
+
purify: function(text: string): string {
|
|
819
|
+
return clickgo.tool.purify(text);
|
|
820
|
+
},
|
|
821
|
+
rand: function(min: number, max: number): number {
|
|
822
|
+
return clickgo.tool.rand(min, max);
|
|
823
|
+
},
|
|
824
|
+
'RANDOM_N': clickgo.tool.RANDOM_N,
|
|
825
|
+
'RANDOM_U': clickgo.tool.RANDOM_U,
|
|
826
|
+
'RANDOM_L': clickgo.tool.RANDOM_L,
|
|
827
|
+
'RANDOM_UN': clickgo.tool.RANDOM_UN,
|
|
828
|
+
'RANDOM_LN': clickgo.tool.RANDOM_LN,
|
|
829
|
+
'RANDOM_LU': clickgo.tool.RANDOM_LU,
|
|
830
|
+
'RANDOM_LUN': clickgo.tool.RANDOM_LUN,
|
|
831
|
+
'RANDOM_V': clickgo.tool.RANDOM_V,
|
|
832
|
+
'RANDOM_LUNS': clickgo.tool.RANDOM_LUNS,
|
|
833
|
+
random: function(length: number = 8, source: string = clickgo.tool.RANDOM_LN, block: string = ''): string {
|
|
834
|
+
return clickgo.tool.random(length, source, block);
|
|
835
|
+
},
|
|
836
|
+
getBoolean: function(param: boolean | string | number): boolean {
|
|
837
|
+
return clickgo.tool.getBoolean(param);
|
|
838
|
+
},
|
|
839
|
+
escapeHTML: function(html: string): string {
|
|
840
|
+
return clickgo.tool.escapeHTML(html);
|
|
841
|
+
},
|
|
842
|
+
request: function(url: string, opt: types.IRequestOptions): Promise<null | any> {
|
|
843
|
+
return clickgo.tool.request(url, opt);
|
|
844
|
+
},
|
|
845
|
+
parseUrl: function(url: string): ILoaderUrl {
|
|
846
|
+
return clickgo.tool.parseUrl(url);
|
|
847
|
+
},
|
|
848
|
+
urlResolve: function(from: string, to: string): string {
|
|
849
|
+
return clickgo.tool.urlResolve(from, to);
|
|
850
|
+
},
|
|
851
|
+
blob2Text: function(blob: Blob): Promise<string> {
|
|
852
|
+
return clickgo.tool.blob2Text(blob);
|
|
853
|
+
},
|
|
854
|
+
blob2DataUrl: function(blob: Blob): Promise<string> {
|
|
855
|
+
return clickgo.tool.blob2DataUrl(blob);
|
|
856
|
+
},
|
|
857
|
+
execCommand: function(ac: string): void {
|
|
858
|
+
clickgo.tool.execCommand(ac);
|
|
859
|
+
}
|
|
860
|
+
},
|
|
861
|
+
'zip': {
|
|
862
|
+
get: function(data?: types.TZipInputFileFormat) {
|
|
863
|
+
return clickgo.zip.get(data);
|
|
864
|
+
}
|
|
865
|
+
}
|
|
866
|
+
};
|
|
867
|
+
/** --- 加载的 js 文件预处理 --- */
|
|
868
|
+
const preprocess = function(code: string, path: string): string {
|
|
869
|
+
// --- 屏蔽 eval 函数 ---
|
|
870
|
+
const exec = /eval\W/.exec(code);
|
|
871
|
+
if (exec) {
|
|
872
|
+
form.notify({
|
|
873
|
+
'title': 'Error',
|
|
874
|
+
'content': `The "eval" is prohibited.\nFile: "${path}".`,
|
|
875
|
+
'type': 'danger'
|
|
876
|
+
});
|
|
877
|
+
return '';
|
|
878
|
+
}
|
|
879
|
+
// --- 给 form 的 class 增加 filename 的 get ---
|
|
880
|
+
code = code.replace(/extends[\s\S]+?\.\s*(AbstractApp|AbstractForm)\s*{/, (t: string) => {
|
|
881
|
+
return t + 'get filename() {return __filename;}';
|
|
882
|
+
});
|
|
883
|
+
return code;
|
|
884
|
+
};
|
|
885
|
+
app.files['/invoke/clickgo.js'] = `module.exports = invokeClickgo;`;
|
|
886
|
+
/** --- .cga 文件,或者不含 / 结尾的路径 --- */
|
|
887
|
+
const path = url;
|
|
888
|
+
const lio = path.endsWith('.cga') ? path.lastIndexOf('/') : path.slice(0, -1).lastIndexOf('/');
|
|
889
|
+
const current = path.slice(0, lio);
|
|
890
|
+
// --- 创建任务对象 task.IRT ---
|
|
243
891
|
list[taskId] = {
|
|
244
892
|
'id': taskId,
|
|
245
893
|
'app': app,
|
|
894
|
+
// 'class': null,
|
|
895
|
+
// 'config': {},
|
|
246
896
|
'customTheme': false,
|
|
247
897
|
'locale': clickgo.vue.reactive({
|
|
248
898
|
'lang': '',
|
|
249
899
|
'data': {}
|
|
250
900
|
}),
|
|
251
|
-
'
|
|
252
|
-
'
|
|
253
|
-
'files': files,
|
|
254
|
-
'main': opt.main ?? false,
|
|
901
|
+
'path': path,
|
|
902
|
+
'current': current,
|
|
255
903
|
|
|
256
|
-
'
|
|
904
|
+
'runtime': clickgo.vue.reactive({
|
|
905
|
+
'permissions': {},
|
|
906
|
+
'dialogFormIds': []
|
|
907
|
+
}),
|
|
257
908
|
'forms': {},
|
|
258
|
-
'
|
|
259
|
-
'
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
'
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
path = tool.urlResolve('/', path);
|
|
271
|
-
const file = await fs.getContent(path, {
|
|
272
|
-
'files': task.files
|
|
273
|
-
});
|
|
274
|
-
if (file && typeof file !== 'string') {
|
|
275
|
-
const c = await control.read(file);
|
|
276
|
-
if (c) {
|
|
277
|
-
task.controls.loaded[path] = c;
|
|
278
|
-
}
|
|
279
|
-
else {
|
|
280
|
-
form.notify({
|
|
281
|
-
'title': 'Control failed to load',
|
|
282
|
-
'content': path
|
|
283
|
-
});
|
|
909
|
+
'controls': {},
|
|
910
|
+
'timers': {},
|
|
911
|
+
'invoke': invoke
|
|
912
|
+
} as any;
|
|
913
|
+
let expo: any = [];
|
|
914
|
+
try {
|
|
915
|
+
expo = loader.require('/app.js', app.files, {
|
|
916
|
+
'dir': '/',
|
|
917
|
+
'invoke': invoke,
|
|
918
|
+
'preprocess': preprocess,
|
|
919
|
+
'map': {
|
|
920
|
+
'clickgo': '/invoke/clickgo'
|
|
284
921
|
}
|
|
285
|
-
}
|
|
922
|
+
})[0];
|
|
286
923
|
}
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
path = tool.urlResolve('/', path);
|
|
292
|
-
const file = await fs.getContent(path, {
|
|
293
|
-
'files': task.files
|
|
294
|
-
});
|
|
295
|
-
if (file && typeof file !== 'string') {
|
|
296
|
-
const th = await theme.read(file);
|
|
297
|
-
if (th) {
|
|
298
|
-
await theme.load(th, taskId);
|
|
299
|
-
}
|
|
300
|
-
}
|
|
301
|
-
}
|
|
924
|
+
catch (e: any) {
|
|
925
|
+
delete list[taskId];
|
|
926
|
+
core.trigger('error', taskId, 0, e, e.message + '(-1)');
|
|
927
|
+
return -2;
|
|
302
928
|
}
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
const locale = app.config.locales[path];
|
|
307
|
-
if (!path.endsWith('.json')) {
|
|
308
|
-
path += '.json';
|
|
309
|
-
}
|
|
310
|
-
const lcontent = await fs.getContent(path, {
|
|
311
|
-
'encoding': 'utf8',
|
|
312
|
-
'files': task.files,
|
|
313
|
-
'current': task.path
|
|
314
|
-
});
|
|
315
|
-
if (!lcontent) {
|
|
316
|
-
continue;
|
|
317
|
-
}
|
|
318
|
-
try {
|
|
319
|
-
const data = JSON.parse(lcontent);
|
|
320
|
-
loadLocaleData(locale, data, '', task.id);
|
|
321
|
-
}
|
|
322
|
-
catch {
|
|
323
|
-
// --- 无所谓 ---
|
|
324
|
-
}
|
|
325
|
-
}
|
|
929
|
+
if (!expo?.default) {
|
|
930
|
+
delete list[taskId];
|
|
931
|
+
return -3;
|
|
326
932
|
}
|
|
327
|
-
// --- 触发 taskStarted 事件 ---
|
|
328
|
-
core.trigger('taskStarted', task.id);
|
|
329
933
|
// --- 创建 Task 总 style ---
|
|
330
|
-
dom.createToStyleList(
|
|
331
|
-
// ---
|
|
332
|
-
const
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
if (typeof f === 'number') {
|
|
934
|
+
dom.createToStyleList(taskId);
|
|
935
|
+
// --- 执行 app ---
|
|
936
|
+
const appCls: core.AbstractApp = new expo.default();
|
|
937
|
+
await appCls.main();
|
|
938
|
+
if (!list[taskId].class) {
|
|
939
|
+
// --- 创建任务失败,也可能没设置 config,报弹窗错误,清理启动应用并返回错误 ---
|
|
337
940
|
// --- 结束任务 ---
|
|
338
|
-
delete list[
|
|
339
|
-
dom.removeFromStyleList(
|
|
340
|
-
|
|
341
|
-
return f - 100;
|
|
342
|
-
}
|
|
343
|
-
// --- 设置 global style(如果 form 创建失败,就不设置 global style 了) ---
|
|
344
|
-
if (app.config.style && app.files[app.config.style + '.css']) {
|
|
345
|
-
const style = app.files[app.config.style + '.css'] as string;
|
|
346
|
-
const r = tool.stylePrepend(style, 'cg-task' + task.id.toString() + '_');
|
|
347
|
-
dom.pushStyle(task.id, await tool.styleUrl2DataUrl(app.config.style, r.style, app.files));
|
|
348
|
-
}
|
|
349
|
-
// --- 是否要加载独立的 theme ---
|
|
350
|
-
if (app.config.themes && app.config.themes.length > 0) {
|
|
351
|
-
task.customTheme = true;
|
|
352
|
-
for (const path of app.config.themes) {
|
|
353
|
-
const blob = await fs.getContent(path, {
|
|
354
|
-
'files': task.files,
|
|
355
|
-
'current': task.path
|
|
356
|
-
});
|
|
357
|
-
if (!(blob instanceof Blob)) {
|
|
358
|
-
continue;
|
|
359
|
-
}
|
|
360
|
-
const th = await theme.read(blob);
|
|
361
|
-
if (!th) {
|
|
362
|
-
continue;
|
|
363
|
-
}
|
|
364
|
-
await theme.load(th, task.id);
|
|
365
|
-
}
|
|
366
|
-
}
|
|
367
|
-
else {
|
|
368
|
-
// --- 检测是否加载系统 theme ---
|
|
369
|
-
if (theme.global) {
|
|
370
|
-
await theme.load(undefined, task.id);
|
|
371
|
-
}
|
|
941
|
+
delete list[taskId];
|
|
942
|
+
dom.removeFromStyleList(taskId);
|
|
943
|
+
return -4;
|
|
372
944
|
}
|
|
945
|
+
// --- 触发 taskStarted 事件 ---
|
|
946
|
+
core.trigger('taskStarted', taskId);
|
|
373
947
|
// --- 给 native 发送任务启动成功的消息 ---
|
|
374
|
-
if (
|
|
375
|
-
|
|
948
|
+
if (taskId === 1) {
|
|
949
|
+
native.invoke('cg-init', native.getToken());
|
|
376
950
|
}
|
|
377
951
|
// --- 提交 sync ---
|
|
952
|
+
/*
|
|
378
953
|
if (clickgo.getNative() && opt.sync) {
|
|
379
954
|
f.vroot.$refs.form.isNativeSync = true;
|
|
380
|
-
|
|
381
|
-
'token': clickgo.native.getToken(),
|
|
382
|
-
'width': f.vroot.$refs.form.widthData,
|
|
383
|
-
'height': f.vroot.$refs.form.heightData
|
|
384
|
-
}));
|
|
955
|
+
native.invoke('cg-set-size', native.getToken(), f.vroot.$refs.form.widthData, f.vroot.$refs.form.heightData);
|
|
385
956
|
window.addEventListener('resize', function(): void {
|
|
386
957
|
f.vroot.$refs.form.setPropData('width', window.innerWidth);
|
|
387
958
|
f.vroot.$refs.form.setPropData('height', window.innerHeight);
|
|
388
959
|
});
|
|
389
960
|
}
|
|
390
|
-
|
|
961
|
+
*/
|
|
962
|
+
return taskId;
|
|
391
963
|
}
|
|
392
964
|
|
|
393
965
|
/**
|
|
@@ -400,10 +972,8 @@ export function end(taskId: number): boolean {
|
|
|
400
972
|
return true;
|
|
401
973
|
}
|
|
402
974
|
// --- 如果是 native 模式 ---
|
|
403
|
-
if (clickgo.getNative() &&
|
|
404
|
-
|
|
405
|
-
'token': clickgo.native.getToken()
|
|
406
|
-
}));
|
|
975
|
+
if (clickgo.getNative() && isMain(taskId)) {
|
|
976
|
+
native.invoke('cg-close', native.getToken());
|
|
407
977
|
}
|
|
408
978
|
// --- 获取最大的 z index 窗体,并让他获取焦点 ---
|
|
409
979
|
const fid = form.getMaxZIndexID({
|
|
@@ -419,15 +989,26 @@ export function end(taskId: number): boolean {
|
|
|
419
989
|
for (const fid in task.forms) {
|
|
420
990
|
const f = task.forms[fid];
|
|
421
991
|
core.trigger('formRemoved', taskId, f.id, f.vroot.$refs.form.title, f.vroot.$refs.form.iconData);
|
|
422
|
-
|
|
992
|
+
try {
|
|
993
|
+
f.vapp.unmount();
|
|
994
|
+
}
|
|
995
|
+
catch (err: any) {
|
|
996
|
+
const msg = `Message: ${err.message}\nTask id: ${task.id}\nForm id: ${fid}\nFunction: task.end, unmount.`;
|
|
997
|
+
form.notify({
|
|
998
|
+
'title': 'Runtime Error',
|
|
999
|
+
'content': msg,
|
|
1000
|
+
'type': 'danger'
|
|
1001
|
+
});
|
|
1002
|
+
console.log('Runtime Error', msg, err);
|
|
1003
|
+
}
|
|
423
1004
|
f.vapp._container.remove();
|
|
424
1005
|
}
|
|
1006
|
+
const flist = document.querySelectorAll('#cg-form-list > [data-task-id="' + taskId.toString() + '"]');
|
|
1007
|
+
for (const f of flist) {
|
|
1008
|
+
f.remove();
|
|
1009
|
+
}
|
|
425
1010
|
// --- 移除 style ---
|
|
426
1011
|
dom.removeFromStyleList(taskId);
|
|
427
|
-
// --- 移除本 task 创建的所有 object url ---
|
|
428
|
-
for (const url of task.objectURLs) {
|
|
429
|
-
tool.revokeObjectURL(url, task.id);
|
|
430
|
-
}
|
|
431
1012
|
// --- 移除所有 timer ---
|
|
432
1013
|
for (const timer in list[taskId].timers) {
|
|
433
1014
|
if (timer.startsWith('1x')) {
|
|
@@ -440,7 +1021,6 @@ export function end(taskId: number): boolean {
|
|
|
440
1021
|
}
|
|
441
1022
|
}
|
|
442
1023
|
// --- 移除各类监听 ---
|
|
443
|
-
native.clearListener(taskId);
|
|
444
1024
|
dom.clearWatchSize(taskId);
|
|
445
1025
|
// --- 移除 task ---
|
|
446
1026
|
delete list[taskId];
|
|
@@ -479,11 +1059,10 @@ export function loadLocaleData(lang: string, data: Record<string, any>, pre: str
|
|
|
479
1059
|
/**
|
|
480
1060
|
* --- 加载 locale 文件 json ---
|
|
481
1061
|
* @param lang 语言名,如 sc
|
|
482
|
-
* @param path
|
|
1062
|
+
* @param path 绝对或者相对 app 路径的地址
|
|
483
1063
|
* @param taskId 所属的 taskId,App 模式下无效
|
|
484
|
-
* @param formId 所属的 formId,App 模式下无效
|
|
485
1064
|
*/
|
|
486
|
-
export async function loadLocale(lang: string, path: string, taskId?: number
|
|
1065
|
+
export async function loadLocale(lang: string, path: string, taskId?: number): Promise<boolean> {
|
|
487
1066
|
if (!taskId) {
|
|
488
1067
|
return false;
|
|
489
1068
|
}
|
|
@@ -491,21 +1070,13 @@ export async function loadLocale(lang: string, path: string, taskId?: number, fo
|
|
|
491
1070
|
if (!task) {
|
|
492
1071
|
return false;
|
|
493
1072
|
}
|
|
494
|
-
let form: types.IForm | null = null;
|
|
495
|
-
if (formId) {
|
|
496
|
-
if (!task.forms[formId]) {
|
|
497
|
-
return false;
|
|
498
|
-
}
|
|
499
|
-
form = task.forms[formId];
|
|
500
|
-
}
|
|
501
1073
|
/** --- 当前父 form 的路径(以 / 结尾)或 /(没有基路径的话) --- */
|
|
502
|
-
|
|
503
|
-
path = tool.urlResolve(base, path) + '.json';
|
|
1074
|
+
path = tool.urlResolve(task.current + '/', path) + '.json';
|
|
504
1075
|
/** --- 获取的语言文件 --- */
|
|
505
1076
|
const fcontent = await fs.getContent(path, {
|
|
506
1077
|
'encoding': 'utf8',
|
|
507
|
-
'files': task.files,
|
|
508
|
-
'current': task.
|
|
1078
|
+
'files': task.app.files,
|
|
1079
|
+
'current': task.current
|
|
509
1080
|
});
|
|
510
1081
|
if (!fcontent) {
|
|
511
1082
|
return false;
|
|
@@ -538,13 +1109,12 @@ export function clearLocale(taskId?: number): void {
|
|
|
538
1109
|
/**
|
|
539
1110
|
* --- 加载全新 locale(老 locale 的所以语言的缓存会被卸载) ---
|
|
540
1111
|
* @param lang 语言名,如 sc
|
|
541
|
-
* @param path
|
|
542
|
-
* @param taskId 所属的 taskId,App 模式下无效
|
|
543
|
-
* @param formId 所属的 formId,App 模式下无效
|
|
1112
|
+
* @param path 绝对或者相对 app 路径的地址
|
|
1113
|
+
* @param taskId 所属的 taskId,App 模式下无效z
|
|
544
1114
|
*/
|
|
545
|
-
export function setLocale(lang: string, path: string, taskId?: number
|
|
1115
|
+
export function setLocale(lang: string, path: string, taskId?: number): Promise<boolean> {
|
|
546
1116
|
clearLocale(taskId);
|
|
547
|
-
return loadLocale(lang, path, taskId
|
|
1117
|
+
return loadLocale(lang, path, taskId);
|
|
548
1118
|
}
|
|
549
1119
|
|
|
550
1120
|
/**
|
|
@@ -590,15 +1160,17 @@ export function createTimer(
|
|
|
590
1160
|
opt: types.ICreateTimerOptions = {}
|
|
591
1161
|
): number {
|
|
592
1162
|
const taskId = opt.taskId;
|
|
1163
|
+
const formId = opt.formId;
|
|
593
1164
|
if (!taskId) {
|
|
594
1165
|
return 0;
|
|
595
1166
|
}
|
|
596
|
-
const
|
|
597
|
-
if (!
|
|
1167
|
+
const task = list[taskId];
|
|
1168
|
+
if (!task) {
|
|
1169
|
+
return 0;
|
|
1170
|
+
}
|
|
1171
|
+
if (formId && !task.forms[formId]) {
|
|
598
1172
|
return 0;
|
|
599
1173
|
}
|
|
600
|
-
/** --- 作用域 --- */
|
|
601
|
-
const scope = opt.scope ?? 'form';
|
|
602
1174
|
/** --- 执行几次,0 代表无限次 --- */
|
|
603
1175
|
const count = opt.count ?? 0;
|
|
604
1176
|
/** --- 当前已经执行的次数 --- */
|
|
@@ -619,13 +1191,11 @@ export function createTimer(
|
|
|
619
1191
|
let timer: number;
|
|
620
1192
|
const timerHandler = (): void => {
|
|
621
1193
|
++c;
|
|
622
|
-
if (
|
|
1194
|
+
if (formId && task.forms[formId] === undefined) {
|
|
623
1195
|
// --- form 已经没了 ---
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
return;
|
|
628
|
-
}
|
|
1196
|
+
clearTimeout(timer);
|
|
1197
|
+
delete task.timers[timer];
|
|
1198
|
+
return;
|
|
629
1199
|
}
|
|
630
1200
|
const r = fun();
|
|
631
1201
|
if (r instanceof Promise) {
|
|
@@ -635,7 +1205,7 @@ export function createTimer(
|
|
|
635
1205
|
}
|
|
636
1206
|
if (count > 0 && c === count) {
|
|
637
1207
|
clearTimeout(timer);
|
|
638
|
-
delete
|
|
1208
|
+
delete task.timers[timer];
|
|
639
1209
|
return;
|
|
640
1210
|
}
|
|
641
1211
|
};
|
|
@@ -646,7 +1216,7 @@ export function createTimer(
|
|
|
646
1216
|
else {
|
|
647
1217
|
timer = window.setInterval(timerHandler, delay);
|
|
648
1218
|
}
|
|
649
|
-
|
|
1219
|
+
task.timers[timer] = formId ?? 0;
|
|
650
1220
|
return timer;
|
|
651
1221
|
}
|
|
652
1222
|
|
|
@@ -676,12 +1246,10 @@ export function removeTimer(timer: number, taskId?: number): void {
|
|
|
676
1246
|
* @param fun 回调函数
|
|
677
1247
|
* @param delay 暂停时间
|
|
678
1248
|
* @param taskId 任务 id,App 模式下无效
|
|
679
|
-
* @param formId 窗体 id,App 模式下无效
|
|
680
1249
|
*/
|
|
681
|
-
export function sleep(fun: () => void | Promise<void>, delay: number, taskId?: number
|
|
1250
|
+
export function sleep(fun: () => void | Promise<void>, delay: number, taskId?: number): number {
|
|
682
1251
|
return createTimer(fun, delay, {
|
|
683
1252
|
'taskId': taskId,
|
|
684
|
-
'formId': formId,
|
|
685
1253
|
'count': 1
|
|
686
1254
|
});
|
|
687
1255
|
}
|
|
@@ -733,11 +1301,11 @@ clickgo.vue.watch(systemTaskInfo, function(n: any, o: any) {
|
|
|
733
1301
|
|
|
734
1302
|
/**
|
|
735
1303
|
* --- 将任务注册为系统 task ---
|
|
736
|
-
* @param formId task bar 的 form id
|
|
1304
|
+
* @param formId task bar 的 form id
|
|
737
1305
|
* @param taskId task id,App 模式下无效
|
|
738
1306
|
*/
|
|
739
|
-
export function setSystem(formId
|
|
740
|
-
if (!
|
|
1307
|
+
export function setSystem(formId: number, taskId?: number): boolean {
|
|
1308
|
+
if (!taskId) {
|
|
741
1309
|
return false;
|
|
742
1310
|
}
|
|
743
1311
|
const task = list[taskId];
|
|
@@ -812,7 +1380,7 @@ export function clearSystem(taskId?: number): boolean {
|
|
|
812
1380
|
}
|
|
813
1381
|
|
|
814
1382
|
/**
|
|
815
|
-
* --- 刷新系统任务的 form 的位置以及 length ---
|
|
1383
|
+
* --- 刷新系统任务的 form 的位置以及 length,App 模式下无效 ---
|
|
816
1384
|
*/
|
|
817
1385
|
export function refreshSystemPosition(): void {
|
|
818
1386
|
if (systemTaskInfo.taskId > 0) {
|
|
@@ -821,14 +1389,14 @@ export function refreshSystemPosition(): void {
|
|
|
821
1389
|
switch (core.config['task.position']) {
|
|
822
1390
|
case 'left':
|
|
823
1391
|
case 'right': {
|
|
824
|
-
form.vroot.$refs.form.setPropData('width',
|
|
1392
|
+
form.vroot.$refs.form.setPropData('width', 0);
|
|
825
1393
|
form.vroot.$refs.form.setPropData('height', window.innerHeight);
|
|
826
1394
|
break;
|
|
827
1395
|
}
|
|
828
1396
|
case 'top':
|
|
829
1397
|
case 'bottom': {
|
|
830
1398
|
form.vroot.$refs.form.setPropData('width', window.innerWidth);
|
|
831
|
-
form.vroot.$refs.form.setPropData('height',
|
|
1399
|
+
form.vroot.$refs.form.setPropData('height', 0);
|
|
832
1400
|
break;
|
|
833
1401
|
}
|
|
834
1402
|
}
|