@truenewx/tnxvue3 2.6.4 → 2.6.5

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 CHANGED
@@ -2,7 +2,7 @@
2
2
  /**
3
3
  * 基于Vue 3的扩展支持
4
4
  */
5
- import tnxcore from '@truenewx/tnxcore';
5
+ import tnxcore, { build } from '@truenewx/tnxcore';
6
6
  import validator from './tnxvue-validator';
7
7
  import createRouter from './tnxvue-router';
8
8
  import Text from './text/Text.vue';
@@ -12,332 +12,331 @@ import * as Vue from 'vue';
12
12
  import mitt from 'mitt';
13
13
  import './tnxvue.css';
14
14
 
15
- const components = {
16
- Div: {
17
- name: 'TnxvueDiv',
18
- template: '<div><slot></slot></div>'
19
- },
20
- Span: {
21
- name: 'TnxvueSpan',
22
- template: '<span><slot></slot></span>'
23
- },
24
- Text,
25
- Percent,
26
- CaptchaVerify,
27
- };
15
+ export { build };
28
16
 
29
- const tnxvue = Object.assign({}, tnxcore, {
30
- components,
31
- router: {
32
- instance: null,
33
- create(VueRouter, menu, fnImportPage) {
34
- return createRouter(VueRouter, menu, fnImportPage);
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,
35
31
  },
36
- beforeLeave(router, from) {
37
- window.tnx.app.page.stopCache(router, from.path);
38
- }
39
- },
40
- createVueInstance(rootComponent, router, rootProps) {
41
- let vm = Vue.createApp(rootComponent, rootProps);
42
- vm.use(this);
43
- if (router) {
44
- vm.use(router);
45
- router.app = window.tnx.app;
46
- window.tnx.router.instance = vm.config.globalProperties.$router;
47
- } else if (window.tnx.router.instance) {
48
- vm.config.globalProperties.$router = window.tnx.router.instance;
49
- }
50
- vm.config.unwrapInjectedRef = true;
51
- window.tnx.app.eventBus = mitt();
52
- window.tnx.app.eventBus.once = function(name, handler) {
53
- this.all.set(name, [handler]);
54
- }
55
- return vm;
56
- },
57
- install(vm) {
58
- for (let key of Object.keys(this.components)) {
59
- const component = this.components[key];
60
- vm.component(component.name, component);
61
- }
62
- this.libs.Vue = Vue;
63
- },
64
- dialog(content, title, buttons, options, contentProps) {
65
- // 默认不实现,由UI框架扩展层实现
66
- throw new Error('Unsupported function');
67
- },
68
- drawer(content, title, buttons, options, contentProps) {
69
- // 默认不实现,由UI框架扩展层实现
70
- throw new Error('Unsupported function');
71
- },
72
- open(component, props, options) {
73
- options = options || {};
74
-
75
- let mode = options.mode;
76
- if (component.methods) {
77
- if (component.methods.dialog) {
78
- options = Object.assign({}, component.methods.dialog(props), options);
79
- } else if (component.methods.drawer) {
80
- options = Object.assign({}, component.methods.drawer(props), options);
81
- mode = 'drawer';
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);
82
39
  }
83
- }
40
+ },
41
+ createVueInstance(rootComponent, router, rootProps) {
42
+ let vm = Vue.createApp(rootComponent, rootProps);
43
+ vm.use(this);
44
+ if (router) {
45
+ vm.use(router);
46
+ router.app = window.tnx.app;
47
+ window.tnx.router.instance = vm.config.globalProperties.$router;
48
+ } else if (window.tnx.router.instance) {
49
+ vm.config.globalProperties.$router = window.tnx.router.instance;
50
+ }
51
+ vm.config.unwrapInjectedRef = true;
52
+ window.tnx.app.eventBus = mitt();
53
+ window.tnx.app.eventBus.once = function(name, handler) {
54
+ this.all.set(name, [handler]);
55
+ }
56
+ return vm;
57
+ },
58
+ install(vm) {
59
+ for (let key of Object.keys(this.components)) {
60
+ const component = this.components[key];
61
+ vm.component(component.name, component);
62
+ }
63
+ this.libs.Vue = Vue;
64
+ },
65
+ dialog(content, title, buttons, options, contentProps) {
66
+ // 默认不实现,由UI框架扩展层实现
67
+ throw new Error('Unsupported function');
68
+ },
69
+ drawer(content, title, buttons, options, contentProps) {
70
+ // 默认不实现,由UI框架扩展层实现
71
+ throw new Error('Unsupported function');
72
+ },
73
+ open(component, props, options) {
74
+ options = options || {};
84
75
 
85
- const title = component.title || options.title;
86
- const buttons = options.buttons || this.getDefaultDialogButtons(options.type, options.click, options.theme);
87
- if (options.buttonText) {
88
- if (!Array.isArray(options.buttonText)) {
89
- options.buttonText = [options.buttonText];
76
+ let mode = options.mode;
77
+ if (component.methods) {
78
+ if (component.methods.dialog) {
79
+ options = Object.assign({}, component.methods.dialog(props), options);
80
+ } else if (component.methods.drawer) {
81
+ options = Object.assign({}, component.methods.drawer(props), options);
82
+ mode = 'drawer';
83
+ }
90
84
  }
91
- for (let i = 0; i < buttons.length; i++) {
92
- let buttonText = options.buttonText[i];
93
- if (buttonText) {
94
- buttons[i].text = buttonText;
85
+
86
+ const title = component.title || options.title;
87
+ const buttons = options.buttons || this.getDefaultDialogButtons(options.type, options.click, options.theme);
88
+ if (options.buttonText) {
89
+ if (!Array.isArray(options.buttonText)) {
90
+ options.buttonText = [options.buttonText];
91
+ }
92
+ for (let i = 0; i < buttons.length; i++) {
93
+ let buttonText = options.buttonText[i];
94
+ if (buttonText) {
95
+ buttons[i].text = buttonText;
96
+ }
95
97
  }
96
98
  }
97
- }
98
- delete options.mode;
99
- delete options.title;
100
- delete options.type;
101
- delete options.click;
102
- if (mode === 'drawer') {
103
- return this.drawer(component, title, buttons, options, props);
104
- }
105
- return this.dialog(component, title, buttons, options, props);
106
- },
107
- getDefaultDialogButtons(type, callback, theme) {
108
- if (callback !== false) {
109
- if (type === 'none') {
110
- return [];
111
- } else if (type === 'confirm') {
112
- return [{
113
- text: '取消',
114
- click(close) {
115
- if (typeof callback === 'function') {
116
- return callback.call(this, false, close);
99
+ delete options.mode;
100
+ delete options.title;
101
+ delete options.type;
102
+ delete options.click;
103
+ if (mode === 'drawer') {
104
+ return this.drawer(component, title, buttons, options, props);
105
+ }
106
+ return this.dialog(component, title, buttons, options, props);
107
+ },
108
+ getDefaultDialogButtons(type, callback, theme) {
109
+ if (callback !== false) {
110
+ if (type === 'none') {
111
+ return [];
112
+ } else if (type === 'confirm') {
113
+ return [{
114
+ text: '取消',
115
+ click(close) {
116
+ if (typeof callback === 'function') {
117
+ return callback.call(this, false, close);
118
+ }
117
119
  }
118
- }
119
- }, {
120
- text: '确定',
121
- type: theme || 'primary',
122
- click(close) {
123
- if (typeof callback === 'function') {
124
- return callback.call(this, true, close);
120
+ }, {
121
+ text: '确定',
122
+ type: theme || 'primary',
123
+ click(close) {
124
+ if (typeof callback === 'function') {
125
+ return callback.call(this, true, close);
126
+ }
125
127
  }
126
- }
127
- }];
128
- } else {
129
- return [{
130
- text: '确定',
131
- type: theme || 'primary',
132
- click(close) {
133
- if (typeof callback === 'function') {
134
- return callback.call(this, close);
128
+ }];
129
+ } else {
130
+ return [{
131
+ text: '确定',
132
+ type: theme || 'primary',
133
+ click(close) {
134
+ if (typeof callback === 'function') {
135
+ return callback.call(this, close);
136
+ }
135
137
  }
136
- }
137
- }];
138
+ }];
139
+ }
138
140
  }
139
- }
140
- return [];
141
- },
142
- });
141
+ return [];
142
+ },
143
+ });
143
144
 
144
- Object.assign(tnxvue.util, {
145
- /**
146
- * 判断指定对象是否组件实例
147
- * @param obj 对象
148
- * @returns {boolean} 是否组件实例
149
- */
150
- isComponent: function(obj) {
151
- return (typeof obj === 'object') && (typeof obj.render === 'function');
152
- }
153
- });
145
+ Object.assign(tnxvue.util, {
146
+ /**
147
+ * 判断指定对象是否组件实例
148
+ * @param obj 对象
149
+ * @returns {boolean} 是否组件实例
150
+ */
151
+ isComponent: function(obj) {
152
+ return (typeof obj === 'object') && (typeof obj.render === 'function');
153
+ }
154
+ });
154
155
 
155
- tnxvue.app.isProduction = function() {
156
- if (process && process.env && process.env.NODE_ENV !== 'production') {
157
- return false;
158
- }
159
- return true;
160
- };
156
+ tnxvue.app.isProduction = function() {
157
+ if (process && process.env && process.env.NODE_ENV !== 'production') {
158
+ return false;
159
+ }
160
+ return true;
161
+ };
161
162
 
162
- tnxvue.app.toDevUrl = function(url, portIndex, replacement) {
163
- if (!this.isProduction()) {
164
- let index = url.indexOf(':', url.indexOf('//'));
165
- if (index > 0) { // 必须带有端口号才可替换
166
- let prefix = url.substring(0, index + 1); // 端口号之前的部分
167
- portIndex = portIndex || 1; // 开发环境端口与正式环境端口不同点的位置,如:8080之于8880,则portIndex为1
168
- replacement = replacement || '0'; // 开发环境端口在不同于正式环境端口位置要替代的值,如8080之于8880,则replacement为'0'
163
+ tnxvue.app.toDevUrl = function(url, portIndex, replacement) {
164
+ if (!this.isProduction()) {
165
+ let index = url.indexOf(':', url.indexOf('//'));
166
+ if (index > 0) { // 必须带有端口号才可替换
167
+ let prefix = url.substring(0, index + 1); // 端口号之前的部分
168
+ portIndex = portIndex || 1; // 开发环境端口与正式环境端口不同点的位置,如:8080之于8880,则portIndex为1
169
+ replacement = replacement || '0'; // 开发环境端口在不同于正式环境端口位置要替代的值,如8080之于8880,则replacement为'0'
169
170
 
170
- let path = ''; // 路由路径
171
- let wellIndex = url.indexOf('#');
172
- if (wellIndex > 0) { // 如果有路由路径,则将url拆成两部分,以便于后续处理
173
- path = url.substring(wellIndex);
174
- url = url.substring(0, wellIndex);
171
+ let path = ''; // 路由路径
172
+ let wellIndex = url.indexOf('#');
173
+ if (wellIndex > 0) { // 如果有路由路径,则将url拆成两部分,以便于后续处理
174
+ path = url.substring(wellIndex);
175
+ url = url.substring(0, wellIndex);
176
+ }
177
+ // 开发环境路径不包含contextPath,去掉url中的contenxtPath
178
+ let replaceEndIndex = prefix.length + portIndex + 1;
179
+ let slashIndex = url.indexOf('/', prefix.length);
180
+ url = url.substring(0, prefix.length + portIndex) + replacement
181
+ + url.substring(replaceEndIndex, slashIndex > replaceEndIndex ? slashIndex : undefined) + path;
175
182
  }
176
- // 开发环境路径不包含contextPath,去掉url中的contenxtPath
177
- let replaceEndIndex = prefix.length + portIndex + 1;
178
- let slashIndex = url.indexOf('/', prefix.length);
179
- url = url.substring(0, prefix.length + portIndex) + replacement
180
- + url.substring(replaceEndIndex, slashIndex > replaceEndIndex ? slashIndex : undefined) + path;
181
183
  }
184
+ return url;
182
185
  }
183
- return url;
184
- }
185
186
 
186
187
  // 元数据到async-validator组件规则的转换处理
187
- tnxvue.app.validator = validator;
188
- tnxvue.app.rpc.getMeta = tnxvue.util.function.around(tnxvue.app.rpc.getMeta, function(getMeta, url, callback, app) {
189
- getMeta.call(tnxvue.app.rpc, url, function(meta) {
190
- if (meta) { // meta已被缓存,所以直接修改其内容,以便同步缓存
191
- meta.$rules = validator.getRules(meta);
192
- if (typeof callback === 'function') {
193
- callback.call(this, meta);
188
+ tnxvue.app.validator = validator;
189
+ tnxvue.app.rpc.getMeta = tnxvue.util.function.around(tnxvue.app.rpc.getMeta, function(getMeta, url, callback, app) {
190
+ getMeta.call(tnxvue.app.rpc, url, function(meta) {
191
+ if (meta) { // meta已被缓存,所以直接修改其内容,以便同步缓存
192
+ meta.$rules = validator.getRules(meta);
193
+ if (typeof callback === 'function') {
194
+ callback.call(this, meta);
195
+ }
194
196
  }
195
- }
196
- }, app);
197
- });
197
+ }, app);
198
+ });
198
199
 
199
- tnxvue.app.page.init = tnxvue.util.function.around(tnxvue.app.page.init, function(init, page, container) {
200
- if (container.tagName === 'BODY') { // vue不推荐以body为挂载目标,故从body下获取第一个div作为容器
201
- for (let i = 0; i < container.children.length; i++) {
202
- const child = container.children[i];
203
- if (child.tagName === 'DIV') {
204
- container = child;
205
- break;
200
+ tnxvue.app.page.init = tnxvue.util.function.around(tnxvue.app.page.init, function(init, page, container) {
201
+ if (container.tagName === 'BODY') { // vue不推荐以body为挂载目标,故从body下获取第一个div作为容器
202
+ for (let i = 0; i < container.children.length; i++) {
203
+ const child = container.children[i];
204
+ if (child.tagName === 'DIV') {
205
+ container = child;
206
+ break;
207
+ }
206
208
  }
207
209
  }
208
- }
209
- init.call(this, page, container);
210
- });
210
+ init.call(this, page, container);
211
+ });
211
212
 
212
- Object.assign(tnxvue.app.page, {
213
- startCache: function(router, model, intervalMillis, ignoredFields) {
214
- if (localStorage && intervalMillis && intervalMillis > 1000) { // 缓存间隔必须超过1秒
215
- let path = this._readCache(router, undefined, function(cache) {
216
- Object.assign(model, cache.model);
217
- });
213
+ Object.assign(tnxvue.app.page, {
214
+ startCache: function(router, model, intervalMillis, ignoredFields) {
215
+ if (localStorage && intervalMillis && intervalMillis > 1000) { // 缓存间隔必须超过1秒
216
+ let path = this._readCache(router, undefined, function(cache) {
217
+ Object.assign(model, cache.model);
218
+ });
218
219
 
219
- if (path) {
220
- let _this = this;
221
- let intervalId = setInterval(function() {
222
- _this._storeCache(router, path, intervalId, model, ignoredFields);
223
- }, intervalMillis);
224
- }
225
- }
226
- return model;
227
- },
228
- _readCache: function(router, path, callback) {
229
- if (localStorage) {
230
- path = path || router.app.$route.path || '/';
231
- let cache = localStorage[path];
232
- if (cache) {
233
- cache = window.tnx.util.string.parseJson(cache);
234
- if (typeof callback === 'function') {
235
- callback.call(this, cache);
220
+ if (path) {
221
+ let _this = this;
222
+ let intervalId = setInterval(function() {
223
+ _this._storeCache(router, path, intervalId, model, ignoredFields);
224
+ }, intervalMillis);
236
225
  }
237
226
  }
238
- return path;
239
- }
240
- },
241
- _storeCache: function(router, path, intervalId, model, ignoredFields) {
242
- if (path && intervalId) {
243
- let data = {};
244
- if (Array.isArray(ignoredFields) && ignoredFields.length) {
245
- Object.keys(model).forEach(key => {
246
- if (!ignoredFields.contains(key)) {
247
- data[key] = model[key];
227
+ return model;
228
+ },
229
+ _readCache: function(router, path, callback) {
230
+ if (localStorage) {
231
+ path = path || router.app.$route.path || '/';
232
+ let cache = localStorage[path];
233
+ if (cache) {
234
+ cache = window.tnx.util.string.parseJson(cache);
235
+ if (typeof callback === 'function') {
236
+ callback.call(this, cache);
248
237
  }
238
+ }
239
+ return path;
240
+ }
241
+ },
242
+ _storeCache: function(router, path, intervalId, model, ignoredFields) {
243
+ if (path && intervalId) {
244
+ let data = {};
245
+ if (Array.isArray(ignoredFields) && ignoredFields.length) {
246
+ Object.keys(model).forEach(key => {
247
+ if (!ignoredFields.contains(key)) {
248
+ data[key] = model[key];
249
+ }
250
+ });
251
+ } else {
252
+ data = model;
253
+ }
254
+ localStorage[path] = tnxvue.util.string.toJson({
255
+ intervalId: intervalId,
256
+ model: data,
257
+ ignored: ignoredFields,
249
258
  });
250
- } else {
251
- data = model;
252
259
  }
253
- localStorage[path] = tnxvue.util.string.toJson({
254
- intervalId: intervalId,
255
- model: data,
256
- ignored: ignoredFields,
260
+ },
261
+ saveCache: function(router, model) {
262
+ let intervalId;
263
+ let ignoredFields;
264
+ let path = this._readCache(router, undefined, function(cache) {
265
+ intervalId = cache.intervalId;
266
+ ignoredFields = cache.ignored;
257
267
  });
258
- }
259
- },
260
- saveCache: function(router, model) {
261
- let intervalId;
262
- let ignoredFields;
263
- let path = this._readCache(router, undefined, function(cache) {
264
- intervalId = cache.intervalId;
265
- ignoredFields = cache.ignored;
266
- });
267
- this._storeCache(router, path, intervalId, model, ignoredFields);
268
- },
269
- stopCache: function(router, path) {
270
- return this._readCache(router, path, function(cache) {
271
- clearInterval(cache.intervalId);
272
- });
273
- },
274
- clearCache: function(router) {
275
- let path = this.stopCache(router);
276
- if (path) {
277
- delete localStorage[path];
278
- }
279
- },
280
- /**
281
- * 前端页面模型转换为后端命令模型,检查文件上传是否完成,去掉后端不需要的多余字段,转换多层嵌入字段数据使其符合服务端命令模型的基本要求
282
- * @param model 前端页面模型
283
- * @param refs 页面中的组件引用集
284
- * @param validFieldNames 有效的字段名称集,如有指定则清除模型中的无效字段
285
- */
286
- toCommandModel: function(vm, model, validFieldNames) {
287
- let result = {};
288
- if (model) {
289
- if (vm.$refs) {
290
- let refKeys = Object.keys(vm.$refs);
291
- for (let refKey of refKeys) {
292
- let ref = vm.$refs[refKey];
293
- if (typeof ref.getLocationUrl === 'function') {
294
- if (ref.validateUploaded() === false) {
295
- return null;
268
+ this._storeCache(router, path, intervalId, model, ignoredFields);
269
+ },
270
+ stopCache: function(router, path) {
271
+ return this._readCache(router, path, function(cache) {
272
+ clearInterval(cache.intervalId);
273
+ });
274
+ },
275
+ clearCache: function(router) {
276
+ let path = this.stopCache(router);
277
+ if (path) {
278
+ delete localStorage[path];
279
+ }
280
+ },
281
+ /**
282
+ * 前端页面模型转换为后端命令模型,检查文件上传是否完成,去掉后端不需要的多余字段,转换多层嵌入字段数据使其符合服务端命令模型的基本要求
283
+ * @param model 前端页面模型
284
+ * @param refs 页面中的组件引用集
285
+ * @param validFieldNames 有效的字段名称集,如有指定则清除模型中的无效字段
286
+ */
287
+ toCommandModel: function(vm, model, validFieldNames) {
288
+ let result = {};
289
+ if (model) {
290
+ if (vm.$refs) {
291
+ let refKeys = Object.keys(vm.$refs);
292
+ for (let refKey of refKeys) {
293
+ let ref = vm.$refs[refKey];
294
+ if (typeof ref.getLocationUrl === 'function') {
295
+ if (ref.validateUploaded() === false) {
296
+ return null;
297
+ }
296
298
  }
297
299
  }
298
300
  }
299
- }
300
- let fieldNames = Object.keys(model);
301
- for (let fieldName of fieldNames) {
302
- if (!validFieldNames || !validFieldNames.length || validFieldNames.contains(fieldName)) {
303
- if (fieldName.contains('__')) {
304
- let path = fieldName.replace('__', '.');
305
- tnxvue.util.object.setValue(result, path, model[fieldName]);
306
- } else {
307
- result[fieldName] = model[fieldName];
301
+ let fieldNames = Object.keys(model);
302
+ for (let fieldName of fieldNames) {
303
+ if (!validFieldNames || !validFieldNames.length || validFieldNames.contains(fieldName)) {
304
+ if (fieldName.contains('__')) {
305
+ let path = fieldName.replace('__', '.');
306
+ tnxvue.util.object.setValue(result, path, model[fieldName]);
307
+ } else {
308
+ result[fieldName] = model[fieldName];
309
+ }
308
310
  }
309
311
  }
310
312
  }
311
- }
312
- return result;
313
- },
314
- /**
315
- * 转换多层嵌入字段数据使其符合前端页面模型的基本要求
316
- * @param model 服务端视图模型
317
- */
318
- toPageModel: function(model) {
319
- let expanded = this._expandRefFields(model);
320
- while (expanded) {
321
- expanded = this._expandRefFields(model);
322
- }
323
- return model;
324
- },
325
- _expandRefFields: function(model) {
326
- let expanded = false;
327
- Object.keys(model).forEach(key => {
328
- let value = model[key];
329
- if (value && typeof value === 'object') {
330
- Object.keys(value).forEach(refKey => {
331
- model[key + '__' + refKey] = value[refKey];
332
- });
333
- delete model[key];
334
- expanded = true;
313
+ return result;
314
+ },
315
+ /**
316
+ * 转换多层嵌入字段数据使其符合前端页面模型的基本要求
317
+ * @param model 服务端视图模型
318
+ */
319
+ toPageModel: function(model) {
320
+ let expanded = this._expandRefFields(model);
321
+ while (expanded) {
322
+ expanded = this._expandRefFields(model);
335
323
  }
336
- });
337
- return expanded;
338
- }
324
+ return model;
325
+ },
326
+ _expandRefFields: function(model) {
327
+ let expanded = false;
328
+ Object.keys(model).forEach(key => {
329
+ let value = model[key];
330
+ if (value && typeof value === 'object') {
331
+ Object.keys(value).forEach(refKey => {
332
+ model[key + '__' + refKey] = value[refKey];
333
+ });
334
+ delete model[key];
335
+ expanded = true;
336
+ }
337
+ });
338
+ return expanded;
339
+ }
340
+ });
341
+ return tnxvue;
339
342
  });
340
-
341
- window.tnx = tnxvue;
342
-
343
- export default tnxvue;
@@ -1,5 +0,0 @@
1
- /**
2
- * tnxad-theme.css
3
- * 对Ant Design颜色主题相关CSS的调整。
4
- * 从通用调整中拆分出来的原因是,工程可能使用定制颜色主题的样式库,本主题样式库应在工程定制颜色主题的样式库之前引入。
5
- */
@@ -1,8 +0,0 @@
1
- /**
2
- * tnxad.css
3
- * 对Ant Design CSS的通用调整
4
- */
5
- body {
6
- margin: 0;
7
- color: #303133;
8
- }