@oinone/kunlun-vue-widget 6.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/oinone-kunlun-vue-widget.esm.js +16 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/types/src/basic/AsyncVueWidget.d.ts +7 -0
- package/dist/types/src/basic/VueFragment.vue.d.ts +2 -0
- package/dist/types/src/basic/VueWidget.d.ts +331 -0
- package/dist/types/src/basic/Widget.d.ts +234 -0
- package/dist/types/src/basic/index.d.ts +3 -0
- package/dist/types/src/data/ActiveRecordsWidget.d.ts +246 -0
- package/dist/types/src/data/PathWidget.d.ts +34 -0
- package/dist/types/src/data/index.d.ts +2 -0
- package/dist/types/src/dsl/DslDefinitionWidget.d.ts +61 -0
- package/dist/types/src/dsl/DslNodeWidget.d.ts +42 -0
- package/dist/types/src/dsl/DslRenderWidget.d.ts +44 -0
- package/dist/types/src/dsl/index.d.ts +3 -0
- package/dist/types/src/feature/index.d.ts +1 -0
- package/dist/types/src/feature/invisible-supported.d.ts +11 -0
- package/dist/types/src/hooks/all-mounted.d.ts +20 -0
- package/dist/types/src/hooks/index.d.ts +1 -0
- package/dist/types/src/index.d.ts +9 -0
- package/dist/types/src/token/index.d.ts +2 -0
- package/dist/types/src/typing/WidgetTagContext.d.ts +39 -0
- package/dist/types/src/typing/WidgetTagProps.d.ts +23 -0
- package/dist/types/src/typing/index.d.ts +3 -0
- package/dist/types/src/typing/typing.d.ts +7 -0
- package/dist/types/src/util/dsl-render.d.ts +106 -0
- package/dist/types/src/util/index.d.ts +4 -0
- package/dist/types/src/util/install.d.ts +4 -0
- package/dist/types/src/util/render.d.ts +7 -0
- package/dist/types/src/util/widget-manager.d.ts +4 -0
- package/dist/types/src/view/index.d.ts +161 -0
- package/index.ts +1 -0
- package/package.json +34 -0
- package/rollup.config.js +21 -0
- package/src/basic/AsyncVueWidget.ts +31 -0
- package/src/basic/VueFragment.vue +11 -0
- package/src/basic/VueWidget.ts +997 -0
- package/src/basic/Widget.ts +675 -0
- package/src/basic/index.ts +3 -0
- package/src/data/ActiveRecordsWidget.ts +572 -0
- package/src/data/PathWidget.ts +82 -0
- package/src/data/index.ts +2 -0
- package/src/dsl/DslDefinitionWidget.ts +235 -0
- package/src/dsl/DslNodeWidget.ts +130 -0
- package/src/dsl/DslRenderWidget.ts +106 -0
- package/src/dsl/index.ts +3 -0
- package/src/feature/index.ts +1 -0
- package/src/feature/invisible-supported.ts +29 -0
- package/src/hooks/all-mounted.ts +179 -0
- package/src/hooks/index.ts +1 -0
- package/src/index.ts +9 -0
- package/src/shim-translate.d.ts +7 -0
- package/src/shim-vue.d.ts +6 -0
- package/src/token/index.ts +8 -0
- package/src/typing/WidgetTagContext.ts +53 -0
- package/src/typing/WidgetTagProps.ts +24 -0
- package/src/typing/index.ts +3 -0
- package/src/typing/typing.ts +7 -0
- package/src/util/dsl-render.ts +464 -0
- package/src/util/index.ts +4 -0
- package/src/util/install.ts +29 -0
- package/src/util/render.ts +21 -0
- package/src/util/widget-manager.ts +14 -0
- package/src/view/index.ts +416 -0
|
@@ -0,0 +1,997 @@
|
|
|
1
|
+
import { genStaticPath, translateValueByKey, WidgetConstructor, WidgetProps } from '@oinone/kunlun-engine';
|
|
2
|
+
import { ReturnPromise, uniqueKeyGenerator } from '@oinone/kunlun-shared';
|
|
3
|
+
import { ComponentPublicInstance, SetupContext } from '@vue/runtime-core';
|
|
4
|
+
import {
|
|
5
|
+
Component,
|
|
6
|
+
ComponentOptions,
|
|
7
|
+
computed,
|
|
8
|
+
createVNode,
|
|
9
|
+
defineComponent,
|
|
10
|
+
DefineComponent,
|
|
11
|
+
EffectScope,
|
|
12
|
+
effectScope,
|
|
13
|
+
isRef,
|
|
14
|
+
nextTick,
|
|
15
|
+
ref,
|
|
16
|
+
Ref,
|
|
17
|
+
Slot,
|
|
18
|
+
Slots,
|
|
19
|
+
toRaw,
|
|
20
|
+
VNode,
|
|
21
|
+
watch
|
|
22
|
+
} from 'vue';
|
|
23
|
+
import VueFragment from './VueFragment.vue';
|
|
24
|
+
import { Widget } from './Widget';
|
|
25
|
+
|
|
26
|
+
enum BehaviorName {
|
|
27
|
+
'beforeCreated' = 'beforeCreated',
|
|
28
|
+
'created' = 'created',
|
|
29
|
+
'beforeMount' = 'beforeMount',
|
|
30
|
+
'mounted' = 'mounted',
|
|
31
|
+
'beforeUpdate' = 'beforeUpdate',
|
|
32
|
+
'updated' = 'updated',
|
|
33
|
+
'activated' = 'activated',
|
|
34
|
+
'deactivated' = 'deactivated',
|
|
35
|
+
'beforeUnmount' = 'beforeUnmount',
|
|
36
|
+
'unmounted' = 'unmounted'
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export type WidgetComponent = string | ComponentOptions | DefineComponent | Component | Record<string, unknown>;
|
|
40
|
+
|
|
41
|
+
export type SetupHook =
|
|
42
|
+
| ((ctx?: void, props?: unknown, result?: unknown) => void)
|
|
43
|
+
| ((ctx?: void, props?: unknown, result?: unknown) => unknown)
|
|
44
|
+
| ((ctx?: void, props?: unknown, result?: unknown) => Promise<void>)
|
|
45
|
+
| ((ctx?: void, props?: unknown, result?: unknown) => Promise<unknown>);
|
|
46
|
+
|
|
47
|
+
export class VueWidget<Props extends WidgetProps = WidgetProps> extends Widget<Props, VNode | VNode[]> {
|
|
48
|
+
protected behaviorGroup = {};
|
|
49
|
+
|
|
50
|
+
private __render__?: (...args: unknown[]) => VNode | null;
|
|
51
|
+
|
|
52
|
+
private static beforeHooks: Map<
|
|
53
|
+
string,
|
|
54
|
+
Map<string, ((next: (args: unknown[]) => void, ...args: unknown[]) => boolean | undefined)[]>
|
|
55
|
+
> = new Map();
|
|
56
|
+
|
|
57
|
+
private static afterHooks: Map<
|
|
58
|
+
string,
|
|
59
|
+
Map<string, ((next: (result: unknown) => void, ...args: unknown[]) => boolean | undefined)[]>
|
|
60
|
+
> = new Map();
|
|
61
|
+
|
|
62
|
+
private static hookHosts: Map<Function, string[]> = new Map();
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* 通过该属性可以直接拿到Widget下Component内的属性
|
|
66
|
+
* @private
|
|
67
|
+
*/
|
|
68
|
+
private opt?: VueWidget;
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* vue实例内属性(props、computed、data)的集合
|
|
72
|
+
*/
|
|
73
|
+
private res?: {};
|
|
74
|
+
|
|
75
|
+
public revolveNodeCode() {
|
|
76
|
+
return uniqueKeyGenerator();
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
private __scope!: EffectScope | null;
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* vue组件setup
|
|
83
|
+
* @param setupHook
|
|
84
|
+
*/
|
|
85
|
+
public setup(setupHook?: SetupHook) {
|
|
86
|
+
return (ctx: void, props?: unknown) => {
|
|
87
|
+
if (this.__scope) {
|
|
88
|
+
this.__scope.stop();
|
|
89
|
+
this.__scope = null;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
this.__scope = effectScope();
|
|
93
|
+
let result = {};
|
|
94
|
+
|
|
95
|
+
this.__scope.run(() => {
|
|
96
|
+
const { opt } = this;
|
|
97
|
+
const attrs = this.getAttributes();
|
|
98
|
+
attrs.forEach((nativeName, displayName) => {
|
|
99
|
+
const compute = this.getComputeHandler(displayName);
|
|
100
|
+
if (compute) {
|
|
101
|
+
if (compute.get) {
|
|
102
|
+
if (!compute.set) {
|
|
103
|
+
Reflect.set(result, displayName, computed(compute.get!.bind(opt)));
|
|
104
|
+
} else {
|
|
105
|
+
Reflect.set(
|
|
106
|
+
result,
|
|
107
|
+
displayName,
|
|
108
|
+
computed({
|
|
109
|
+
get: compute.get!.bind(opt),
|
|
110
|
+
set: compute.set!.bind(opt)
|
|
111
|
+
})
|
|
112
|
+
);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
} else {
|
|
116
|
+
const raw = Reflect.get(this, nativeName);
|
|
117
|
+
if (typeof raw === 'function') {
|
|
118
|
+
Reflect.set(result, displayName, raw.bind(opt));
|
|
119
|
+
} else if (typeof raw === 'object' && raw) {
|
|
120
|
+
Reflect.set(result, displayName, ref(raw));
|
|
121
|
+
} else {
|
|
122
|
+
Reflect.set(result, displayName, ref(raw));
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
const watchers = this.getWatchers();
|
|
128
|
+
watchers.forEach((watcher) => {
|
|
129
|
+
const path = watcher.path.split('.');
|
|
130
|
+
const val = result[path[0]];
|
|
131
|
+
if (val) {
|
|
132
|
+
if (path.length === 1) {
|
|
133
|
+
/**
|
|
134
|
+
*如果当前要监听的值是个Object类型,那么监听的newValue跟oldValue是相等的
|
|
135
|
+
*
|
|
136
|
+
* @see {@link https://cn.vuejs.org/v2/api/#vm-watch}
|
|
137
|
+
*/
|
|
138
|
+
watch(val, watcher.handler.bind(opt), watcher.options);
|
|
139
|
+
} else {
|
|
140
|
+
watch(
|
|
141
|
+
() => {
|
|
142
|
+
let tmp = val.value || {};
|
|
143
|
+
for (let index = 1; index < path.length; index++) {
|
|
144
|
+
tmp = tmp[path[index]];
|
|
145
|
+
if (!tmp) {
|
|
146
|
+
break;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
return tmp;
|
|
150
|
+
},
|
|
151
|
+
watcher.handler.bind(opt),
|
|
152
|
+
watcher.options
|
|
153
|
+
);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
});
|
|
157
|
+
const returnResult = setupHook && (setupHook(ctx, props, result) as Record<string, unknown>);
|
|
158
|
+
returnResult && (result = { ...result, ...returnResult });
|
|
159
|
+
this.res = result;
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
return result;
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* 标记一个方法为可被钩子注入,注解使用
|
|
168
|
+
* @constructor
|
|
169
|
+
* @protected
|
|
170
|
+
*/
|
|
171
|
+
protected static HookHost() {
|
|
172
|
+
return <T extends Widget>(target: T, name: string) => {
|
|
173
|
+
const hosts: string[] = VueWidget.hookHosts.get(target.constructor) || [];
|
|
174
|
+
hosts.push(name);
|
|
175
|
+
VueWidget.hookHosts.set(target.constructor, hosts);
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* 获得组件中注册的所有钩子
|
|
181
|
+
* @param widget
|
|
182
|
+
* @private
|
|
183
|
+
*/
|
|
184
|
+
private static getHookHosts(widget: Widget) {
|
|
185
|
+
const results: string[] = [];
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* 获得对象的继承链
|
|
189
|
+
* 0: ColorPickWidget()
|
|
190
|
+
* 1: FormFieldWidget()
|
|
191
|
+
* 2: FieldWidget()
|
|
192
|
+
* 3: DslNodeWidget()
|
|
193
|
+
* 4: VueWidget()
|
|
194
|
+
* 5: Widget()
|
|
195
|
+
*/
|
|
196
|
+
const getProtoChains = (): Function[] => {
|
|
197
|
+
const chains: Function[] = [];
|
|
198
|
+
let obj = widget.constructor;
|
|
199
|
+
let { name } = obj;
|
|
200
|
+
while (name !== '') {
|
|
201
|
+
name = obj.name;
|
|
202
|
+
chains.push(obj);
|
|
203
|
+
obj = Object.getPrototypeOf(obj);
|
|
204
|
+
}
|
|
205
|
+
return chains;
|
|
206
|
+
};
|
|
207
|
+
const chains = getProtoChains();
|
|
208
|
+
chains.forEach((c) => {
|
|
209
|
+
const hosts = VueWidget.hookHosts.get(c);
|
|
210
|
+
hosts && hosts.forEach((r) => results.push(r));
|
|
211
|
+
});
|
|
212
|
+
return results;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* 获得指定组件内方法的前/后置钩子
|
|
217
|
+
* @param widgetName
|
|
218
|
+
* @param hook
|
|
219
|
+
* @param beforeOrAfter
|
|
220
|
+
* @private
|
|
221
|
+
*/
|
|
222
|
+
private static getHooks(widgetName: string, hook: string, beforeOrAfter: 'before' | 'after') {
|
|
223
|
+
const widget = Widget.select(widgetName)!;
|
|
224
|
+
const getProtoChains = <T extends Function>(obj: T) => {
|
|
225
|
+
const result: string[] = [];
|
|
226
|
+
let iterator = obj;
|
|
227
|
+
while (iterator.name !== '') {
|
|
228
|
+
result.push(iterator.name);
|
|
229
|
+
iterator = Object.getPrototypeOf(iterator);
|
|
230
|
+
}
|
|
231
|
+
return result;
|
|
232
|
+
};
|
|
233
|
+
const chains = getProtoChains(widget.constructor);
|
|
234
|
+
const hooks: ((
|
|
235
|
+
next: (...args: unknown[]) => void,
|
|
236
|
+
...args: unknown[]
|
|
237
|
+
) => boolean | undefined | Promise<boolean> | Promise<void>)[] = [];
|
|
238
|
+
chains.forEach((c) => {
|
|
239
|
+
let tahooks: Map<
|
|
240
|
+
string,
|
|
241
|
+
((
|
|
242
|
+
next: (...args: unknown[]) => void,
|
|
243
|
+
...args: unknown[]
|
|
244
|
+
) => boolean | undefined | Promise<boolean> | Promise<void>)[]
|
|
245
|
+
>;
|
|
246
|
+
if (beforeOrAfter === 'after') {
|
|
247
|
+
tahooks = VueWidget.afterHooks.get(c)!;
|
|
248
|
+
} else {
|
|
249
|
+
tahooks = VueWidget.beforeHooks.get(c)!;
|
|
250
|
+
}
|
|
251
|
+
const thooks = (tahooks && tahooks.get(hook)) || [];
|
|
252
|
+
thooks.forEach((hookHandle) => hooks.push(hookHandle));
|
|
253
|
+
});
|
|
254
|
+
return hooks;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
/**
|
|
258
|
+
* 标记一个方法为后置钩子
|
|
259
|
+
* @param host
|
|
260
|
+
* @constructor
|
|
261
|
+
* @protected
|
|
262
|
+
*/
|
|
263
|
+
protected static BeforeHook(host: string) {
|
|
264
|
+
return <T extends Widget>(
|
|
265
|
+
target: T,
|
|
266
|
+
_name: string,
|
|
267
|
+
description: TypedPropertyDescriptor<() => boolean> | TypedPropertyDescriptor<() => void>
|
|
268
|
+
) => {
|
|
269
|
+
const afterHosts = VueWidget.beforeHooks.get(target.constructor.name) || new Map();
|
|
270
|
+
const afterHooks = afterHosts.get(host) || [];
|
|
271
|
+
afterHooks.push(description.value!);
|
|
272
|
+
afterHosts.set(host, afterHooks);
|
|
273
|
+
VueWidget.beforeHooks.set(target.constructor.name, afterHosts);
|
|
274
|
+
};
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
/**
|
|
278
|
+
* 标记一个方法为前置钩子
|
|
279
|
+
* @param host
|
|
280
|
+
* @constructor
|
|
281
|
+
* @protected
|
|
282
|
+
*/
|
|
283
|
+
protected static AfterHook(host: string) {
|
|
284
|
+
return <T extends Widget>(
|
|
285
|
+
target: T,
|
|
286
|
+
_name: string,
|
|
287
|
+
description:
|
|
288
|
+
| TypedPropertyDescriptor<(next: never, ...args: unknown[]) => boolean>
|
|
289
|
+
| TypedPropertyDescriptor<(next: unknown, ...args: unknown[]) => void>
|
|
290
|
+
) => {
|
|
291
|
+
const afterHosts = VueWidget.afterHooks.get(target.constructor.name) || new Map();
|
|
292
|
+
const afterHooks = afterHosts.get(host) || [];
|
|
293
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
294
|
+
afterHooks.push(description.value!);
|
|
295
|
+
afterHosts.set(host, afterHooks);
|
|
296
|
+
VueWidget.afterHooks.set(target.constructor.name, afterHosts);
|
|
297
|
+
};
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
private component!: WidgetComponent;
|
|
301
|
+
|
|
302
|
+
@Widget.Reactive()
|
|
303
|
+
private node_code: string = this.revolveNodeCode();
|
|
304
|
+
|
|
305
|
+
public getNodeCode(): string {
|
|
306
|
+
return this.node_code;
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
public getNodeCodeRef(): Ref<number> {
|
|
310
|
+
return (this.res! as { node_code: Ref<number> }).node_code;
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
/**
|
|
314
|
+
* 获取当前组件的响应式对象
|
|
315
|
+
*/
|
|
316
|
+
public getOperator<T extends VueWidget>(): T {
|
|
317
|
+
const { opt } = this;
|
|
318
|
+
if (!opt) {
|
|
319
|
+
return this as unknown as T;
|
|
320
|
+
// throw new Error(`error: operator lost :${this.getWidgetType()}:${this.getHandle()}`);
|
|
321
|
+
}
|
|
322
|
+
return opt as T;
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
/**
|
|
326
|
+
* 在当前组件节点下创建子节点
|
|
327
|
+
* @param constructor widget
|
|
328
|
+
* @param slotName slotName
|
|
329
|
+
* @param initConfig widget中initialize函数接受的参数
|
|
330
|
+
* @param specifiedIndex 指定该widget的在父节点中的位置,默认是最后一位
|
|
331
|
+
* @param resolveNewCode 是否更新node_code
|
|
332
|
+
*/
|
|
333
|
+
public createWidget<T extends Widget>(
|
|
334
|
+
constructor: WidgetConstructor<T['config'], T>,
|
|
335
|
+
slotName?: string,
|
|
336
|
+
initConfig?: T['config'],
|
|
337
|
+
specifiedIndex?: number,
|
|
338
|
+
resolveNewCode = false
|
|
339
|
+
): T {
|
|
340
|
+
const opt = this.getOperator();
|
|
341
|
+
const widget: T = super.createWidget.bind(opt)<T>(
|
|
342
|
+
constructor,
|
|
343
|
+
slotName,
|
|
344
|
+
initConfig || ({} as T['config']),
|
|
345
|
+
specifiedIndex
|
|
346
|
+
);
|
|
347
|
+
// 不要改,兼容执行视图和mask重新渲染 拿掉if mask的重绘失效了
|
|
348
|
+
if (resolveNewCode) {
|
|
349
|
+
opt.node_code = this.revolveNodeCode();
|
|
350
|
+
}
|
|
351
|
+
const instance = widget && widget.getOperator();
|
|
352
|
+
if (specifiedIndex !== undefined && specifiedIndex >= 0) {
|
|
353
|
+
this.getChildrenInstance()[specifiedIndex] = widget.getOperator();
|
|
354
|
+
} else {
|
|
355
|
+
// fixme: widget可能为空
|
|
356
|
+
this.addChildrenInstance(instance);
|
|
357
|
+
}
|
|
358
|
+
return instance as unknown as T;
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
/**
|
|
362
|
+
* 在当前组件节点下删除子节点树
|
|
363
|
+
* @param name
|
|
364
|
+
*/
|
|
365
|
+
public deleteWidget(name: string) {
|
|
366
|
+
const result = super.deleteWidget(name);
|
|
367
|
+
const opt = this.getOperator();
|
|
368
|
+
opt.node_code = this.revolveNodeCode();
|
|
369
|
+
|
|
370
|
+
return result;
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
/**
|
|
374
|
+
* 给指定的下标插入widget
|
|
375
|
+
*
|
|
376
|
+
* 如果要在最后一位插入,可以用createWidget
|
|
377
|
+
*
|
|
378
|
+
* @param {Widget} widget
|
|
379
|
+
* @param {number} index
|
|
380
|
+
*/
|
|
381
|
+
public insertWidget(widget: Widget, index: number) {
|
|
382
|
+
super.insertWidget(widget, index);
|
|
383
|
+
const opt = this.getOperator();
|
|
384
|
+
opt.node_code = this.revolveNodeCode();
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
/**
|
|
388
|
+
* 移动widget, 将widget从 A 下标移动到 B 下标
|
|
389
|
+
*
|
|
390
|
+
* @param {number} index1
|
|
391
|
+
* @param {number} index2
|
|
392
|
+
*/
|
|
393
|
+
public moveChildWidget(index1: number, index2: number) {
|
|
394
|
+
super.moveChildWidget(index1, index2);
|
|
395
|
+
const opt = this.getOperator();
|
|
396
|
+
opt.node_code = this.revolveNodeCode();
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
/**
|
|
400
|
+
* 根据下标删除对应的child widget, 如果当前 children中有重复的handler,那么会删除匹配的第一个
|
|
401
|
+
*
|
|
402
|
+
* @param {number} index
|
|
403
|
+
* @param {string} handle?
|
|
404
|
+
*/
|
|
405
|
+
public deleteWidgetByIndex(index: number, handle?: string) {
|
|
406
|
+
const result = super.deleteWidgetByIndex(index, handle);
|
|
407
|
+
const opt = this.getOperator();
|
|
408
|
+
opt.node_code = this.revolveNodeCode();
|
|
409
|
+
|
|
410
|
+
return result;
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
/**
|
|
414
|
+
* 初始化当前组件
|
|
415
|
+
* @param props
|
|
416
|
+
*/
|
|
417
|
+
public initialize(props: Props = {} as Props): VueWidget {
|
|
418
|
+
super.initialize(props);
|
|
419
|
+
this.component = VueFragment;
|
|
420
|
+
this.buildOperator();
|
|
421
|
+
/* IFDEBUG */
|
|
422
|
+
// console.debug(`${this.getWidgetType()}:initialize`);
|
|
423
|
+
/* FIDEBUG */
|
|
424
|
+
return this;
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
private buildOperator(): VueWidget {
|
|
428
|
+
const operator = new Proxy(this, {
|
|
429
|
+
get: (target, key: string | symbol) => {
|
|
430
|
+
if (key === 'isProxy') {
|
|
431
|
+
return true;
|
|
432
|
+
}
|
|
433
|
+
if (key === 'constructor') {
|
|
434
|
+
return this.constructor;
|
|
435
|
+
}
|
|
436
|
+
const result = this.res || {};
|
|
437
|
+
const res = Reflect.get(result, key);
|
|
438
|
+
if (res) {
|
|
439
|
+
if (isRef(res)) {
|
|
440
|
+
if (typeof res.value === 'object') {
|
|
441
|
+
return res.value;
|
|
442
|
+
}
|
|
443
|
+
return res.value;
|
|
444
|
+
}
|
|
445
|
+
return res;
|
|
446
|
+
}
|
|
447
|
+
return Reflect.get(target, key);
|
|
448
|
+
},
|
|
449
|
+
set: (target, key: string | symbol, value: unknown) => {
|
|
450
|
+
const result = this.res || {};
|
|
451
|
+
const res = Reflect.get(result, key);
|
|
452
|
+
if (typeof res === 'function') {
|
|
453
|
+
return Reflect.set(result, key, value);
|
|
454
|
+
}
|
|
455
|
+
if (isRef(res)) {
|
|
456
|
+
res.value = value;
|
|
457
|
+
return true;
|
|
458
|
+
}
|
|
459
|
+
return Reflect.set(target, key, value);
|
|
460
|
+
}
|
|
461
|
+
});
|
|
462
|
+
this.opt = operator;
|
|
463
|
+
this.initialize = this.initialize.bind(operator);
|
|
464
|
+
|
|
465
|
+
const hosts = VueWidget.getHookHosts(this);
|
|
466
|
+
hosts.forEach((hookName) => {
|
|
467
|
+
const host = Reflect.get(this, hookName);
|
|
468
|
+
Reflect.set(this, hookName, (...args: unknown[]) => {
|
|
469
|
+
if (hookName === 'render') {
|
|
470
|
+
return host.apply(operator, args);
|
|
471
|
+
}
|
|
472
|
+
const _args = operator.executeBeforeHooks(hookName, args);
|
|
473
|
+
const result = host.apply(operator, _args);
|
|
474
|
+
return operator.executeAfterHooks(hookName, result);
|
|
475
|
+
});
|
|
476
|
+
});
|
|
477
|
+
return operator;
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
/**
|
|
481
|
+
* Class Component Vue组件
|
|
482
|
+
* @private
|
|
483
|
+
*/
|
|
484
|
+
private widgetComponent: Component | undefined;
|
|
485
|
+
|
|
486
|
+
/**
|
|
487
|
+
* 获取Class Component Vue组件
|
|
488
|
+
*/
|
|
489
|
+
public getWidgetComponent(isBuild = false): Component | undefined {
|
|
490
|
+
let component = this.widgetComponent;
|
|
491
|
+
if (!component && isBuild) {
|
|
492
|
+
component = this.buildWidgetComponent();
|
|
493
|
+
this.widgetComponent = component;
|
|
494
|
+
}
|
|
495
|
+
return component;
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
/**
|
|
499
|
+
* 设置Class Component Vue组件
|
|
500
|
+
* @param component Vue组件
|
|
501
|
+
*/
|
|
502
|
+
public setWidgetComponent(component: Component | undefined) {
|
|
503
|
+
this.widgetComponent = component;
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
/**
|
|
507
|
+
* 扩展组件
|
|
508
|
+
*/
|
|
509
|
+
public renderExpandComponent(): Component | VNode | undefined {
|
|
510
|
+
return undefined;
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
/**
|
|
514
|
+
* 混入组件
|
|
515
|
+
* @private
|
|
516
|
+
*/
|
|
517
|
+
private mixinComponent: Component | undefined;
|
|
518
|
+
|
|
519
|
+
/**
|
|
520
|
+
* 获取混入组件
|
|
521
|
+
*/
|
|
522
|
+
public getMixinComponent() {
|
|
523
|
+
return this.mixinComponent;
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
/**
|
|
527
|
+
* 设置混入组件
|
|
528
|
+
* @param component Vue组件
|
|
529
|
+
* @protected
|
|
530
|
+
*/
|
|
531
|
+
public setMixinComponent(component: Component | undefined) {
|
|
532
|
+
if (component) {
|
|
533
|
+
component = {
|
|
534
|
+
inheritAttrs: false,
|
|
535
|
+
...component
|
|
536
|
+
};
|
|
537
|
+
}
|
|
538
|
+
this.mixinComponent = component;
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
/**
|
|
542
|
+
* 渲染当前组件
|
|
543
|
+
* @param context 渲染上下文
|
|
544
|
+
* @param slots 插槽
|
|
545
|
+
*/
|
|
546
|
+
@VueWidget.HookHost()
|
|
547
|
+
public render(context?: Record<string, unknown>, slots?: Slots): VNode | VNode[] {
|
|
548
|
+
if (!this.widgetComponent) {
|
|
549
|
+
this.widgetComponent = this.buildWidgetComponent();
|
|
550
|
+
}
|
|
551
|
+
if (!this.widgetComponent) {
|
|
552
|
+
return [];
|
|
553
|
+
}
|
|
554
|
+
return this.renderWidgetComponent(this.widgetComponent, context, slots);
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
protected getWidgetComponentName() {
|
|
558
|
+
const { name } = this.constructor;
|
|
559
|
+
return name;
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
/**
|
|
563
|
+
* 构造Vue组件
|
|
564
|
+
* @protected
|
|
565
|
+
*/
|
|
566
|
+
protected buildWidgetComponent(): Component | undefined {
|
|
567
|
+
let component = this.getComponent();
|
|
568
|
+
if (!component) {
|
|
569
|
+
return undefined;
|
|
570
|
+
}
|
|
571
|
+
component = toRaw(component);
|
|
572
|
+
// const setup: any = this.setup(this.setupHook.bind(this));
|
|
573
|
+
|
|
574
|
+
const opt = this.getOperator();
|
|
575
|
+
const extendComponents = this.getUsingComponents();
|
|
576
|
+
return defineComponent({
|
|
577
|
+
name: this.getWidgetComponentName(),
|
|
578
|
+
components: extendComponents,
|
|
579
|
+
inheritAttrs: false,
|
|
580
|
+
setup: this.setup(this.setupHook.bind(this)) as any,
|
|
581
|
+
beforeMount: () => {
|
|
582
|
+
this.behaviorGroup[BehaviorName.beforeMount]?.();
|
|
583
|
+
this.$$beforeMount.call(opt);
|
|
584
|
+
this.beforeMount.call(opt);
|
|
585
|
+
},
|
|
586
|
+
mounted: () => {
|
|
587
|
+
this.behaviorGroup[BehaviorName.mounted]?.();
|
|
588
|
+
this.$$mounted.call(opt);
|
|
589
|
+
this.mounted.call(opt);
|
|
590
|
+
},
|
|
591
|
+
beforeUpdate: () => {
|
|
592
|
+
this.behaviorGroup[BehaviorName.beforeUpdate]?.();
|
|
593
|
+
this.$$beforeUpdate.call(opt);
|
|
594
|
+
this.beforeUpdate.call(opt);
|
|
595
|
+
},
|
|
596
|
+
updated: () => {
|
|
597
|
+
this.behaviorGroup[BehaviorName.updated]?.();
|
|
598
|
+
this.$$updated.call(opt);
|
|
599
|
+
this.updated.call(opt);
|
|
600
|
+
},
|
|
601
|
+
activated: () => {
|
|
602
|
+
this.behaviorGroup[BehaviorName.activated]?.();
|
|
603
|
+
this.$$activated.call(opt);
|
|
604
|
+
this.activated.call(opt);
|
|
605
|
+
},
|
|
606
|
+
deactivated: () => {
|
|
607
|
+
this.behaviorGroup[BehaviorName.deactivated]?.();
|
|
608
|
+
this.$$deactivated.call(opt);
|
|
609
|
+
this.deactivated.call(opt);
|
|
610
|
+
},
|
|
611
|
+
beforeUnmount: () => {
|
|
612
|
+
this.behaviorGroup[BehaviorName.beforeUnmount]?.();
|
|
613
|
+
this.$$beforeUnmount.call(opt);
|
|
614
|
+
this.beforeUnmount.call(opt);
|
|
615
|
+
},
|
|
616
|
+
unmounted: () => {
|
|
617
|
+
this.behaviorGroup[BehaviorName.unmounted]?.();
|
|
618
|
+
this.unmounted.call(opt);
|
|
619
|
+
this.$$unmounted.call(opt);
|
|
620
|
+
this.$$unmountedAfterProperties.call(opt);
|
|
621
|
+
},
|
|
622
|
+
render: (ctx: ComponentPublicInstance & Record<string, unknown>) => {
|
|
623
|
+
const props = this.buildProps(ctx);
|
|
624
|
+
const { $slots } = ctx;
|
|
625
|
+
const componentProps = this.resolveProps(component, props);
|
|
626
|
+
|
|
627
|
+
const children = $slots && Object.keys($slots).length ? $slots : this.resolveChildren();
|
|
628
|
+
|
|
629
|
+
const expandCom = this.renderExpandComponent() as VNode;
|
|
630
|
+
const expandSlot = {} as Record<string, any>;
|
|
631
|
+
|
|
632
|
+
if (expandCom) {
|
|
633
|
+
const defaultSlotContent = children.default ? children.default() : [];
|
|
634
|
+
expandSlot.default = () => [...defaultSlotContent, expandCom];
|
|
635
|
+
}
|
|
636
|
+
|
|
637
|
+
return this.renderMixinComponent(
|
|
638
|
+
createVNode(component, componentProps, {
|
|
639
|
+
...children,
|
|
640
|
+
...expandSlot
|
|
641
|
+
}),
|
|
642
|
+
props
|
|
643
|
+
);
|
|
644
|
+
}
|
|
645
|
+
});
|
|
646
|
+
}
|
|
647
|
+
|
|
648
|
+
/**
|
|
649
|
+
* 只获取vue 组件需要的props
|
|
650
|
+
*
|
|
651
|
+
*/
|
|
652
|
+
protected resolveProps(component, props) {
|
|
653
|
+
return props;
|
|
654
|
+
// TODO 由于很多组件内部使用了$attrs, 需要先把$attrs替换成对应的props,再使用下面的代码,性能可提升20%
|
|
655
|
+
// const componentProps = (component as VNode).props || {};
|
|
656
|
+
// const keys = Array.isArray(componentProps) ? componentProps : Object.keys(componentProps);
|
|
657
|
+
|
|
658
|
+
// if (component.mixins && component.mixins.length) {
|
|
659
|
+
// keys.push(...component.mixins.map((mixin) => Object.keys(mixin.props || {})));
|
|
660
|
+
// }
|
|
661
|
+
|
|
662
|
+
// return keys.reduce((acc, key) => ({ ...acc, [key]: props[key] }), {});
|
|
663
|
+
}
|
|
664
|
+
|
|
665
|
+
/**
|
|
666
|
+
* 渲染混入组件
|
|
667
|
+
* @param vNode 当前Vue组件渲染节点
|
|
668
|
+
* @param props 当前Vue组件渲染属性
|
|
669
|
+
* @protected
|
|
670
|
+
*/
|
|
671
|
+
protected renderMixinComponent(vNode: VNode, props: Record<string, unknown>): VNode | VNode[] {
|
|
672
|
+
const mixinComponent = this.getMixinComponent();
|
|
673
|
+
if (mixinComponent) {
|
|
674
|
+
const finalVNode = vNode;
|
|
675
|
+
const realProps = this.resolveProps(mixinComponent, props);
|
|
676
|
+
vNode = createVNode(mixinComponent, realProps, { default: () => finalVNode });
|
|
677
|
+
}
|
|
678
|
+
return vNode;
|
|
679
|
+
}
|
|
680
|
+
|
|
681
|
+
/**
|
|
682
|
+
* 渲染当前组件
|
|
683
|
+
* @param widgetComponent 当前组件
|
|
684
|
+
* @param context 组件上下文
|
|
685
|
+
* @param slots 组件插槽
|
|
686
|
+
* @protected
|
|
687
|
+
*/
|
|
688
|
+
protected renderWidgetComponent(widgetComponent: Component, context?: Record<string, unknown>, slots?: Slots): VNode {
|
|
689
|
+
return createVNode(widgetComponent, {}, slots);
|
|
690
|
+
}
|
|
691
|
+
|
|
692
|
+
/**
|
|
693
|
+
* 构建当前组件渲染vue组件传递时的props
|
|
694
|
+
* @param result
|
|
695
|
+
* @protected
|
|
696
|
+
*/
|
|
697
|
+
protected buildProps(result: Record<string, unknown>) {
|
|
698
|
+
const props: Record<string, unknown> = {};
|
|
699
|
+
|
|
700
|
+
const attrs = this.getAttributes();
|
|
701
|
+
|
|
702
|
+
const propStrs = this.getProps();
|
|
703
|
+
attrs.forEach((displayName, nativeName) => {
|
|
704
|
+
if (propStrs.includes(displayName)) {
|
|
705
|
+
Reflect.set(props, displayName, Reflect.get(result, nativeName));
|
|
706
|
+
}
|
|
707
|
+
});
|
|
708
|
+
props['data-handle'] = this.getHandle();
|
|
709
|
+
return props;
|
|
710
|
+
}
|
|
711
|
+
|
|
712
|
+
protected buildPropsStrs(): string[] {
|
|
713
|
+
const attrs = this.getProps();
|
|
714
|
+
const props: string[] = [];
|
|
715
|
+
attrs.forEach((key) => props.push(key));
|
|
716
|
+
return props;
|
|
717
|
+
}
|
|
718
|
+
|
|
719
|
+
/**
|
|
720
|
+
* 将当前组件的子组件树解析为Vue Slots树
|
|
721
|
+
* @protected
|
|
722
|
+
*/
|
|
723
|
+
protected resolveChildren(): Record<string, Slot> {
|
|
724
|
+
const result = {};
|
|
725
|
+
const slots: string[] = [];
|
|
726
|
+
const children = this.getChildren();
|
|
727
|
+
children.forEach((c) => {
|
|
728
|
+
if (!slots.includes(c.getName())) {
|
|
729
|
+
slots.push(c.getName());
|
|
730
|
+
}
|
|
731
|
+
});
|
|
732
|
+
slots.forEach((s) => {
|
|
733
|
+
Reflect.set(result, s, (...args: unknown[]) =>
|
|
734
|
+
children.filter((c) => c.getName() === s).map((c) => c.render(...args))
|
|
735
|
+
);
|
|
736
|
+
});
|
|
737
|
+
return result;
|
|
738
|
+
}
|
|
739
|
+
|
|
740
|
+
/**
|
|
741
|
+
* Vue组件setup方法钩子
|
|
742
|
+
* @param _ctx
|
|
743
|
+
* @param _props
|
|
744
|
+
* @param _result
|
|
745
|
+
* @protected
|
|
746
|
+
*/
|
|
747
|
+
protected setupHook(_ctx: void, _props: unknown, _result: unknown): unknown {
|
|
748
|
+
this.behaviorGroup[BehaviorName.beforeCreated]?.();
|
|
749
|
+
this.$$beforeCreated();
|
|
750
|
+
this.beforeCreated();
|
|
751
|
+
this.behaviorGroup[BehaviorName.created]?.();
|
|
752
|
+
this.$$created();
|
|
753
|
+
this.created();
|
|
754
|
+
return {};
|
|
755
|
+
}
|
|
756
|
+
|
|
757
|
+
/**
|
|
758
|
+
* 绑定一个标准的Vue组件或者一个html标签用于当前组件的渲染
|
|
759
|
+
* @param component
|
|
760
|
+
*/
|
|
761
|
+
public setComponent(component: WidgetComponent) {
|
|
762
|
+
this.component = {
|
|
763
|
+
inheritAttrs: false,
|
|
764
|
+
...(component as Component)
|
|
765
|
+
};
|
|
766
|
+
}
|
|
767
|
+
|
|
768
|
+
/**
|
|
769
|
+
* 销毁当前组件
|
|
770
|
+
*/
|
|
771
|
+
public dispose(force = false) {
|
|
772
|
+
super.dispose(force);
|
|
773
|
+
this.opt = undefined;
|
|
774
|
+
|
|
775
|
+
const empty = null as any;
|
|
776
|
+
|
|
777
|
+
if (this.__scope) {
|
|
778
|
+
this.__scope.stop();
|
|
779
|
+
this.__scope = empty;
|
|
780
|
+
}
|
|
781
|
+
this.component = empty;
|
|
782
|
+
this.mixinComponent = empty;
|
|
783
|
+
this.widgetComponent = empty;
|
|
784
|
+
|
|
785
|
+
/**
|
|
786
|
+
* 销毁 响应式依赖收集、原型链的属性、事件
|
|
787
|
+
*/
|
|
788
|
+
if (force) {
|
|
789
|
+
nextTick(() => {
|
|
790
|
+
this.res = {};
|
|
791
|
+
(this as any).__proto__ = null;
|
|
792
|
+
});
|
|
793
|
+
}
|
|
794
|
+
}
|
|
795
|
+
|
|
796
|
+
/**
|
|
797
|
+
* 获取当前组件渲染时使用的Vue组件
|
|
798
|
+
* @public
|
|
799
|
+
*/
|
|
800
|
+
public getComponent() {
|
|
801
|
+
const { name, __render__, __name__ } = this.constructor as Function & { __render__: Function; __name__: string };
|
|
802
|
+
if (!!__render__) {
|
|
803
|
+
this.component = defineComponent({
|
|
804
|
+
name: __name__ || name,
|
|
805
|
+
props: this.buildPropsStrs(),
|
|
806
|
+
render: __render__,
|
|
807
|
+
components: this.getUsingComponents()
|
|
808
|
+
});
|
|
809
|
+
}
|
|
810
|
+
return this.component;
|
|
811
|
+
}
|
|
812
|
+
|
|
813
|
+
/**
|
|
814
|
+
* 获取当前组件引用的其他Vue组件
|
|
815
|
+
* @protected
|
|
816
|
+
*/
|
|
817
|
+
protected getUsingComponents(): Record<string, Component> {
|
|
818
|
+
return {};
|
|
819
|
+
}
|
|
820
|
+
|
|
821
|
+
private executeAfterHooks(name: string, result: unknown) {
|
|
822
|
+
const hooks = VueWidget.getHooks(this.getHandle(), name, 'after');
|
|
823
|
+
let index = 0;
|
|
824
|
+
const res = { result };
|
|
825
|
+
const next = () => {
|
|
826
|
+
index < hooks.length && hooks[index++].apply(this, [next, res]);
|
|
827
|
+
};
|
|
828
|
+
next();
|
|
829
|
+
return res.result;
|
|
830
|
+
}
|
|
831
|
+
|
|
832
|
+
private executeBeforeHooks(name: string, ...args: unknown[]) {
|
|
833
|
+
const hooks = VueWidget.getHooks(this.getHandle(), name, 'before');
|
|
834
|
+
let index = 0;
|
|
835
|
+
const _args = { args };
|
|
836
|
+
const next = () => {
|
|
837
|
+
index < hooks.length && hooks[index++].apply(this, [next, _args]);
|
|
838
|
+
};
|
|
839
|
+
next();
|
|
840
|
+
return _args.args;
|
|
841
|
+
}
|
|
842
|
+
|
|
843
|
+
/**
|
|
844
|
+
* Vue钩子
|
|
845
|
+
* @protected
|
|
846
|
+
*/
|
|
847
|
+
protected beforeCreated() {}
|
|
848
|
+
|
|
849
|
+
/**
|
|
850
|
+
* @internal
|
|
851
|
+
*/
|
|
852
|
+
protected $$beforeCreated() {}
|
|
853
|
+
|
|
854
|
+
/**
|
|
855
|
+
* Vue钩子
|
|
856
|
+
* @protected
|
|
857
|
+
*/
|
|
858
|
+
protected created() {}
|
|
859
|
+
|
|
860
|
+
/**
|
|
861
|
+
* @internal
|
|
862
|
+
*/
|
|
863
|
+
protected $$created() {}
|
|
864
|
+
|
|
865
|
+
/**
|
|
866
|
+
* Vue钩子
|
|
867
|
+
* @protected
|
|
868
|
+
*/
|
|
869
|
+
protected beforeMount() {}
|
|
870
|
+
|
|
871
|
+
/**
|
|
872
|
+
* @internal
|
|
873
|
+
*/
|
|
874
|
+
protected $$beforeMount() {}
|
|
875
|
+
|
|
876
|
+
/**
|
|
877
|
+
* Vue钩子
|
|
878
|
+
* @protected
|
|
879
|
+
*/
|
|
880
|
+
protected mounted() {}
|
|
881
|
+
|
|
882
|
+
/**
|
|
883
|
+
* @internal
|
|
884
|
+
*/
|
|
885
|
+
protected $$mounted() {}
|
|
886
|
+
|
|
887
|
+
/**
|
|
888
|
+
* Vue钩子
|
|
889
|
+
* @protected
|
|
890
|
+
*/
|
|
891
|
+
protected beforeUpdate() {}
|
|
892
|
+
|
|
893
|
+
/**
|
|
894
|
+
* @internal
|
|
895
|
+
*/
|
|
896
|
+
protected $$beforeUpdate() {}
|
|
897
|
+
|
|
898
|
+
/**
|
|
899
|
+
* Vue钩子
|
|
900
|
+
* @protected
|
|
901
|
+
*/
|
|
902
|
+
protected updated() {}
|
|
903
|
+
|
|
904
|
+
/**
|
|
905
|
+
* @internal
|
|
906
|
+
*/
|
|
907
|
+
protected $$updated() {}
|
|
908
|
+
|
|
909
|
+
/**
|
|
910
|
+
* Vue钩子
|
|
911
|
+
* @protected
|
|
912
|
+
*/
|
|
913
|
+
protected activated() {}
|
|
914
|
+
|
|
915
|
+
/**
|
|
916
|
+
* @internal
|
|
917
|
+
*/
|
|
918
|
+
protected $$activated() {}
|
|
919
|
+
|
|
920
|
+
/**
|
|
921
|
+
* Vue钩子
|
|
922
|
+
* @protected
|
|
923
|
+
*/
|
|
924
|
+
protected deactivated() {}
|
|
925
|
+
|
|
926
|
+
/**
|
|
927
|
+
* @internal
|
|
928
|
+
*/
|
|
929
|
+
protected $$deactivated() {}
|
|
930
|
+
|
|
931
|
+
/**
|
|
932
|
+
* Vue钩子
|
|
933
|
+
* @protected
|
|
934
|
+
*/
|
|
935
|
+
protected beforeUnmount() {}
|
|
936
|
+
|
|
937
|
+
/**
|
|
938
|
+
* @internal
|
|
939
|
+
*/
|
|
940
|
+
protected $$beforeUnmount() {}
|
|
941
|
+
|
|
942
|
+
/**
|
|
943
|
+
* Vue钩子
|
|
944
|
+
* @protected
|
|
945
|
+
*/
|
|
946
|
+
protected unmounted() {}
|
|
947
|
+
|
|
948
|
+
/**
|
|
949
|
+
* @internal
|
|
950
|
+
*/
|
|
951
|
+
protected $$unmounted() {}
|
|
952
|
+
|
|
953
|
+
protected $$unmountedAfterProperties() {
|
|
954
|
+
this.dispose();
|
|
955
|
+
}
|
|
956
|
+
|
|
957
|
+
public registryBehavior(name: keyof typeof BehaviorName, cb: () => void) {
|
|
958
|
+
this.behaviorGroup[name] = cb;
|
|
959
|
+
}
|
|
960
|
+
|
|
961
|
+
protected reset() {
|
|
962
|
+
this.widgetComponent = undefined;
|
|
963
|
+
(this.getParent() as VueWidget).node_code = this.revolveNodeCode();
|
|
964
|
+
}
|
|
965
|
+
|
|
966
|
+
@Widget.Reactive()
|
|
967
|
+
protected translate(key, values: { [key: string]: any } = {}): string {
|
|
968
|
+
const translate = Reflect.get(window, 'translate');
|
|
969
|
+
|
|
970
|
+
const result = translate ? translate(key) : '';
|
|
971
|
+
|
|
972
|
+
if (result === key || Object.keys(values).length === 0) {
|
|
973
|
+
return result;
|
|
974
|
+
}
|
|
975
|
+
|
|
976
|
+
const regExp = /\{\s*([A-Z0-9_]+)\s*\}/gi;
|
|
977
|
+
|
|
978
|
+
return result.replace(regExp, (matched: string, k: string): string => values[k]);
|
|
979
|
+
}
|
|
980
|
+
|
|
981
|
+
@Widget.Reactive()
|
|
982
|
+
protected translateByI18n(key: string): string {
|
|
983
|
+
return translateValueByKey(key) || key;
|
|
984
|
+
}
|
|
985
|
+
|
|
986
|
+
@Widget.Method()
|
|
987
|
+
protected genStaticPath(resourceName: string) {
|
|
988
|
+
return genStaticPath(resourceName);
|
|
989
|
+
}
|
|
990
|
+
|
|
991
|
+
public forceUpdate() {
|
|
992
|
+
const opt = this.getOperator();
|
|
993
|
+
if (opt) {
|
|
994
|
+
opt.node_code = this.revolveNodeCode();
|
|
995
|
+
}
|
|
996
|
+
}
|
|
997
|
+
}
|