@truenewx/tnxvue3 3.4.1 → 3.4.3

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/src/tnxvue.js DELETED
@@ -1,426 +0,0 @@
1
- // tnxvue.js
2
- /**
3
- * 基于Vue 3的扩展支持
4
- */
5
- import tnxcore from '../../tnxcore/src/tnxcore';
6
- import validator from './tnxvue-validator';
7
- import createRouter from './tnxvue-router';
8
- import Text from './text/Text.vue';
9
- import Percent from './percent/Percent.vue';
10
- import CaptchaVerify from './aj-captcha/Verify.vue';
11
- import * as Vue from 'vue';
12
- import mitt from 'mitt';
13
- import './tnxvue.css';
14
-
15
- export const build = tnxcore.build;
16
-
17
- export default build('tnxvue', () => {
18
- const tnxvue = Object.assign({}, tnxcore, {
19
- components: {
20
- Div: {
21
- name: 'TnxvueDiv',
22
- template: '<div><slot></slot></div>'
23
- },
24
- Span: {
25
- name: 'TnxvueSpan',
26
- template: '<span><slot></slot></span>'
27
- },
28
- Text,
29
- Percent,
30
- CaptchaVerify,
31
- },
32
- router: {
33
- instance: null,
34
- create(VueRouter, menu, fnImportPage) {
35
- return createRouter(VueRouter, menu, fnImportPage);
36
- },
37
- beforeLeave(router, from) {
38
- window.tnx.app.page.stopCache(router, from.path);
39
- }
40
- },
41
- /**
42
- * 深度监听指定对象,在created()中调用才能生效
43
- * @param vm 页面vue实例
44
- * @param target 要监听的对象
45
- * @param handler 处理函数
46
- */
47
- deepWatch(vm, target, handler) {
48
- vm.$watch(() => {
49
- try {
50
- return JSON.stringify(target);
51
- } catch (e) {
52
- console.error(e);
53
- }
54
- return undefined;
55
- }, (newValue, oldValue) => {
56
- try {
57
- if (newValue !== oldValue) {
58
- const newObject = JSON.parse(newValue);
59
- const oldObject = JSON.parse(oldValue);
60
- this.deepCompare(newObject, oldObject, '', handler);
61
- }
62
- } catch (e) {
63
- console.error(e);
64
- }
65
- }, {deep: true});
66
- },
67
- deepCompare(object1, object2, path = '', handler) {
68
- if (object1) {
69
- const keys = Object.keys(object1);
70
- keys.forEach(key => {
71
- const fullPath = path ? `${path}.${key}` : key;
72
- if (object2) {
73
- if (Array.isArray(object1[key]) && Array.isArray(object2[key])) {
74
- object1[key].forEach((item, index) => {
75
- this.deepCompare(item, object2[key][index], `${fullPath}[${index}]`, handler);
76
- });
77
- } else if (typeof object1[key] === 'object' && typeof object2[key] === 'object') {
78
- this.deepCompare(object1[key], object2[key], fullPath, handler);
79
- } else if (object1[key] !== object2[key]) {
80
- handler(object1[key], object2[key], fullPath);
81
- }
82
- } else {
83
- handler(object1[key], undefined, fullPath);
84
- }
85
- });
86
- }
87
- },
88
- createVueInstance(rootComponent, router, rootProps) {
89
- let vm = Vue.createApp(rootComponent, rootProps);
90
- vm.use(this);
91
- if (router) {
92
- vm.use(router);
93
- router.app = window.tnx.app;
94
- window.tnx.router.instance = vm.config.globalProperties.$router;
95
- } else if (window.tnx.router.instance) {
96
- vm.config.globalProperties.$router = window.tnx.router.instance;
97
- }
98
-
99
- if (!window.tnx.app.eventBus) {
100
- window.tnx.app.eventBus = window.tnx.app.eventBus || mitt();
101
- window.tnx.app.eventBus.once = function (name, handler) {
102
- this.all.set(name, [handler]);
103
- }
104
- }
105
-
106
- return vm;
107
- },
108
- install(vm) {
109
- for (let key of Object.keys(this.components)) {
110
- const component = this.components[key];
111
- vm.component(component.name, component);
112
- }
113
- },
114
- nextTickTimeout(vm, handler, timeout) {
115
- vm.$nextTick(() => {
116
- setTimeout(handler, timeout);
117
- });
118
- },
119
- dialog(content, title, buttons, options, contentProps) {
120
- // 默认不实现,由UI框架扩展层实现
121
- throw new Error('Unsupported function');
122
- },
123
- drawer(content, title, buttons, options, contentProps) {
124
- // 默认不实现,由UI框架扩展层实现
125
- throw new Error('Unsupported function');
126
- },
127
- open(component, props, options) {
128
- options = options || {};
129
-
130
- let mode = options.mode;
131
- if (component.methods) {
132
- if (component.methods.dialog) {
133
- options = Object.assign({}, component.methods.dialog(props), options);
134
- } else if (component.methods.drawer) {
135
- options = Object.assign({}, component.methods.drawer(props), options);
136
- mode = 'drawer';
137
- }
138
- }
139
-
140
- const title = component.title || options.title;
141
- const buttons = options.buttons || this.getDefaultDialogButtons(options.type, options.click, options.theme);
142
- if (options.buttonText) {
143
- if (!Array.isArray(options.buttonText)) {
144
- options.buttonText = [options.buttonText];
145
- }
146
- for (let i = 0; i < buttons.length; i++) {
147
- let buttonText = options.buttonText[i];
148
- if (buttonText) {
149
- buttons[i].text = buttonText;
150
- }
151
- }
152
- }
153
- delete options.mode;
154
- delete options.title;
155
- delete options.type;
156
- delete options.click;
157
- if (mode === 'drawer') {
158
- return this.drawer(component, title, buttons, options, props);
159
- }
160
- return this.dialog(component, title, buttons, options, props);
161
- },
162
- getDefaultDialogButtons(type, click, theme) {
163
- if (click !== false) {
164
- if (type === 'none') {
165
- return [];
166
- } else if (type === 'confirm') {
167
- return [{
168
- text: '确定',
169
- type: theme || 'primary',
170
- click(close) {
171
- if (typeof click === 'function') {
172
- return click.call(this, true, close);
173
- }
174
- }
175
- }, {
176
- text: '取消',
177
- click(close) {
178
- if (typeof click === 'function') {
179
- return click.call(this, false, close);
180
- }
181
- }
182
- }];
183
- } else if (type === 'close') {
184
- return [{
185
- text: '关闭',
186
- type: theme,
187
- click(close) {
188
- if (typeof click === 'function') {
189
- return click.call(this, close);
190
- }
191
- }
192
- }];
193
- } else {
194
- return [{
195
- text: '确定',
196
- type: theme || 'primary',
197
- click(close) {
198
- if (typeof click === 'function') {
199
- return click.call(this, close);
200
- }
201
- }
202
- }];
203
- }
204
- }
205
- return [];
206
- },
207
- });
208
-
209
- tnxvue.libs.Vue = Vue;
210
-
211
- Object.assign(tnxvue.util, {
212
- /**
213
- * 判断指定对象是否组件实例
214
- * @param obj 对象
215
- * @returns {boolean} 是否组件实例
216
- */
217
- isComponent: function (obj) {
218
- return (typeof obj === 'object') && (typeof obj.render === 'function');
219
- }
220
- });
221
-
222
- tnxvue.app.isProduction = function () {
223
- try {
224
- return !(process && process.env && process.env.NODE_ENV !== 'production');
225
- } catch (e) {
226
- // process未定义时会出错,此时为生产模式
227
- return true;
228
- }
229
- };
230
-
231
- tnxvue.app.toDevUrl = function (url, portIndex, replacement) {
232
- if (!this.isProduction()) {
233
- let index = url.indexOf(':', url.indexOf('//'));
234
- if (index > 0) { // 必须带有端口号才可替换
235
- let prefix = url.substring(0, index + 1); // 端口号之前的部分
236
- portIndex = portIndex || 1; // 开发环境端口与正式环境端口不同点的位置,如:8080之于8880,则portIndex为1
237
- replacement = replacement || '0'; // 开发环境端口在不同于正式环境端口位置要替代的值,如8080之于8880,则replacement为'0'
238
-
239
- let path = ''; // 路由路径
240
- let wellIndex = url.indexOf('#');
241
- if (wellIndex > 0) { // 如果有路由路径,则将url拆成两部分,以便于后续处理
242
- path = url.substring(wellIndex);
243
- url = url.substring(0, wellIndex);
244
- }
245
- // 开发环境路径不包含contextPath,去掉url中的contenxtPath
246
- let replaceEndIndex = prefix.length + portIndex + 1;
247
- let slashIndex = url.indexOf('/', prefix.length);
248
- url = url.substring(0, prefix.length + portIndex) + replacement
249
- + url.substring(replaceEndIndex, slashIndex > replaceEndIndex ? slashIndex : undefined) + path;
250
- }
251
- }
252
- return url;
253
- }
254
-
255
- // 元数据到async-validator组件规则的转换处理
256
- tnxvue.app.validator = validator;
257
- tnxvue.app.rpc.getMeta =
258
- tnxvue.util.function.around(tnxvue.app.rpc.getMeta, function (getMeta, url, callback, app) {
259
- return getMeta.call(tnxvue.app.rpc, url, function (meta) {
260
- if (meta) { // meta已被缓存,所以直接修改其内容,以便同步缓存
261
- meta.$rules = validator.getRules(meta);
262
- if (typeof callback === 'function') {
263
- callback.call(this, meta);
264
- }
265
- }
266
- }, app);
267
- });
268
-
269
- Object.assign(tnxvue.app.page, {
270
- // TODO 路由缓存迁移至tnxvue-router.js中
271
- startCache: function (router, model, intervalMillis, ignoredFields) {
272
- if (localStorage && intervalMillis && intervalMillis > 1000) { // 缓存间隔必须超过1秒
273
- let path = this._readCache(router, undefined, function (cache) {
274
- Object.assign(model, cache.model);
275
- });
276
-
277
- if (path) {
278
- let _this = this;
279
- let intervalId = setInterval(() => {
280
- _this._storeCache(router, path, intervalId, model, ignoredFields);
281
- }, intervalMillis);
282
- }
283
- }
284
- return model;
285
- },
286
- _readCache: function (router, path, callback) {
287
- if (localStorage) {
288
- path = path || router.app.$route.path || '/';
289
- let cache = localStorage[path];
290
- if (cache) {
291
- cache = window.tnx.util.string.parseJson(cache);
292
- if (typeof callback === 'function') {
293
- callback.call(this, cache);
294
- }
295
- }
296
- return path;
297
- }
298
- },
299
- _storeCache: function (router, path, intervalId, model, ignoredFields) {
300
- if (path && intervalId) {
301
- let data = {};
302
- if (Array.isArray(ignoredFields) && ignoredFields.length) {
303
- Object.keys(model).forEach(key => {
304
- if (!ignoredFields.contains(key)) {
305
- data[key] = model[key];
306
- }
307
- });
308
- } else {
309
- data = model;
310
- }
311
- localStorage[path] = tnxvue.util.string.toJson({
312
- intervalId: intervalId,
313
- model: data,
314
- ignored: ignoredFields,
315
- });
316
- }
317
- },
318
- saveCache: function (router, model) {
319
- let intervalId;
320
- let ignoredFields;
321
- let path = this._readCache(router, undefined, function (cache) {
322
- intervalId = cache.intervalId;
323
- ignoredFields = cache.ignored;
324
- });
325
- this._storeCache(router, path, intervalId, model, ignoredFields);
326
- },
327
- stopCache: function (router, path) {
328
- return this._readCache(router, path, function (cache) {
329
- clearInterval(cache.intervalId);
330
- });
331
- },
332
- clearCache: function (router) {
333
- let path = this.stopCache(router);
334
- if (path) {
335
- delete localStorage[path];
336
- }
337
- },
338
- /**
339
- * 前端页面模型转换为后端命令模型,检查文件上传是否完成,去掉后端不需要的多余字段,转换多层嵌入字段数据使其符合服务端命令模型的基本要求
340
- * @param vm vue实例
341
- * @param model 前端页面模型
342
- * @param validFieldNames 有效的字段名称集,如有指定则清除模型中的无效字段
343
- */
344
- toCommandModel: function (vm, model, validFieldNames) {
345
- let result = {};
346
- if (model) {
347
- if (vm.$refs) {
348
- let refKeys = Object.keys(vm.$refs);
349
- for (let refKey of refKeys) {
350
- let ref = vm.$refs[refKey];
351
- if (typeof ref.getLocationUrl === 'function') {
352
- if (ref.validateUploaded() === false) {
353
- return null;
354
- }
355
- }
356
- }
357
- }
358
- let fieldNames = Object.keys(model);
359
- for (let fieldName of fieldNames) {
360
- if (!validFieldNames || !validFieldNames.length || validFieldNames.contains(fieldName)) {
361
- if (fieldName.contains('__')) {
362
- let path = fieldName.replace('__', '.');
363
- tnxvue.util.object.setValue(result, path, model[fieldName]);
364
- } else {
365
- result[fieldName] = model[fieldName];
366
- }
367
- }
368
- }
369
- }
370
- return result;
371
- },
372
- /**
373
- * 转换多层嵌入字段数据使其符合前端页面模型的基本要求
374
- * @param model 服务端视图模型
375
- */
376
- toPageModel: function (model) {
377
- let expanded = this._expandRefFields(model);
378
- while (expanded) {
379
- expanded = this._expandRefFields(model);
380
- }
381
- return model;
382
- },
383
- _expandRefFields: function (model) {
384
- let expanded = false;
385
- Object.keys(model).forEach(key => {
386
- let value = model[key];
387
- if (value && typeof value === 'object') {
388
- Object.keys(value).forEach(refKey => {
389
- model[key + '__' + refKey] = value[refKey];
390
- });
391
- delete model[key];
392
- expanded = true;
393
- }
394
- });
395
- return expanded;
396
- }
397
- });
398
-
399
- /**
400
- * 页面级缓存支持
401
- */
402
- tnxvue.app.page.cache = {
403
- _getName: function (key) {
404
- return 'cache_' + key;
405
- },
406
- get: function (vm, key, defaultValue) {
407
- let name = this._getName(key);
408
- let cache = vm.$root[name];
409
- if (cache === undefined) {
410
- cache = defaultValue;
411
- vm.$root[name] = cache;
412
- }
413
- return cache;
414
- },
415
- set: function (vm, key, value) {
416
- let name = this._getName(key);
417
- if (value === undefined) {
418
- delete vm.$root[name];
419
- } else {
420
- vm.$root[name] = value;
421
- }
422
- }
423
- }
424
-
425
- return tnxvue;
426
- });