@ibiz-template/model-helper 0.6.1-dev.0 → 0.6.1-dev.1
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/package.json +4 -5
- package/src/index.ts +0 -12
- package/src/model/PSSYSAPP.ts +0 -12
- package/src/model-helper.ts +0 -360
- package/src/model-loader.ts +0 -51
- package/src/model-util.ts +0 -400
- package/src/utils/format-path/format-path.ts +0 -9
- package/src/utils/index.ts +0 -9
- package/src/utils/merge-model/merge-app-menu.ts +0 -84
- package/src/utils/merge-model/merge-model.ts +0 -20
- package/src/utils/plural/plural.ts +0 -30
- package/src/utils/service-path-util/service-path-util.ts +0 -249
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ibiz-template/model-helper",
|
|
3
|
-
"version": "0.6.1-dev.
|
|
3
|
+
"version": "0.6.1-dev.1",
|
|
4
4
|
"description": "控制器包",
|
|
5
5
|
"main": "out/index.js",
|
|
6
6
|
"types": "out/index.d.ts",
|
|
@@ -12,8 +12,7 @@
|
|
|
12
12
|
},
|
|
13
13
|
"files": [
|
|
14
14
|
"dist",
|
|
15
|
-
"out"
|
|
16
|
-
"src"
|
|
15
|
+
"out"
|
|
17
16
|
],
|
|
18
17
|
"scripts": {
|
|
19
18
|
"dev": "tsc --watch",
|
|
@@ -39,7 +38,7 @@
|
|
|
39
38
|
"ramda": "^0.29.1"
|
|
40
39
|
},
|
|
41
40
|
"devDependencies": {
|
|
42
|
-
"@ibiz-template/runtime": "^0.6.1-dev.
|
|
41
|
+
"@ibiz-template/runtime": "^0.6.1-dev.1",
|
|
43
42
|
"@types/pluralize": "^0.0.33",
|
|
44
43
|
"@types/ramda": "^0.29.10"
|
|
45
44
|
},
|
|
@@ -47,5 +46,5 @@
|
|
|
47
46
|
"@ibiz-template/runtime": "^0.6.0",
|
|
48
47
|
"ramda": "^0.29.0"
|
|
49
48
|
},
|
|
50
|
-
"gitHead": "
|
|
49
|
+
"gitHead": "5f8ce122d58af1b3ae28e3e389c4384780013e12"
|
|
51
50
|
}
|
package/src/index.ts
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import '@ibiz/model-core';
|
|
2
|
-
import '@ibiz-template/runtime';
|
|
3
|
-
|
|
4
|
-
export * from './model-helper';
|
|
5
|
-
export { ModelHelper } from './model-helper';
|
|
6
|
-
|
|
7
|
-
declare global {
|
|
8
|
-
interface IObject {
|
|
9
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
10
|
-
[key: string | symbol]: any;
|
|
11
|
-
}
|
|
12
|
-
}
|
package/src/model/PSSYSAPP.ts
DELETED
package/src/model-helper.ts
DELETED
|
@@ -1,360 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
IAppCodeList,
|
|
3
|
-
IAppDataEntity,
|
|
4
|
-
IAppView,
|
|
5
|
-
IApplication,
|
|
6
|
-
IAppLan,
|
|
7
|
-
ISubAppRef,
|
|
8
|
-
IAppMenuModel,
|
|
9
|
-
IAppMenu,
|
|
10
|
-
} from '@ibiz/model-core';
|
|
11
|
-
import { DSLHelper } from '@ibiz/rt-model-api';
|
|
12
|
-
import { ModelUtil } from './model-util';
|
|
13
|
-
import { ModelLoader } from './model-loader';
|
|
14
|
-
import { mergeAppMenu, plural } from './utils';
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* 模型加载工具类
|
|
18
|
-
*
|
|
19
|
-
* @author chitanda
|
|
20
|
-
* @date 2023-04-16 17:04:46
|
|
21
|
-
* @export
|
|
22
|
-
* @class ModelHelper
|
|
23
|
-
*/
|
|
24
|
-
export class ModelHelper {
|
|
25
|
-
protected dsl = new DSLHelper();
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* 当前子应用清单
|
|
29
|
-
*
|
|
30
|
-
* @author chitanda
|
|
31
|
-
* @date 2023-12-06 15:12:30
|
|
32
|
-
* @protected
|
|
33
|
-
* @type {ISubAppRef[]}
|
|
34
|
-
*/
|
|
35
|
-
protected subAppRefs: ISubAppRef[] = [];
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* 模型获取工具类缓存
|
|
39
|
-
*
|
|
40
|
-
* @author chitanda
|
|
41
|
-
* @date 2023-04-16 17:04:56
|
|
42
|
-
* @protected
|
|
43
|
-
* @type {Map<string, ModelUtil>}
|
|
44
|
-
*/
|
|
45
|
-
protected cache: Map<string, ModelUtil> = new Map();
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* Creates an instance of ModelHelper.
|
|
49
|
-
* @author chitanda
|
|
50
|
-
* @date 2024-01-08 10:01:20
|
|
51
|
-
* @param {(url: string, params?: IParams) => Promise<IModel>} getModel 模型加载方法
|
|
52
|
-
* @param {string} defaultAppId 默认应用标识
|
|
53
|
-
* @param {boolean} [permission=true] 是否启用权限
|
|
54
|
-
*/
|
|
55
|
-
constructor(
|
|
56
|
-
protected getModel: (url: string, params?: IParams) => Promise<IModel>,
|
|
57
|
-
protected defaultAppId: string,
|
|
58
|
-
protected permission: boolean = true,
|
|
59
|
-
) {
|
|
60
|
-
ibiz.hub.registerModelLoaderProvider(new ModelLoader(this));
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
/**
|
|
64
|
-
* 初始化应用内容
|
|
65
|
-
*
|
|
66
|
-
* @author chitanda
|
|
67
|
-
* @date 2023-12-06 17:12:51
|
|
68
|
-
* @param {string} [id]
|
|
69
|
-
* @return {*} {Promise<boolean>}
|
|
70
|
-
*/
|
|
71
|
-
async initApp(id?: string): Promise<boolean> {
|
|
72
|
-
await this.initToHub(id);
|
|
73
|
-
return true;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
/**
|
|
77
|
-
* 初始化具体应用模型工具类
|
|
78
|
-
*
|
|
79
|
-
* @author chitanda
|
|
80
|
-
* @date 2023-04-16 17:04:41
|
|
81
|
-
* @param {string} modelTag
|
|
82
|
-
* @param {string} [appId=this.defaultAppId]
|
|
83
|
-
* @return {*} {Promise<void>}
|
|
84
|
-
*/
|
|
85
|
-
async initModelUtil(
|
|
86
|
-
modelTag: string,
|
|
87
|
-
appId: string = this.defaultAppId,
|
|
88
|
-
): Promise<void> {
|
|
89
|
-
const modelUtil = new ModelUtil(
|
|
90
|
-
appId,
|
|
91
|
-
modelTag,
|
|
92
|
-
this.getModel,
|
|
93
|
-
this.defaultAppId === appId,
|
|
94
|
-
this.permission,
|
|
95
|
-
);
|
|
96
|
-
await modelUtil.init();
|
|
97
|
-
this.cache.set(appId, modelUtil);
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
/**
|
|
101
|
-
* 初始化模型至Hub中
|
|
102
|
-
*
|
|
103
|
-
* @author chitanda
|
|
104
|
-
* @date 2023-04-17 14:04:55
|
|
105
|
-
* @protected
|
|
106
|
-
* @param {(string | IObject)} [appId]
|
|
107
|
-
* @return {*} {Promise<void>}
|
|
108
|
-
*/
|
|
109
|
-
protected async initToHub(appId?: string | IObject): Promise<void> {
|
|
110
|
-
const id: string = this.calcAppId(appId);
|
|
111
|
-
const app = ibiz.hub.getApp(id);
|
|
112
|
-
const modelUtil = this.getModelUtil(appId);
|
|
113
|
-
const appSourceModel = await modelUtil.getAppModel();
|
|
114
|
-
// 将引用的视图注册到 hub 清单中,只有主应用才会注册。子应用的注册由主应用在初始化子应用时搞定
|
|
115
|
-
if (appSourceModel.getAllPSAppViews && appId === ibiz.env.appId) {
|
|
116
|
-
const appViews = appSourceModel.getAllPSAppViews as IModel[];
|
|
117
|
-
appViews.forEach(appView => {
|
|
118
|
-
ibiz.hub.setAppView(appView.id, appSourceModel.id, appView.priority);
|
|
119
|
-
});
|
|
120
|
-
}
|
|
121
|
-
if (appSourceModel.getDefaultPSAppIndexView) {
|
|
122
|
-
const view = appSourceModel.getDefaultPSAppIndexView as IModel;
|
|
123
|
-
const name = view.path.split('/').pop().replace('.json', '');
|
|
124
|
-
ibiz.hub.defaultAppIndexViewName = name;
|
|
125
|
-
}
|
|
126
|
-
if (appSourceModel.getAllPSAppCodeLists) {
|
|
127
|
-
const codeLists = appSourceModel.getAllPSAppCodeLists as IAppCodeList[];
|
|
128
|
-
codeLists.forEach(codeList => {
|
|
129
|
-
app.codeList.setCodeList(
|
|
130
|
-
this.dsl.appCodeList(codeList) as IAppCodeList,
|
|
131
|
-
);
|
|
132
|
-
});
|
|
133
|
-
}
|
|
134
|
-
if (appSourceModel.getAllPSAppDataEntities) {
|
|
135
|
-
const dataEntities = appSourceModel.getAllPSAppDataEntities as IModel[];
|
|
136
|
-
dataEntities.forEach(dataEntity => {
|
|
137
|
-
app.deName2DeCodeName.set(dataEntity.name, dataEntity.codeName);
|
|
138
|
-
});
|
|
139
|
-
}
|
|
140
|
-
// 模型扩展标准视图布局面板
|
|
141
|
-
const subViewRefs = app.model.appSubViewTypeRefs || [];
|
|
142
|
-
subViewRefs.forEach(item => {
|
|
143
|
-
if (item.replaceDefault) {
|
|
144
|
-
ibiz.util.layoutPanel.register(
|
|
145
|
-
`${item.viewType}_DEFAULT`,
|
|
146
|
-
item.viewLayoutPanel!,
|
|
147
|
-
);
|
|
148
|
-
}
|
|
149
|
-
});
|
|
150
|
-
// 子应用模型相关处理
|
|
151
|
-
{
|
|
152
|
-
const { subAppRefs = [] } = app.model;
|
|
153
|
-
const { getAllPSSubAppRefs = [] } = appSourceModel;
|
|
154
|
-
for (let i = 0; i < subAppRefs.length; i++) {
|
|
155
|
-
const subApp = subAppRefs[i];
|
|
156
|
-
const sourceSubApp = getAllPSSubAppRefs[i];
|
|
157
|
-
// eslint-disable-next-line no-await-in-loop
|
|
158
|
-
await this.initSubApp(app, subApp, sourceSubApp);
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
/**
|
|
164
|
-
* 初始化子应用相关内容
|
|
165
|
-
*
|
|
166
|
-
* @author chitanda
|
|
167
|
-
* @date 2023-12-06 15:12:23
|
|
168
|
-
* @protected
|
|
169
|
-
* @param {IApplication} app
|
|
170
|
-
* @param {ISubAppRef} subApp
|
|
171
|
-
* @return {*} {Promise<void>}
|
|
172
|
-
*/
|
|
173
|
-
protected async initSubApp(
|
|
174
|
-
app: IApplication,
|
|
175
|
-
subApp: ISubAppRef,
|
|
176
|
-
sourceSubApp: IModel,
|
|
177
|
-
): Promise<void> {
|
|
178
|
-
this.subAppRefs.push(subApp);
|
|
179
|
-
const ids = subApp.appViewIds || [];
|
|
180
|
-
const views = sourceSubApp.getAllPSAppViews || [];
|
|
181
|
-
ids.forEach((id, index) => {
|
|
182
|
-
const view = views[index];
|
|
183
|
-
ibiz.hub.setAppView(id, subApp.id, view.priority);
|
|
184
|
-
});
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
/**
|
|
188
|
-
* 获取应用模型
|
|
189
|
-
*
|
|
190
|
-
* @author chitanda
|
|
191
|
-
* @date 2023-04-16 17:04:13
|
|
192
|
-
* @param {(string | IObject)} [appId]
|
|
193
|
-
* @return {*} {Promise<IApplication>}
|
|
194
|
-
*/
|
|
195
|
-
async getAppModel(appId?: string | IObject): Promise<IApplication> {
|
|
196
|
-
const id: string = this.calcAppId(appId);
|
|
197
|
-
if (!this.cache.has(id)) {
|
|
198
|
-
const data = ibiz.appData || {};
|
|
199
|
-
await this.initModelUtil(data.dynamodeltag, id);
|
|
200
|
-
}
|
|
201
|
-
const model = await this.getModelUtil(appId).getAppModel();
|
|
202
|
-
const app = this.dsl.application(model) as IApplication;
|
|
203
|
-
return app;
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
/**
|
|
207
|
-
* 获取应用全局样式
|
|
208
|
-
*
|
|
209
|
-
* @author chitanda
|
|
210
|
-
* @date 2023-09-06 10:09:48
|
|
211
|
-
* @param {(string | IObject)} [appId]
|
|
212
|
-
* @return {*} {(Promise<string | null>)}
|
|
213
|
-
*/
|
|
214
|
-
getAppStyle(appId?: string | IObject): Promise<string | null> {
|
|
215
|
-
return this.getModelUtil(appId).getAppStyle();
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
/**
|
|
219
|
-
* 根据应用实体 codeName 获取应用实体模型
|
|
220
|
-
*
|
|
221
|
-
* @author chitanda
|
|
222
|
-
* @date 2023-04-16 18:04:33
|
|
223
|
-
* @param {string} name
|
|
224
|
-
* @param {(string | IObject)} [appId]
|
|
225
|
-
* @param {boolean} [isId]
|
|
226
|
-
* @return {*} {Promise<IAppDataEntity>}
|
|
227
|
-
*/
|
|
228
|
-
async getAppDataEntityModel(
|
|
229
|
-
name: string,
|
|
230
|
-
appId?: string | IObject,
|
|
231
|
-
isId?: boolean,
|
|
232
|
-
): Promise<IAppDataEntity> {
|
|
233
|
-
const util = this.getModelUtil(appId);
|
|
234
|
-
const model = await util.getAppDataEntityModel(name, isId, true);
|
|
235
|
-
const dsl = this.dsl.appDataEntity(model) as IAppDataEntity;
|
|
236
|
-
const list = util.servicePathUtil.calcRequestPaths(dsl.id!);
|
|
237
|
-
dsl.requestPaths = list;
|
|
238
|
-
dsl.codeName2 = plural(dsl.codeName!.toLowerCase());
|
|
239
|
-
return dsl;
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
/**
|
|
243
|
-
* 计算应用视图需要合并的子应用模型
|
|
244
|
-
*
|
|
245
|
-
* @author chitanda
|
|
246
|
-
* @date 2023-12-06 16:12:25
|
|
247
|
-
* @protected
|
|
248
|
-
* @param {IAppView} view
|
|
249
|
-
*/
|
|
250
|
-
protected calcAppViewSubAppModel(view: IAppView): void {
|
|
251
|
-
if (view.viewType === 'APPINDEXVIEW') {
|
|
252
|
-
if (view.controls) {
|
|
253
|
-
view.controls.forEach((ctrl: IAppMenu) => {
|
|
254
|
-
if (ctrl.controlType === 'APPMENU') {
|
|
255
|
-
ctrl = ctrl as IAppMenuModel;
|
|
256
|
-
mergeAppMenu(ctrl, this.subAppRefs);
|
|
257
|
-
}
|
|
258
|
-
});
|
|
259
|
-
}
|
|
260
|
-
}
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
/**
|
|
264
|
-
* 根据应用视图 codeName 获取应用视图模型
|
|
265
|
-
*
|
|
266
|
-
* @author chitanda
|
|
267
|
-
* @date 2023-04-16 17:04:38
|
|
268
|
-
* @param {string} name
|
|
269
|
-
* @param {(string | IObject)} [appId]
|
|
270
|
-
* @return {*} {Promise<IAppView>}
|
|
271
|
-
*/
|
|
272
|
-
async getAppViewModel(
|
|
273
|
-
name: string,
|
|
274
|
-
appId?: string | IObject,
|
|
275
|
-
): Promise<IAppView> {
|
|
276
|
-
const model = await this.getModelUtil(appId).getAppViewModel(name);
|
|
277
|
-
const dsl = this.dsl.appView(model) as IAppView;
|
|
278
|
-
this.calcAppViewSubAppModel(dsl);
|
|
279
|
-
return dsl;
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
/**
|
|
283
|
-
* 根据路径和参数加载应用视图模型,主要用于后台根据运行时参数重新计算视图模型
|
|
284
|
-
*
|
|
285
|
-
* @author chitanda
|
|
286
|
-
* @date 2024-01-08 10:01:43
|
|
287
|
-
* @param {string} viewId
|
|
288
|
-
* @param {IParams} [params]
|
|
289
|
-
* @param {string} [appId]
|
|
290
|
-
* @return {*} {Promise<IAppView>}
|
|
291
|
-
*/
|
|
292
|
-
async loadAppViewModel(
|
|
293
|
-
viewId: string,
|
|
294
|
-
params?: IParams,
|
|
295
|
-
appId?: string,
|
|
296
|
-
): Promise<IAppView> {
|
|
297
|
-
const model = await this.getModelUtil(appId).getAppViewModel(
|
|
298
|
-
viewId,
|
|
299
|
-
params,
|
|
300
|
-
true,
|
|
301
|
-
);
|
|
302
|
-
const dsl = this.dsl.appView(model) as IAppView;
|
|
303
|
-
return dsl;
|
|
304
|
-
}
|
|
305
|
-
|
|
306
|
-
/**
|
|
307
|
-
* 获取应用多语言模型
|
|
308
|
-
*
|
|
309
|
-
* @author chitanda
|
|
310
|
-
* @date 2023-08-24 21:08:17
|
|
311
|
-
* @param {string} language
|
|
312
|
-
* @param {(string | IObject)} [appId]
|
|
313
|
-
* @return {*} {Promise<IAppLan>}
|
|
314
|
-
*/
|
|
315
|
-
async getPSAppLang(
|
|
316
|
-
language: string,
|
|
317
|
-
appId?: string | IObject,
|
|
318
|
-
): Promise<IAppLan> {
|
|
319
|
-
const model = await this.getModelUtil(appId).getPSAppLang(language);
|
|
320
|
-
return this.dsl.appLan(model) as IAppLan;
|
|
321
|
-
}
|
|
322
|
-
|
|
323
|
-
/**
|
|
324
|
-
* 获取对应模型工具类
|
|
325
|
-
*
|
|
326
|
-
* @author chitanda
|
|
327
|
-
* @date 2023-04-16 18:04:08
|
|
328
|
-
* @protected
|
|
329
|
-
* @param {(IObject | string)} context
|
|
330
|
-
* @return {*} {ModelUtil}
|
|
331
|
-
*/
|
|
332
|
-
protected getModelUtil(
|
|
333
|
-
context: IObject | string = this.defaultAppId,
|
|
334
|
-
): ModelUtil {
|
|
335
|
-
const appId: string = this.calcAppId(context);
|
|
336
|
-
if (this.cache.has(appId)) {
|
|
337
|
-
return this.cache.get(appId)!;
|
|
338
|
-
}
|
|
339
|
-
throw new Error(`[${appId}]未初始化,请先调用 initModelUtil 方法初始化`);
|
|
340
|
-
}
|
|
341
|
-
|
|
342
|
-
/**
|
|
343
|
-
* 计算应用标识
|
|
344
|
-
*
|
|
345
|
-
* @author chitanda
|
|
346
|
-
* @date 2023-04-16 17:04:19
|
|
347
|
-
* @protected
|
|
348
|
-
* @param {(IObject | string)} [data=this.defaultAppId]
|
|
349
|
-
* @return {*} {string}
|
|
350
|
-
*/
|
|
351
|
-
protected calcAppId(data: IObject | string = this.defaultAppId): string {
|
|
352
|
-
let appId: string;
|
|
353
|
-
if (typeof data === 'string') {
|
|
354
|
-
appId = data;
|
|
355
|
-
} else {
|
|
356
|
-
appId = (data as { appId: string }).appId;
|
|
357
|
-
}
|
|
358
|
-
return appId;
|
|
359
|
-
}
|
|
360
|
-
}
|
package/src/model-loader.ts
DELETED
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
import { ModelLoaderProvider } from '@ibiz-template/runtime';
|
|
2
|
-
import { IApplication, IAppView, IAppDataEntity } from '@ibiz/model-core';
|
|
3
|
-
import { ModelHelper } from './model-helper';
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* 模型加载适配器
|
|
7
|
-
*
|
|
8
|
-
* @author chitanda
|
|
9
|
-
* @date 2023-04-17 23:04:44
|
|
10
|
-
* @export
|
|
11
|
-
* @class ModelLoader
|
|
12
|
-
* @implements {ModelLoaderProvider}
|
|
13
|
-
*/
|
|
14
|
-
export class ModelLoader implements ModelLoaderProvider {
|
|
15
|
-
constructor(protected helper: ModelHelper) {}
|
|
16
|
-
|
|
17
|
-
initApp(id?: string): Promise<boolean> {
|
|
18
|
-
return this.helper.initApp(id);
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
getApp(id?: string): Promise<IApplication> {
|
|
22
|
-
return this.helper.getAppModel(id);
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
getAppView(appId: string, codeName: string): Promise<IAppView> {
|
|
26
|
-
return this.helper.getAppViewModel(codeName, appId);
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
getAppDataEntity(appId: string, id: string): Promise<IAppDataEntity> {
|
|
30
|
-
return this.helper.getAppDataEntityModel(id, appId);
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
getAppDataEntityByCodeName(
|
|
34
|
-
appId: string,
|
|
35
|
-
codeName: string,
|
|
36
|
-
): Promise<IAppDataEntity> {
|
|
37
|
-
return this.helper.getAppDataEntityModel(codeName, appId, false);
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
getAppStyle(appId: string): Promise<string | null> {
|
|
41
|
-
return this.helper.getAppStyle(appId);
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
loadAppView(
|
|
45
|
-
appId: string,
|
|
46
|
-
viewId: string,
|
|
47
|
-
params: IParams,
|
|
48
|
-
): Promise<IAppView> {
|
|
49
|
-
return this.helper.loadAppViewModel(viewId, params, appId);
|
|
50
|
-
}
|
|
51
|
-
}
|
package/src/model-util.ts
DELETED
|
@@ -1,400 +0,0 @@
|
|
|
1
|
-
import { calcUniqueTag } from '@ibiz/rt-model-api';
|
|
2
|
-
import { IAppDERS } from '@ibiz/model-core';
|
|
3
|
-
import { isEmpty } from 'ramda';
|
|
4
|
-
import { formatPath, mergeModel, ServicePathUtil } from './utils';
|
|
5
|
-
import { PSSysApp } from './model/PSSYSAPP';
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* 全动模型处理工具类,每个App一个实例
|
|
9
|
-
*
|
|
10
|
-
* @author chitanda
|
|
11
|
-
* @date 2023-04-16 17:04:06
|
|
12
|
-
* @export
|
|
13
|
-
* @class ModelUtil
|
|
14
|
-
*/
|
|
15
|
-
export class ModelUtil {
|
|
16
|
-
/**
|
|
17
|
-
* 模型缓存
|
|
18
|
-
*
|
|
19
|
-
* @author chitanda
|
|
20
|
-
* @date 2023-04-16 17:04:40
|
|
21
|
-
* @protected
|
|
22
|
-
* @type {Map<string, IModel>}
|
|
23
|
-
*/
|
|
24
|
-
protected modelCache: Map<string, IModel> = new Map();
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* 应用模型
|
|
28
|
-
*
|
|
29
|
-
* @author chitanda
|
|
30
|
-
* @date 2023-04-16 17:04:17
|
|
31
|
-
* @protected
|
|
32
|
-
* @type {IModel}
|
|
33
|
-
*/
|
|
34
|
-
protected appModel!: IModel;
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* 服务路径计算工具类
|
|
38
|
-
*
|
|
39
|
-
* @author chitanda
|
|
40
|
-
* @date 2023-04-22 12:04:15
|
|
41
|
-
* @type {ServicePathUtil}
|
|
42
|
-
*/
|
|
43
|
-
servicePathUtil!: ServicePathUtil;
|
|
44
|
-
|
|
45
|
-
/**
|
|
46
|
-
* Creates an instance of GlobalModel.
|
|
47
|
-
*
|
|
48
|
-
* @author chitanda
|
|
49
|
-
* @date 2023-04-13 21:04:21
|
|
50
|
-
* @param {string}appId 应用标识
|
|
51
|
-
* @param {string} modelTag
|
|
52
|
-
* @param {(url: string, params?: IParams) => Promise<IModel>} get 模型加载方法
|
|
53
|
-
* @param {boolean} hub 是否为 hub 应用基座
|
|
54
|
-
*/
|
|
55
|
-
constructor(
|
|
56
|
-
protected appId: string,
|
|
57
|
-
protected modelTag: string,
|
|
58
|
-
protected get: (url: string, params?: IParams) => Promise<IModel>,
|
|
59
|
-
protected hub: boolean,
|
|
60
|
-
protected permission: boolean = true,
|
|
61
|
-
) {}
|
|
62
|
-
|
|
63
|
-
/**
|
|
64
|
-
* 在使用前需要初始化,来进行异步加载
|
|
65
|
-
*
|
|
66
|
-
* @author chitanda
|
|
67
|
-
* @date 2023-04-16 17:04:35
|
|
68
|
-
* @return {*} {Promise<void>}
|
|
69
|
-
*/
|
|
70
|
-
async init(): Promise<void> {
|
|
71
|
-
await this.getAppModel();
|
|
72
|
-
await this.specialHandling();
|
|
73
|
-
// 填充缓存模型
|
|
74
|
-
{
|
|
75
|
-
const { cache } = this.appModel;
|
|
76
|
-
if (cache) {
|
|
77
|
-
const views = cache.getPSAppViews;
|
|
78
|
-
if (views) {
|
|
79
|
-
views.forEach((item: IModel) => {
|
|
80
|
-
item.path = item.dynaModelFilePath;
|
|
81
|
-
const appPath = this.calcAppPath(item.path);
|
|
82
|
-
this.modelCache.set(appPath, item);
|
|
83
|
-
});
|
|
84
|
-
if (this.appModel.getAllPSAppViews == null) {
|
|
85
|
-
this.appModel.getAllPSAppViews = views;
|
|
86
|
-
} else {
|
|
87
|
-
this.appModel.getAllPSAppViews.push(...views);
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
const allDataEntities = (this.appModel.getAllPSAppDataEntities ||
|
|
93
|
-
[]) as IModel[];
|
|
94
|
-
allDataEntities.forEach(item => {
|
|
95
|
-
item.id = calcUniqueTag(item, false);
|
|
96
|
-
});
|
|
97
|
-
const allViews = (this.appModel.getAllPSAppViews || []) as IModel[];
|
|
98
|
-
allViews.forEach(item => {
|
|
99
|
-
item.id = calcUniqueTag(item, false);
|
|
100
|
-
});
|
|
101
|
-
const allAppDERSs = (this.appModel.getAllPSAppDERSs || []) as IModel[];
|
|
102
|
-
allAppDERSs.forEach(item => {
|
|
103
|
-
const major = item.getMajorPSAppDataEntity;
|
|
104
|
-
const minor = item.getMinorPSAppDataEntity;
|
|
105
|
-
item.majorAppDataEntityId = calcUniqueTag(major, false);
|
|
106
|
-
item.minorAppDataEntityId = calcUniqueTag(minor, false);
|
|
107
|
-
});
|
|
108
|
-
this.servicePathUtil = new ServicePathUtil(
|
|
109
|
-
allDataEntities,
|
|
110
|
-
allAppDERSs as IAppDERS[],
|
|
111
|
-
);
|
|
112
|
-
if (
|
|
113
|
-
this.appModel.getAllPSAppLans &&
|
|
114
|
-
this.appModel.getAllPSAppLans.length > 0
|
|
115
|
-
) {
|
|
116
|
-
ibiz.env.isEnableMultiLan = true;
|
|
117
|
-
} else {
|
|
118
|
-
ibiz.env.isEnableMultiLan = false;
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
/**
|
|
123
|
-
* 特殊处理应用模型
|
|
124
|
-
*
|
|
125
|
-
* @author chitanda
|
|
126
|
-
* @date 2023-09-21 15:09:07
|
|
127
|
-
* @protected
|
|
128
|
-
* @return {*} {Promise<void>}
|
|
129
|
-
*/
|
|
130
|
-
protected async specialHandling(): Promise<void> {
|
|
131
|
-
// 特殊处理预置全局界面行为,附加一些特殊的模板预置模型
|
|
132
|
-
if (this.appModel.getAllPSAppDEUIActions) {
|
|
133
|
-
mergeModel(
|
|
134
|
-
this.appModel.getAllPSAppDEUIActions,
|
|
135
|
-
PSSysApp.getAllPSAppDEUIActions,
|
|
136
|
-
'codeName',
|
|
137
|
-
);
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
/**
|
|
142
|
-
* 获取应用模型
|
|
143
|
-
*
|
|
144
|
-
* @author chitanda
|
|
145
|
-
* @date 2023-04-16 17:04:21
|
|
146
|
-
* @return {*} {Promise<IModel>}
|
|
147
|
-
*/
|
|
148
|
-
async getAppModel(): Promise<IModel> {
|
|
149
|
-
if (!this.appModel) {
|
|
150
|
-
let appPath: string = '/PSSYSAPP.json';
|
|
151
|
-
if (this.hub && ibiz.env.hub) {
|
|
152
|
-
appPath = `/PSSYSAPP.hub.json`;
|
|
153
|
-
}
|
|
154
|
-
if (this.permission === false) {
|
|
155
|
-
appPath = `/simple/PSSYSAPP.simple.json`;
|
|
156
|
-
}
|
|
157
|
-
this.appModel = await this.getModel(appPath);
|
|
158
|
-
this.appModel.id = this.appId;
|
|
159
|
-
}
|
|
160
|
-
return this.appModel;
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
/**
|
|
164
|
-
* 加载应用模型全局样式
|
|
165
|
-
*
|
|
166
|
-
* @author chitanda
|
|
167
|
-
* @date 2023-09-06 10:09:11
|
|
168
|
-
* @return {*} {(Promise<string | null>)}
|
|
169
|
-
*/
|
|
170
|
-
async getAppStyle(): Promise<string | null> {
|
|
171
|
-
let style: string = '';
|
|
172
|
-
try {
|
|
173
|
-
let stylePath: string = '/PSSYSAPP.json.css';
|
|
174
|
-
if (this.hub && ibiz.env.hub) {
|
|
175
|
-
stylePath = `/PSSYSAPP.hubsubapp.json.css`;
|
|
176
|
-
}
|
|
177
|
-
if (this.permission === false) {
|
|
178
|
-
stylePath = `/simple/PSSYSAPP.simple.json.css`;
|
|
179
|
-
}
|
|
180
|
-
style = await this.getStyleModel(stylePath);
|
|
181
|
-
if (style) {
|
|
182
|
-
return style;
|
|
183
|
-
}
|
|
184
|
-
} catch (error) {
|
|
185
|
-
// 忽略样式加载异常
|
|
186
|
-
ibiz.log.error(error);
|
|
187
|
-
}
|
|
188
|
-
return null;
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
/**
|
|
192
|
-
* 根据应用实体 codeName 或者 id 获取应用实体模型
|
|
193
|
-
*
|
|
194
|
-
* @author chitanda
|
|
195
|
-
* @date 2023-04-16 18:04:45
|
|
196
|
-
* @param {string} tag
|
|
197
|
-
* @param {boolean} [isId=true]
|
|
198
|
-
* @param {boolean} [ignoreCase=false]
|
|
199
|
-
* @return {*} {Promise<IModel>}
|
|
200
|
-
*/
|
|
201
|
-
async getAppDataEntityModel(
|
|
202
|
-
tag: string,
|
|
203
|
-
isId: boolean = true,
|
|
204
|
-
ignoreCase: boolean = false,
|
|
205
|
-
): Promise<IModel> {
|
|
206
|
-
const allDataEntities = this.appModel.getAllPSAppDataEntities as IModel[];
|
|
207
|
-
if (allDataEntities && allDataEntities.length > 0) {
|
|
208
|
-
const lowerTag = tag.toLowerCase();
|
|
209
|
-
let dataEntity: IModel | undefined;
|
|
210
|
-
if (isId) {
|
|
211
|
-
dataEntity = allDataEntities.find(v => {
|
|
212
|
-
if (ignoreCase) {
|
|
213
|
-
return v.id.toLowerCase() === lowerTag;
|
|
214
|
-
}
|
|
215
|
-
return v.id === tag;
|
|
216
|
-
});
|
|
217
|
-
} else {
|
|
218
|
-
dataEntity = allDataEntities.find(v => {
|
|
219
|
-
if (ignoreCase) {
|
|
220
|
-
return v.codeName.toLowerCase() === lowerTag;
|
|
221
|
-
}
|
|
222
|
-
return v.codeName === tag;
|
|
223
|
-
});
|
|
224
|
-
}
|
|
225
|
-
if (dataEntity) {
|
|
226
|
-
return this.getModel(dataEntity.path);
|
|
227
|
-
}
|
|
228
|
-
}
|
|
229
|
-
throw new Error(`应用[${this.appId}]未找到数据实体[${tag}]`);
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
/**
|
|
233
|
-
* 根据应用视图 id 获取应用视图模型,如果给了 params 则每次都会重新加载模型
|
|
234
|
-
*
|
|
235
|
-
* @author chitanda
|
|
236
|
-
* @date 2024-01-15 12:01:36
|
|
237
|
-
* @param {string} tag
|
|
238
|
-
* @param {IParams} [params]
|
|
239
|
-
* @param {boolean} [isDynamic]
|
|
240
|
-
* @return {*} {Promise<IModel>}
|
|
241
|
-
*/
|
|
242
|
-
async getAppViewModel(
|
|
243
|
-
tag: string,
|
|
244
|
-
params?: IParams,
|
|
245
|
-
isDynamic?: boolean,
|
|
246
|
-
): Promise<IModel> {
|
|
247
|
-
const allViews = this.appModel.getAllPSAppViews as IModel[];
|
|
248
|
-
if (allViews && allViews.length > 0) {
|
|
249
|
-
const lowerTag = tag.toLowerCase();
|
|
250
|
-
const exTag = `.${lowerTag}`;
|
|
251
|
-
const view = allViews.find(
|
|
252
|
-
v => v.id.endsWith(exTag) || v.id === lowerTag,
|
|
253
|
-
);
|
|
254
|
-
if (view) {
|
|
255
|
-
return this.getModel(view.path, params, isDynamic);
|
|
256
|
-
}
|
|
257
|
-
}
|
|
258
|
-
throw new Error(`应用[${this.appId}]未找到视图[${tag}]`);
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
/**
|
|
262
|
-
* 加载应用多语言模型
|
|
263
|
-
*
|
|
264
|
-
* @author chitanda
|
|
265
|
-
* @date 2023-08-24 22:08:23
|
|
266
|
-
* @param {string} language
|
|
267
|
-
* @return {*} {Promise<IModel>}
|
|
268
|
-
*/
|
|
269
|
-
async getPSAppLang(language: string): Promise<IModel> {
|
|
270
|
-
const app = await this.getAppModel();
|
|
271
|
-
if (app.getAllPSAppLans) {
|
|
272
|
-
const langs = app.getAllPSAppLans as IModel[];
|
|
273
|
-
const lang = langs.find(item => item.language === language);
|
|
274
|
-
if (lang) {
|
|
275
|
-
return this.getModel(lang.path);
|
|
276
|
-
}
|
|
277
|
-
ibiz.log.error(`[${language}]语言未支持`);
|
|
278
|
-
}
|
|
279
|
-
return {};
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
/**
|
|
283
|
-
* 加载应用样式字符串
|
|
284
|
-
*
|
|
285
|
-
* @author chitanda
|
|
286
|
-
* @date 2023-09-07 11:09:11
|
|
287
|
-
* @param {string} modelPath
|
|
288
|
-
* @return {*} {Promise<string>}
|
|
289
|
-
*/
|
|
290
|
-
getStyleModel(modelPath: string): Promise<string> {
|
|
291
|
-
let url: string;
|
|
292
|
-
if (this.hub) {
|
|
293
|
-
url = this.calcAppPath(modelPath);
|
|
294
|
-
} else {
|
|
295
|
-
url = this.calcSubAppPath(modelPath);
|
|
296
|
-
}
|
|
297
|
-
return this.get(url) as unknown as Promise<string>;
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
/**
|
|
301
|
-
* 加载模型,如果给了 params 则不会缓存模型
|
|
302
|
-
*
|
|
303
|
-
* @author chitanda
|
|
304
|
-
* @date 2024-01-15 12:01:57
|
|
305
|
-
* @param {string} modelPath
|
|
306
|
-
* @param {IParams} [params]
|
|
307
|
-
* @param {boolean} [isDynamic]
|
|
308
|
-
* @return {*} {Promise<IModel>}
|
|
309
|
-
*/
|
|
310
|
-
async getModel(
|
|
311
|
-
modelPath: string,
|
|
312
|
-
params?: IParams,
|
|
313
|
-
isDynamic?: boolean,
|
|
314
|
-
): Promise<IModel> {
|
|
315
|
-
let url: string;
|
|
316
|
-
if (this.hub) {
|
|
317
|
-
url = this.calcAppPath(modelPath, isDynamic);
|
|
318
|
-
} else {
|
|
319
|
-
url = this.calcSubAppPath(modelPath, isDynamic);
|
|
320
|
-
}
|
|
321
|
-
const isParams = params && !isEmpty(params);
|
|
322
|
-
if (this.modelCache.has(url) && !isParams) {
|
|
323
|
-
return this.modelCache.get(url)!;
|
|
324
|
-
}
|
|
325
|
-
const model = await this.get(url, params);
|
|
326
|
-
if (!isParams) {
|
|
327
|
-
this.modelCache.set(url, model);
|
|
328
|
-
}
|
|
329
|
-
this.deepFillAppId(model);
|
|
330
|
-
return model;
|
|
331
|
-
}
|
|
332
|
-
|
|
333
|
-
/**
|
|
334
|
-
* 递归填充应用标识
|
|
335
|
-
*
|
|
336
|
-
* @author chitanda
|
|
337
|
-
* @date 2023-08-21 10:08:41
|
|
338
|
-
* @protected
|
|
339
|
-
* @param {IModel} model
|
|
340
|
-
*/
|
|
341
|
-
protected deepFillAppId(model: IModel): void {
|
|
342
|
-
model.appId = this.appId;
|
|
343
|
-
const keys = Object.keys(model);
|
|
344
|
-
keys.forEach(key => {
|
|
345
|
-
const value = model[key];
|
|
346
|
-
if (value && typeof value === 'object') {
|
|
347
|
-
if (Array.isArray(value)) {
|
|
348
|
-
value.forEach(item => {
|
|
349
|
-
if (item && typeof item === 'object') {
|
|
350
|
-
this.deepFillAppId(item);
|
|
351
|
-
}
|
|
352
|
-
});
|
|
353
|
-
} else {
|
|
354
|
-
this.deepFillAppId(value);
|
|
355
|
-
}
|
|
356
|
-
}
|
|
357
|
-
});
|
|
358
|
-
}
|
|
359
|
-
|
|
360
|
-
/**
|
|
361
|
-
* 计算应用模型请求路径
|
|
362
|
-
*
|
|
363
|
-
* @author chitanda
|
|
364
|
-
* @date 2024-01-15 12:01:45
|
|
365
|
-
* @protected
|
|
366
|
-
* @param {string} modelPath
|
|
367
|
-
* @param {boolean} [isDynamic=false]
|
|
368
|
-
* @return {*} {string}
|
|
369
|
-
*/
|
|
370
|
-
protected calcAppPath(modelPath: string, isDynamic: boolean = false): string {
|
|
371
|
-
if (isDynamic) {
|
|
372
|
-
return formatPath(modelPath);
|
|
373
|
-
}
|
|
374
|
-
return `${formatPath(modelPath)}${
|
|
375
|
-
this.modelTag ? `?dynamodeltag=${this.modelTag}` : ''
|
|
376
|
-
}`;
|
|
377
|
-
}
|
|
378
|
-
|
|
379
|
-
/**
|
|
380
|
-
* 计算子应用模型请求路径
|
|
381
|
-
*
|
|
382
|
-
* @author chitanda
|
|
383
|
-
* @date 2024-01-15 12:01:39
|
|
384
|
-
* @protected
|
|
385
|
-
* @param {string} modelPath
|
|
386
|
-
* @param {boolean} [isDynamic=false]
|
|
387
|
-
* @return {*} {string}
|
|
388
|
-
*/
|
|
389
|
-
protected calcSubAppPath(
|
|
390
|
-
modelPath: string,
|
|
391
|
-
isDynamic: boolean = false,
|
|
392
|
-
): string {
|
|
393
|
-
if (isDynamic) {
|
|
394
|
-
return `/subapps/${this.appId}${formatPath(modelPath)}`;
|
|
395
|
-
}
|
|
396
|
-
return `/subapps/${this.appId}${formatPath(modelPath)}?dynamodeltag=${
|
|
397
|
-
this.modelTag
|
|
398
|
-
}`;
|
|
399
|
-
}
|
|
400
|
-
}
|
package/src/utils/index.ts
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
export { formatPath } from './format-path/format-path';
|
|
2
|
-
export { mergeModel } from './merge-model/merge-model';
|
|
3
|
-
export { plural, pluralLower } from './plural/plural';
|
|
4
|
-
export {
|
|
5
|
-
ServicePathDeep,
|
|
6
|
-
ServicePathItem,
|
|
7
|
-
ServicePathUtil,
|
|
8
|
-
} from './service-path-util/service-path-util';
|
|
9
|
-
export { mergeAppMenu } from './merge-model/merge-app-menu';
|
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
import { IAppMenuItem, IAppMenuModel, ISubAppRef } from '@ibiz/model-core';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* 递归合并主菜单项和子菜单项
|
|
5
|
-
* @author lxm
|
|
6
|
-
* @date 2023-12-07 03:16:13
|
|
7
|
-
* @param {IAppMenuItem} mainItem
|
|
8
|
-
* @param {IAppMenuItem} subItem
|
|
9
|
-
*/
|
|
10
|
-
function mergeMenuItem(mainItem: IAppMenuItem, subItem: IAppMenuItem): void {
|
|
11
|
-
// 主菜单项没有子菜单项直接合并替换
|
|
12
|
-
if (!mainItem.appMenuItems?.length) {
|
|
13
|
-
if (subItem.appMenuItems?.length) {
|
|
14
|
-
// 子菜单有下级菜单的时候只是添加下级菜单
|
|
15
|
-
mainItem.appMenuItems = subItem.appMenuItems;
|
|
16
|
-
} else {
|
|
17
|
-
// 子菜单项也没有下级菜单的时候覆盖
|
|
18
|
-
Object.assign(mainItem, subItem);
|
|
19
|
-
}
|
|
20
|
-
} else {
|
|
21
|
-
const addItems: IAppMenuItem[] = [];
|
|
22
|
-
subItem.appMenuItems?.forEach(item => {
|
|
23
|
-
const sameMenu = mainItem.appMenuItems?.find(x => x.id === item.id);
|
|
24
|
-
if (sameMenu) {
|
|
25
|
-
mergeMenuItem(sameMenu, item);
|
|
26
|
-
} else {
|
|
27
|
-
addItems.push(item);
|
|
28
|
-
}
|
|
29
|
-
});
|
|
30
|
-
mainItem.appMenuItems.push(...addItems);
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* 合并主菜单和子菜单
|
|
36
|
-
* @author lxm
|
|
37
|
-
* @date 2023-12-07 03:15:54
|
|
38
|
-
* @param {IAppMenuModel} main
|
|
39
|
-
* @param {IAppMenuModel} sub
|
|
40
|
-
*/
|
|
41
|
-
function mergeMenu(main: IAppMenuModel, sub: IAppMenuModel): void {
|
|
42
|
-
const addItems: IAppMenuItem[] = [];
|
|
43
|
-
sub.appMenuItems?.forEach(item => {
|
|
44
|
-
const sameMenu = main.appMenuItems?.find(x => x.id === item.id);
|
|
45
|
-
if (sameMenu) {
|
|
46
|
-
mergeMenuItem(sameMenu, item);
|
|
47
|
-
} else {
|
|
48
|
-
addItems.push(item);
|
|
49
|
-
}
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
if (!main.appMenuItems) {
|
|
53
|
-
main.appMenuItems = [];
|
|
54
|
-
}
|
|
55
|
-
main.appMenuItems.push(...addItems);
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
/**
|
|
59
|
-
* 合并主应用首页菜单
|
|
60
|
-
* @author lxm
|
|
61
|
-
* @date 2023-12-07 02:26:57
|
|
62
|
-
* @export
|
|
63
|
-
* @param {IAppMenuModel} mainMenu
|
|
64
|
-
* @param {ISubAppRef[]} subAppRefs
|
|
65
|
-
*/
|
|
66
|
-
export function mergeAppMenu(
|
|
67
|
-
mainMenu: IAppMenuModel,
|
|
68
|
-
subAppRefs: ISubAppRef[],
|
|
69
|
-
): void {
|
|
70
|
-
const subMenus: IAppMenuModel[] = [];
|
|
71
|
-
subAppRefs.forEach(sub => {
|
|
72
|
-
if (sub.appMenuModel?.appMenuItems?.length) {
|
|
73
|
-
subMenus.push(sub.appMenuModel);
|
|
74
|
-
}
|
|
75
|
-
});
|
|
76
|
-
if (subMenus.length === 0) {
|
|
77
|
-
return;
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
// 依次合并主应用菜单和子应用菜单
|
|
81
|
-
subMenus.forEach(subMenu => {
|
|
82
|
-
mergeMenu(mainMenu, subMenu);
|
|
83
|
-
});
|
|
84
|
-
}
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import { mergeDeepLeft } from 'ramda';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* 将预置的模型合并到当前模型中
|
|
5
|
-
*
|
|
6
|
-
* @author chitanda
|
|
7
|
-
* @date 2023-09-22 10:09:10
|
|
8
|
-
* @export
|
|
9
|
-
* @param {IModel[]} models
|
|
10
|
-
* @param {IModel} m
|
|
11
|
-
* @param {string} tag
|
|
12
|
-
*/
|
|
13
|
-
export function mergeModel(models: IModel[], m: IModel, tag: string): void {
|
|
14
|
-
models.forEach(model => {
|
|
15
|
-
const item = m[model[tag]];
|
|
16
|
-
if (item) {
|
|
17
|
-
Object.assign(model, mergeDeepLeft(model, item));
|
|
18
|
-
}
|
|
19
|
-
});
|
|
20
|
-
}
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import pluralize from 'pluralize';
|
|
2
|
-
|
|
3
|
-
// 补充特殊转换规则
|
|
4
|
-
pluralize.addPluralRule(/(matr|vert|ind)ix|ex$/, '$1ices');
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* 英文转复数写法
|
|
8
|
-
*
|
|
9
|
-
* @author chitanda
|
|
10
|
-
* @date 2022-08-25 18:08:41
|
|
11
|
-
* @export
|
|
12
|
-
* @param {string} key
|
|
13
|
-
* @return {*} {string}
|
|
14
|
-
*/
|
|
15
|
-
export function plural(key: string): string {
|
|
16
|
-
return pluralize(key);
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* 英文转复数写法并转全小写
|
|
21
|
-
*
|
|
22
|
-
* @author chitanda
|
|
23
|
-
* @date 2022-08-25 18:08:23
|
|
24
|
-
* @export
|
|
25
|
-
* @param {string} key
|
|
26
|
-
* @return {*} {string}
|
|
27
|
-
*/
|
|
28
|
-
export function pluralLower(key: string): string {
|
|
29
|
-
return plural(key).toLowerCase();
|
|
30
|
-
}
|
|
@@ -1,249 +0,0 @@
|
|
|
1
|
-
import { IAppDERS } from '@ibiz/model-core';
|
|
2
|
-
import { pluralLower } from '../plural/plural';
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* 获取服务拼接递归对象
|
|
6
|
-
*/
|
|
7
|
-
export type ServicePathDeep = [IAppDERS, ServicePathDeep[]];
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* 服务路径项
|
|
11
|
-
*/
|
|
12
|
-
export type ServicePathItem = {
|
|
13
|
-
/**
|
|
14
|
-
* 实体代码名称(标准)
|
|
15
|
-
*
|
|
16
|
-
* @author chitanda
|
|
17
|
-
* @date 2022-08-25 18:08:35
|
|
18
|
-
* @type {string}
|
|
19
|
-
*/
|
|
20
|
-
codeName: string;
|
|
21
|
-
/**
|
|
22
|
-
* 实体代码名称(小写)
|
|
23
|
-
*
|
|
24
|
-
* @author chitanda
|
|
25
|
-
* @date 2022-08-25 18:08:54
|
|
26
|
-
* @type {string}
|
|
27
|
-
*/
|
|
28
|
-
lower: string;
|
|
29
|
-
/**
|
|
30
|
-
* 实体代码名称复数(小写)
|
|
31
|
-
*
|
|
32
|
-
* @author chitanda
|
|
33
|
-
* @date 2022-08-25 18:08:13
|
|
34
|
-
* @type {string}
|
|
35
|
-
*/
|
|
36
|
-
plural: string;
|
|
37
|
-
};
|
|
38
|
-
|
|
39
|
-
/**
|
|
40
|
-
* 服务路径拼接工具
|
|
41
|
-
*
|
|
42
|
-
* @author chitanda
|
|
43
|
-
* @date 2022-08-22 21:08:52
|
|
44
|
-
* @export
|
|
45
|
-
* @class ServicePathUtil
|
|
46
|
-
*/
|
|
47
|
-
export class ServicePathUtil {
|
|
48
|
-
/**
|
|
49
|
-
* 应用实体关系
|
|
50
|
-
*
|
|
51
|
-
* @author chitanda
|
|
52
|
-
* @date 2022-08-22 22:08:18
|
|
53
|
-
* @protected
|
|
54
|
-
* @type {Map<string, IAppDERS[]>} <应用实体 id, 应用实体父关系>
|
|
55
|
-
*/
|
|
56
|
-
protected entityRsMap: Map<string, IAppDERS[]> = new Map();
|
|
57
|
-
|
|
58
|
-
/**
|
|
59
|
-
* 实体资源路径
|
|
60
|
-
*
|
|
61
|
-
* @author chitanda
|
|
62
|
-
* @date 2022-08-22 22:08:58
|
|
63
|
-
* @protected
|
|
64
|
-
* @type {Map<string, ServicePathItem[][]>}
|
|
65
|
-
*/
|
|
66
|
-
protected entityRsPathMap: Map<string, ServicePathItem[][]> = new Map();
|
|
67
|
-
|
|
68
|
-
constructor(
|
|
69
|
-
protected appDataEntities: IModel[],
|
|
70
|
-
protected allDERss: IAppDERS[],
|
|
71
|
-
) {}
|
|
72
|
-
|
|
73
|
-
/**
|
|
74
|
-
* 根据应用主实体过滤从关系集合
|
|
75
|
-
*
|
|
76
|
-
* @author chitanda
|
|
77
|
-
* @date 2023-04-20 17:04:34
|
|
78
|
-
* @protected
|
|
79
|
-
* @param {string} id
|
|
80
|
-
* @return {*} {IAppDERS[]}
|
|
81
|
-
*/
|
|
82
|
-
protected filterDERSs(id: string): IAppDERS[] {
|
|
83
|
-
if (this.entityRsMap.has(id)) {
|
|
84
|
-
return this.entityRsMap.get(id)!;
|
|
85
|
-
}
|
|
86
|
-
const items = this.allDERss.filter(item => {
|
|
87
|
-
if ((item as IModel).rSMode === 2 && item.minorAppDataEntityId === id) {
|
|
88
|
-
return item;
|
|
89
|
-
}
|
|
90
|
-
return null;
|
|
91
|
-
});
|
|
92
|
-
if (items.length > 0) {
|
|
93
|
-
this.entityRsMap.set(id, items);
|
|
94
|
-
}
|
|
95
|
-
return items;
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
/**
|
|
99
|
-
* 计算指定应用实体所有资源路径
|
|
100
|
-
*
|
|
101
|
-
* @author chitanda
|
|
102
|
-
* @date 2023-04-22 13:04:27
|
|
103
|
-
* @param {string} id
|
|
104
|
-
* @return {*} {string[]}
|
|
105
|
-
*/
|
|
106
|
-
calcRequestPaths(id: string): string[] {
|
|
107
|
-
const paths = this.calcPaths(id);
|
|
108
|
-
return paths.map(path => {
|
|
109
|
-
return path.map(item => `${item.plural}/\${${item.lower}}`).join('/');
|
|
110
|
-
});
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
/**
|
|
114
|
-
* 计算指定实体所有资源路径
|
|
115
|
-
*
|
|
116
|
-
* @author chitanda
|
|
117
|
-
* @date 2023-04-22 13:04:36
|
|
118
|
-
* @protected
|
|
119
|
-
* @param {string} id
|
|
120
|
-
* @return {*} {ServicePathItem[][]} 返回顺序为 [祖父实体,爷爷实体,父实体,当前实体]
|
|
121
|
-
*/
|
|
122
|
-
protected calcPaths(id: string): ServicePathItem[][] {
|
|
123
|
-
const entityRef = this.appDataEntities.find(item => item.id === id);
|
|
124
|
-
if (!entityRef) {
|
|
125
|
-
throw new Error(`未找到实体 ${id}`);
|
|
126
|
-
}
|
|
127
|
-
const { codeName } = entityRef;
|
|
128
|
-
if (this.entityRsPathMap.has(codeName)) {
|
|
129
|
-
return this.entityRsPathMap.get(codeName)!;
|
|
130
|
-
}
|
|
131
|
-
const deRss = this.filterDERSs(id);
|
|
132
|
-
if (deRss) {
|
|
133
|
-
// 已经计算过的应用实体标识
|
|
134
|
-
const ids: string[] = [id];
|
|
135
|
-
const arr = this.calcDeepPath(ids, deRss);
|
|
136
|
-
this.deepFillPath(codeName, [codeName], arr);
|
|
137
|
-
let paths = this.entityRsPathMap.get(codeName);
|
|
138
|
-
if (paths) {
|
|
139
|
-
paths = this.sortPath(paths);
|
|
140
|
-
this.entityRsPathMap.set(codeName, paths);
|
|
141
|
-
return paths;
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
return [];
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
/**
|
|
148
|
-
* 计算递归资源路径
|
|
149
|
-
*
|
|
150
|
-
* @author chitanda
|
|
151
|
-
* @date 2023-08-23 14:08:39
|
|
152
|
-
* @protected
|
|
153
|
-
* @param {string[]} ids
|
|
154
|
-
* @param {IAppDERS[]} deRss
|
|
155
|
-
* @param {number} [num=0]
|
|
156
|
-
* @return {*} {ServicePathDeep[]}
|
|
157
|
-
*/
|
|
158
|
-
protected calcDeepPath(
|
|
159
|
-
ids: string[],
|
|
160
|
-
deRss: IAppDERS[],
|
|
161
|
-
num: number = 0,
|
|
162
|
-
): ServicePathDeep[] {
|
|
163
|
-
if (num > 10) {
|
|
164
|
-
throw new Error('服务路径计算超过最大层级 10');
|
|
165
|
-
}
|
|
166
|
-
num += 1;
|
|
167
|
-
const arr: ServicePathDeep[] = [];
|
|
168
|
-
deRss.forEach(rs => {
|
|
169
|
-
if (ids.includes(rs.majorAppDataEntityId!)) {
|
|
170
|
-
ibiz.log.warn(
|
|
171
|
-
'计算资源关系路径出现循环递归引用,触发实体:',
|
|
172
|
-
rs.majorAppDataEntityId,
|
|
173
|
-
'当前已计算过实体清单: ',
|
|
174
|
-
ids,
|
|
175
|
-
);
|
|
176
|
-
return;
|
|
177
|
-
}
|
|
178
|
-
const items = this.filterDERSs(rs.majorAppDataEntityId!);
|
|
179
|
-
arr.push([
|
|
180
|
-
rs,
|
|
181
|
-
this.calcDeepPath([...ids, rs.majorAppDataEntityId!], items, num),
|
|
182
|
-
]);
|
|
183
|
-
});
|
|
184
|
-
return arr;
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
/**
|
|
188
|
-
* 递归填充计算所有资源路径
|
|
189
|
-
*
|
|
190
|
-
* @author chitanda
|
|
191
|
-
* @date 2022-08-22 22:08:04
|
|
192
|
-
* @protected
|
|
193
|
-
* @param {string} deCodeName
|
|
194
|
-
* @param {string[]} pathNames
|
|
195
|
-
* @param {ServicePathDeep[]} items
|
|
196
|
-
*/
|
|
197
|
-
protected deepFillPath(
|
|
198
|
-
deCodeName: string,
|
|
199
|
-
pathNames: string[],
|
|
200
|
-
items: ServicePathDeep[],
|
|
201
|
-
): void {
|
|
202
|
-
items.forEach(item => {
|
|
203
|
-
const [rs, children] = item;
|
|
204
|
-
if (children.length > 0) {
|
|
205
|
-
this.deepFillPath(
|
|
206
|
-
deCodeName,
|
|
207
|
-
[...pathNames, rs.majorDECodeName!],
|
|
208
|
-
children,
|
|
209
|
-
);
|
|
210
|
-
}
|
|
211
|
-
if (!this.entityRsPathMap.has(deCodeName)) {
|
|
212
|
-
this.entityRsPathMap.set(deCodeName, []);
|
|
213
|
-
}
|
|
214
|
-
const arr = this.entityRsPathMap.get(deCodeName)!;
|
|
215
|
-
|
|
216
|
-
arr.push(
|
|
217
|
-
[
|
|
218
|
-
...pathNames.map(pathName => {
|
|
219
|
-
return {
|
|
220
|
-
codeName: pathName,
|
|
221
|
-
lower: pathName.toLowerCase(),
|
|
222
|
-
plural: pluralLower(pathName),
|
|
223
|
-
};
|
|
224
|
-
}),
|
|
225
|
-
{
|
|
226
|
-
codeName: rs.majorDECodeName!,
|
|
227
|
-
lower: rs.majorDECodeName!.toLowerCase(),
|
|
228
|
-
plural: pluralLower(rs.majorDECodeName!),
|
|
229
|
-
},
|
|
230
|
-
].reverse(),
|
|
231
|
-
);
|
|
232
|
-
});
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
/**
|
|
236
|
-
* 排序资源路径顺序
|
|
237
|
-
*
|
|
238
|
-
* @author chitanda
|
|
239
|
-
* @date 2022-08-22 22:08:44
|
|
240
|
-
* @protected
|
|
241
|
-
* @param {ServicePathItem[][]} paths
|
|
242
|
-
* @return {*} {ServicePathItem[][]}
|
|
243
|
-
*/
|
|
244
|
-
protected sortPath(paths: ServicePathItem[][]): ServicePathItem[][] {
|
|
245
|
-
return paths.sort((a, b) => {
|
|
246
|
-
return b.length - a.length;
|
|
247
|
-
});
|
|
248
|
-
}
|
|
249
|
-
}
|