@ibiz-template/runtime 0.5.1 → 0.5.3-beta.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.
Files changed (39) hide show
  1. package/dist/index.esm.js +198 -152
  2. package/dist/index.system.min.js +1 -1
  3. package/out/app-hub.d.ts +11 -0
  4. package/out/app-hub.d.ts.map +1 -1
  5. package/out/app-hub.js +17 -0
  6. package/out/controller/control/form/edit-form/edit-form.controller.d.ts.map +1 -1
  7. package/out/controller/control/form/edit-form/edit-form.controller.js +0 -1
  8. package/out/controller/control/tree-grid-ex/tree-grid-ex-column/tree-grid-ex-field-column/tree-grid-ex-field-column.controller.d.ts +0 -9
  9. package/out/controller/control/tree-grid-ex/tree-grid-ex-column/tree-grid-ex-field-column/tree-grid-ex-field-column.controller.d.ts.map +1 -1
  10. package/out/controller/control/tree-grid-ex/tree-grid-ex-column/tree-grid-ex-field-column/tree-grid-ex-field-column.controller.js +0 -20
  11. package/out/controller/control/tree-grid-ex/tree-grid-ex-row.state.d.ts.map +1 -1
  12. package/out/controller/control/tree-grid-ex/tree-grid-ex-row.state.js +0 -4
  13. package/out/interface/common/i-app-hub-service/i-app-hub-service.d.ts +11 -0
  14. package/out/interface/common/i-app-hub-service/i-app-hub-service.d.ts.map +1 -1
  15. package/out/interface/provider/model-loader.provider.d.ts +11 -0
  16. package/out/interface/provider/model-loader.provider.d.ts.map +1 -1
  17. package/out/logic-scheduler/executor/app-ui-logic-executor.d.ts +2 -2
  18. package/out/logic-scheduler/executor/app-ui-logic-executor.d.ts.map +1 -1
  19. package/out/logic-scheduler/executor/app-ui-logic-executor.js +26 -32
  20. package/out/service/dto/method.dto.d.ts.map +1 -1
  21. package/out/service/dto/method.dto.js +6 -4
  22. package/out/service/service/entity/method/de-action.d.ts.map +1 -1
  23. package/out/service/service/entity/method/de-action.js +9 -7
  24. package/out/service/vo/tree-node-data/tree-data-set-node-data.d.ts.map +1 -1
  25. package/out/service/vo/tree-node-data/tree-data-set-node-data.js +33 -8
  26. package/out/utils/open-redirect-view/open-redirect-view.d.ts.map +1 -1
  27. package/out/utils/open-redirect-view/open-redirect-view.js +70 -35
  28. package/package.json +3 -3
  29. package/src/app-hub.ts +26 -0
  30. package/src/controller/control/form/edit-form/edit-form.controller.ts +0 -2
  31. package/src/controller/control/tree-grid-ex/tree-grid-ex-column/tree-grid-ex-field-column/tree-grid-ex-field-column.controller.ts +2 -35
  32. package/src/controller/control/tree-grid-ex/tree-grid-ex-row.state.ts +0 -4
  33. package/src/interface/common/i-app-hub-service/i-app-hub-service.ts +16 -0
  34. package/src/interface/provider/model-loader.provider.ts +16 -0
  35. package/src/logic-scheduler/executor/app-ui-logic-executor.ts +42 -32
  36. package/src/service/dto/method.dto.ts +6 -4
  37. package/src/service/service/entity/method/de-action.ts +9 -7
  38. package/src/service/vo/tree-node-data/tree-data-set-node-data.ts +32 -7
  39. package/src/utils/open-redirect-view/open-redirect-view.ts +76 -43
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ibiz-template/runtime",
3
- "version": "0.5.1",
3
+ "version": "0.5.3-beta.0",
4
4
  "description": "控制器包",
5
5
  "type": "module",
6
6
  "main": "out/index.js",
@@ -29,7 +29,7 @@
29
29
  "author": "chitanda",
30
30
  "license": "MIT",
31
31
  "devDependencies": {
32
- "@ibiz-template/core": "^0.5.1-next.0",
32
+ "@ibiz-template/core": "^0.5.2",
33
33
  "@ibiz/model-core": "^0.1.2",
34
34
  "@types/path-browserify": "^1.0.2",
35
35
  "@types/qs": "^6.9.11",
@@ -59,5 +59,5 @@
59
59
  "qx-util": "^0.4.8",
60
60
  "ramda": "^0.29.0"
61
61
  },
62
- "gitHead": "f442a5daebbca26f24b167d8afa470d8fd2ff8b8"
62
+ "gitHead": "5eb401038895adf73adda7baf784193ef0f40ce5"
63
63
  }
package/src/app-hub.ts CHANGED
@@ -233,6 +233,32 @@ export class AppHub implements IAppHubService {
233
233
  throw new RuntimeError(`视图[${id}]不存在`);
234
234
  }
235
235
 
236
+ /**
237
+ * 根据视图模型路径,加参数重新计算视图模型
238
+ *
239
+ * @author chitanda
240
+ * @date 2024-01-08 11:01:54
241
+ * @param {string} appId
242
+ * @param {string} modelPath
243
+ * @param {IParams} params
244
+ * @return {*} {Promise<IAppView>}
245
+ */
246
+ async loadAppView(
247
+ appId: string,
248
+ modelPath: string,
249
+ params: IParams,
250
+ ): Promise<IAppView> {
251
+ if (this.modelLoaderProvider) {
252
+ const model = await this.modelLoaderProvider.loadAppView(
253
+ appId,
254
+ modelPath,
255
+ params,
256
+ );
257
+ return model;
258
+ }
259
+ throw new RuntimeError(`视图[${modelPath}]不存在`);
260
+ }
261
+
236
262
  /**
237
263
  * 根据应用实体代码名称查找应用视图
238
264
  *
@@ -441,8 +441,6 @@ export class EditFormController
441
441
  ),
442
442
  );
443
443
  }
444
-
445
- await awaitTimeout(2000);
446
444
  } finally {
447
445
  if (showBusyIndicator) {
448
446
  this.endLoading();
@@ -1,11 +1,6 @@
1
1
  /* eslint-disable @typescript-eslint/no-unused-vars */
2
- import {
3
- IDETreeDEFColumn,
4
- IDETreeNode,
5
- IDETreeNodeDataItem,
6
- } from '@ibiz/model-core';
2
+ import { IDETreeDEFColumn } from '@ibiz/model-core';
7
3
  import { TreeGridExColumnController } from '../tree-grid-ex-column/tree-grid-ex-column.controller';
8
- import { ITreeGridExRowState } from '../../../../../interface';
9
4
 
10
5
  /**
11
6
  * 树表格(增强)属性列控制器
@@ -15,32 +10,4 @@ import { ITreeGridExRowState } from '../../../../../interface';
15
10
  * @class TreeGridExFieldColumnController
16
11
  * @extends {TreeGridExColumnController<IDETreeDEFColumn>}
17
12
  */
18
- export class TreeGridExFieldColumnController extends TreeGridExColumnController<IDETreeDEFColumn> {
19
- /**
20
- * 给rowController初始化属性列的状态
21
- *
22
- * @author zpc
23
- * @date 2024-01-07 21:09:43
24
- * @param {ITreeGridExRowState} row
25
- */
26
- initColumnStates(row: ITreeGridExRowState): void {
27
- const { data } = row;
28
- if (!this.model.id || !data._deData) {
29
- return;
30
- }
31
-
32
- const { detreeNodeDataItems } = this.treeGrid.getNodeModel(
33
- data._nodeId,
34
- ) as IDETreeNode;
35
- const targetTreeNodeDataItem = detreeNodeDataItems?.find(
36
- (treeNodeDataItem: IDETreeNodeDataItem) => {
37
- return treeNodeDataItem.detreeColumnId === this.model.id;
38
- },
39
- );
40
- if (targetTreeNodeDataItem && targetTreeNodeDataItem.appDEFieldId) {
41
- (data as IData)[this.model.id.toLowerCase()] = (data._deData as IData)[
42
- targetTreeNodeDataItem.appDEFieldId.toLowerCase()
43
- ];
44
- }
45
- }
46
- }
13
+ export class TreeGridExFieldColumnController extends TreeGridExColumnController<IDETreeDEFColumn> {}
@@ -28,10 +28,6 @@ export class TreeGridExRowState implements ITreeGridExRowState {
28
28
 
29
29
  constructor(data: ITreeNodeData, treeGrid: TreeGridExController) {
30
30
  this.data = data;
31
- // 初始化属性列数据状态
32
- Object.values(treeGrid.fieldColumns).forEach(column => {
33
- column.initColumnStates(this);
34
- });
35
31
  // 初始化操作列状态
36
32
  Object.values(treeGrid.uaColumns).forEach(column => {
37
33
  column.initActionStates(this);
@@ -126,6 +126,22 @@ export interface IAppHubService {
126
126
  */
127
127
  getAppView(tag: string): Promise<IAppView>;
128
128
 
129
+ /**
130
+ * 根据参数加载请求视图模型,用于后台根据运行时参数加载视图
131
+ *
132
+ * @author chitanda
133
+ * @date 2024-01-08 11:01:27
134
+ * @param {string} appId
135
+ * @param {string} viewId
136
+ * @param {IParams} params
137
+ * @return {*} {Promise<IAppView>}
138
+ */
139
+ loadAppView(
140
+ appId: string,
141
+ viewId: string,
142
+ params: IParams,
143
+ ): Promise<IAppView>;
144
+
129
145
  /**
130
146
  * 获取应用实体模型
131
147
  *
@@ -38,6 +38,22 @@ export interface ModelLoaderProvider {
38
38
  */
39
39
  getAppView(appId: string, codeName: string): Promise<IAppView>;
40
40
 
41
+ /**
42
+ * 根据参数加载请求视图模型,用于后台根据运行时参数加载视图
43
+ *
44
+ * @author chitanda
45
+ * @date 2024-01-08 10:01:43
46
+ * @param {string} appId
47
+ * @param {string} viewId
48
+ * @param {IParams} params
49
+ * @return {*} {Promise<IAppView>}
50
+ */
51
+ loadAppView(
52
+ appId: string,
53
+ viewId: string,
54
+ params: IParams,
55
+ ): Promise<IAppView>;
56
+
41
57
  /**
42
58
  * 根据 id 获取应用实体模型
43
59
  *
@@ -11,7 +11,7 @@ import {
11
11
  } from '@ibiz/model-core';
12
12
  import { notNilEmpty } from 'qx-util';
13
13
  import { OpenAppViewCommand } from '../../command';
14
- import { IModalData, IUILogicParams } from '../../interface';
14
+ import { IModalData, IUILogicParams, IViewController } from '../../interface';
15
15
  import { calcDeCodeNameById } from '../../model';
16
16
  import { convertNavData } from '../../utils';
17
17
  import { LogicExecutor } from './logic-executor';
@@ -256,7 +256,13 @@ export class AppUILogicExecutor extends LogicExecutor {
256
256
 
257
257
  // 执行批添加新建逻辑
258
258
  if (enableBatchAdd && result.data) {
259
- await this.doBatchAdd(appUILogic, result.data, context, newViewRef);
259
+ await this.doBatchAdd(
260
+ appUILogic,
261
+ result.data,
262
+ context,
263
+ newViewRef,
264
+ parameters.view,
265
+ );
260
266
  }
261
267
 
262
268
  return result;
@@ -325,10 +331,11 @@ export class AppUILogicExecutor extends LogicExecutor {
325
331
  * @return {*} {Promise<void>}
326
332
  */
327
333
  protected async doBatchAdd(
328
- appUILogic: IAppUIOpenDataLogic,
334
+ appUILogic: IAppUINewDataLogic,
329
335
  selections: IData[],
330
336
  context: IContext,
331
337
  newViewRef: IAppUILogicRefViewBase,
338
+ view: IViewController,
332
339
  ): Promise<void> {
333
340
  // 批添加新建选中数据后
334
341
  if (selections?.length) {
@@ -342,8 +349,8 @@ export class AppUILogicExecutor extends LogicExecutor {
342
349
  throw new RuntimeModelError(selfDe, '实体没有从关系集合!');
343
350
  }
344
351
 
345
- // 获取选择视图对应父实体在当前实体里的外键属性名称。
346
- let pickParentFieldName: string;
352
+ // *获取选择视图对应父实体在当前实体里的外键属性名称。
353
+ let pickParentFieldName: string = '';
347
354
  minorDERs?.forEach(item => {
348
355
  const majorDeName = calcDeCodeNameById(item.majorAppDataEntityId!);
349
356
  if (pickParentDeName === majorDeName) {
@@ -351,14 +358,21 @@ export class AppUILogicExecutor extends LogicExecutor {
351
358
  }
352
359
  });
353
360
 
354
- // 获取key为keymapping的特殊视图参数
355
- const openViewKeyParam = newViewRef.navigateParams?.find(navParam => {
356
- return navParam.key === 'keymapping';
357
- });
358
- let addData: IData[] = [];
359
- if (openViewKeyParam) {
360
- const keyValuePairs = openViewKeyParam.value!.split(';');
361
- const keyMapping: IData = {};
361
+ if (pickParentFieldName === undefined) {
362
+ throw new RuntimeError(
363
+ `没有找到${pickParentDeName}在当前实体的外键属性`,
364
+ );
365
+ }
366
+
367
+ // *转换的属性映射,默认映射一个外键属性,额外的通过当前视图的参数配置PROPERTYMAP
368
+ const keyMapping: IData = {
369
+ srfkey: pickParentFieldName,
370
+ };
371
+ const propertyMap = view.model.appViewParams?.find(
372
+ item => item.key!.toLowerCase() === 'PROPERTYMAP'.toLowerCase(),
373
+ );
374
+ if (propertyMap) {
375
+ const keyValuePairs = propertyMap.value!.split(',');
362
376
  // 遍历键值对数组并添加到 keyMapping 映射对象中
363
377
  for (const pair of keyValuePairs) {
364
378
  const [sourceKey, targetKey] = pair.split(':');
@@ -366,27 +380,23 @@ export class AppUILogicExecutor extends LogicExecutor {
366
380
  keyMapping[sourceKey] = targetKey;
367
381
  }
368
382
  }
369
- addData = selections.map(item => {
370
- const tempData: IData = {
371
- [pickParentFieldName]: item.srfkey,
372
- };
373
- // 遍历映射对象,将属性从 item 复制到 tempData
374
- for (const key in keyMapping) {
375
- if (Object.prototype.hasOwnProperty.call(keyMapping, key)) {
376
- const targetKey = keyMapping[key];
377
- if (Object.prototype.hasOwnProperty.call(item, key)) {
378
- tempData[targetKey] = item[key];
379
- }
380
- }
381
- }
382
- return tempData;
383
- });
384
- } else {
385
- addData = selections.map(item => ({
386
- [pickParentFieldName]: item.srfkey,
387
- }));
388
383
  }
389
384
 
385
+ ibiz.log.debug('批量新建转换映射属性', keyMapping);
386
+
387
+ // *转换属性
388
+ const addData: IData[] = selections.map(item => {
389
+ const tempData: IData = {};
390
+ // 遍历映射对象,将属性从 item 复制到 tempData
391
+ Object.keys(keyMapping).forEach(key => {
392
+ const targetKey = keyMapping[key];
393
+ tempData[targetKey] = item[key];
394
+ });
395
+ return tempData;
396
+ });
397
+
398
+ ibiz.log.debug('批量新建创建数据', addData);
399
+
390
400
  // 获取实体服务并调用创建接口
391
401
  const service = ibiz.hub.getApp(context.srfappid).deService;
392
402
  await service.exec(selfDe.id!, 'Create', context, addData);
@@ -220,10 +220,12 @@ export class MethodDto {
220
220
  const items: IData[] = datum[key];
221
221
  if (items) {
222
222
  const pKey = datum[this.entity.keyAppDEFieldId!];
223
- // 特殊处理,在子包内设置父对象标识
224
- items.forEach(item => {
225
- item[field.refPickupAppDEFieldId!] = pKey;
226
- });
223
+ if (field.refPickupAppDEFieldId) {
224
+ // 特殊处理,在子包内设置父对象标识
225
+ items.forEach(item => {
226
+ item[field.refPickupAppDEFieldId!] = pKey;
227
+ });
228
+ }
227
229
  await dto.sets(context, items);
228
230
  // 删除下边一行代码,DTO 的属性也不能直接删除。界面上表单类似重复器的地方会用到,保存时也需要由界面提供
229
231
  // delete datum[key];
@@ -463,13 +463,15 @@ export class DEActionMethod extends Method {
463
463
  const configs = uiDomain.getDERConfig(this.entity.id!);
464
464
  if (configs.length > 0) {
465
465
  configs.forEach(config => {
466
- const { majorDECodeName, pickupDEFName } = config;
467
- const majorLowerCodeName = majorDECodeName.toLowerCase();
468
- const pickupLowerDEFName = pickupDEFName.toLowerCase();
469
- const majorkey = context[majorLowerCodeName];
470
- // 父主键不能是自身,否则自关系的时候就改错了
471
- if (majorkey && majorkey !== data.srfkey) {
472
- data[pickupLowerDEFName] = majorkey;
466
+ if (config.pickupDEFName) {
467
+ const { majorDECodeName, pickupDEFName } = config;
468
+ const majorLowerCodeName = majorDECodeName.toLowerCase();
469
+ const pickupLowerDEFName = pickupDEFName.toLowerCase();
470
+ const majorkey = context[majorLowerCodeName];
471
+ // 父主键不能是自身,否则自关系的时候就改错了
472
+ if (majorkey && majorkey !== data.srfkey) {
473
+ data[pickupLowerDEFName] = majorkey;
474
+ }
473
475
  }
474
476
  });
475
477
  }
@@ -1,6 +1,7 @@
1
1
  /* eslint-disable no-constructor-return */
2
2
  import { IDETreeDataSetNode, IDETreeNodeDataItem } from '@ibiz/model-core';
3
3
  import { updateKeyDefine } from '@ibiz-template/core';
4
+ import { isNil } from 'ramda';
4
5
  import { IIcon, ITreeNodeData } from '../../../interface';
5
6
  import { calcDeCodeNameById } from '../../../model';
6
7
  import { ScriptFactory } from '../../../utils';
@@ -70,28 +71,46 @@ export class TreeDataSetNodeData extends TreeNodeData implements ITreeNodeData {
70
71
  this._leaf = fieldValueToBoolean(data[model.leafFlagAppDEFieldId]);
71
72
  }
72
73
 
73
- /** 数据项映射 */
74
+ /** 数据项和实体属性映射 */
74
75
  const dataItemKeyMap = new Map<string | symbol, string | symbol>();
75
76
  dataItemKeyMap.set('srfkey', 'srfkey');
76
77
  dataItemKeyMap.set('srfmajortext', 'srfmajortext');
77
78
 
78
- const dataItemDefaults: IData = {};
79
79
  model.detreeNodeDataItems?.forEach(dataItem => {
80
80
  const uiKey = dataItem.id!.toLowerCase();
81
81
  // 后台实体属性
82
82
  const deFieldKey = dataItem.appDEFieldId!.toLowerCase();
83
83
  dataItemKeyMap.set(uiKey, deFieldKey);
84
- if (dataItem.defaultValue) {
85
- dataItemDefaults[uiKey] = dataItem.defaultValue;
84
+
85
+ // *设置默认值
86
+ if (dataItem.defaultValue && isNil(data[deFieldKey])) {
87
+ data[deFieldKey] = dataItem.defaultValue;
88
+ }
89
+ });
90
+
91
+ /** 表格列和数据项的映射从而算出实体属性的映射 */
92
+ const nodeColumnKeyMap = new Map<string | symbol, string | symbol>();
93
+ model.detreeNodeColumns?.forEach(column => {
94
+ const columnKey = column.detreeColumnId!; // 不配树表格列不会有这个模型
95
+ const dataItemKey = column.dataItemName; // 配了就一定有数据项名称
96
+ if (!columnKey || !dataItemKey) {
97
+ ibiz.log.error('模型异常缺少detreeColumnId或者dataItemName', column);
98
+ } else {
99
+ nodeColumnKeyMap.set(columnKey, dataItemKeyMap.get(dataItemKey)!);
86
100
  }
87
101
  });
88
102
 
89
103
  return new Proxy<TreeDataSetNodeData>(this, {
90
104
  set(target, p, value): boolean {
91
- if (Object.prototype.hasOwnProperty.call(target._deData, p)) {
92
- target._deData[p] = value;
105
+ if (nodeColumnKeyMap.has(p)) {
106
+ // 通过树表格列标识设置
107
+ target._deData[nodeColumnKeyMap.get(p)!] = value;
93
108
  } else if (dataItemKeyMap.has(p)) {
109
+ // 通过树节点数据项标识设置
94
110
  target._deData[dataItemKeyMap.get(p)!] = value;
111
+ } else if (Object.prototype.hasOwnProperty.call(target._deData, p)) {
112
+ // 通过实体数据属性标识设置
113
+ target._deData[p] = value;
95
114
  } else {
96
115
  (target as IData)[p] = value;
97
116
  }
@@ -102,9 +121,15 @@ export class TreeDataSetNodeData extends TreeNodeData implements ITreeNodeData {
102
121
  if ((target as IData)[p] !== undefined) {
103
122
  return (target as IData)[p];
104
123
  }
124
+ // 通过树表格列标识获取
125
+ if (nodeColumnKeyMap.has(p)) {
126
+ return target._deData[nodeColumnKeyMap.get(p)!];
127
+ }
128
+ // 通过树节点数据项标识获取
105
129
  if (dataItemKeyMap.has(p)) {
106
- return target._deData[dataItemKeyMap.get(p)!] || dataItemDefaults[p];
130
+ return target._deData[dataItemKeyMap.get(p)!];
107
131
  }
132
+ // 通过实体数据属性标识获取
108
133
  if (target._deData[p] !== undefined) {
109
134
  return target._deData[p];
110
135
  }
@@ -214,51 +214,80 @@ export async function getDERedirectToView(
214
214
  }
215
215
  const entity = await ibiz.hub.getAppDataEntity(entityId, appView.appId);
216
216
  const rdTag = await calcDERdTag(entity, appView, params, curData);
217
- // !!!工作流临时补充特殊处理标识, 避免补充了工作流流程匹配不上, 再从默认tag匹配!!!
218
- const rdTagItems = rdTag.split(':');
219
- const wfRdTag =
220
- rdTagItems.length === 2 ? rdTag : rdTagItems.slice(0, 2).join(':');
221
- // 拼接当前重定向视图所在应用实体名称为前缀
222
- const deRdTag = `${entity.name!.toUpperCase()}:${rdTag}`;
223
- // 所有重定向引用视图
224
- const allRefViews = [];
225
- if (appView.redirectAppViewRefs) {
226
- allRefViews.push(...appView.redirectAppViewRefs);
227
- }
228
- if (appView.appViewRefs) {
229
- allRefViews.push(...appView.appViewRefs);
230
- }
231
- const refView = allRefViews.find(view => {
232
- const matchKey = view.name || view.id;
233
- // 特殊补充 wfRdTag 匹配,子流程应用特殊模式
234
- return matchKey === deRdTag || matchKey === rdTag || matchKey === wfRdTag;
235
- });
236
- if (refView) {
237
- const viewId = refView.refAppViewId;
238
- if (viewId) {
239
- return {
240
- type: 'view',
241
- viewId,
242
- context,
243
- params,
244
- opts: { ...opts, data: [curData] },
245
- };
217
+ let viewId = '';
218
+ // view://协议开头处理,值示例: view://{app}/{viewcodename}?srfwftag={wftag}
219
+ if (rdTag.startsWith('view://')) {
220
+ const url = new URL(rdTag);
221
+ if (url.searchParams.size > 0) {
222
+ url.searchParams.forEach((value, _key) => {
223
+ params[_key] = value;
224
+ });
225
+ }
226
+ const rdTagItems = url.pathname.replace('//', '').split('/');
227
+ // 当只有一个时,为视图标识。当有两个时,第二个是视图标识
228
+ const [appOrViewTag, viewTag] = rdTagItems;
229
+ if (viewTag) {
230
+ viewId = viewTag;
231
+ } else {
232
+ viewId = appOrViewTag;
246
233
  }
247
- throw new RuntimeModelError(refView, `未配置实际引用视图`);
248
234
  } else {
249
- ibiz.log.error(
250
- '重定向视图引用有:',
251
- allRefViews?.map(({ refAppViewId, name, realTitle }) => ({
252
- viewId: refAppViewId,
253
- tag: name,
254
- title: realTitle,
255
- })),
256
- );
257
- throw new RuntimeModelError(
258
- appView,
259
- `未找到重定向标识[${rdTag}]或[${deRdTag}]或工作流[${wfRdTag}]对应视图`,
260
- );
235
+ // !!!工作流临时补充特殊处理标识, 避免补充了工作流流程匹配不上, 再从默认tag匹配!!!
236
+ const rdTagItems = rdTag.split(':');
237
+ const wfRdTag =
238
+ rdTagItems.length === 2 ? rdTag : rdTagItems.slice(0, 2).join(':');
239
+ // 拼接当前重定向视图所在应用实体名称为前缀
240
+ const deRdTag = `${entity.name!.toUpperCase()}:${rdTag}`;
241
+ // 所有重定向引用视图
242
+ const allRefViews = [];
243
+ if (appView.redirectAppViewRefs) {
244
+ allRefViews.push(...appView.redirectAppViewRefs);
245
+ }
246
+ if (appView.appViewRefs) {
247
+ allRefViews.push(...appView.appViewRefs);
248
+ }
249
+ const refView = allRefViews.find(view => {
250
+ const matchKey = view.name || view.id;
251
+ // 特殊补充 wfRdTag 匹配,子流程应用特殊模式
252
+ return matchKey === deRdTag || matchKey === rdTag || matchKey === wfRdTag;
253
+ });
254
+ if (refView) {
255
+ viewId = refView.refAppViewId!;
256
+ if (viewId) {
257
+ return {
258
+ type: 'view',
259
+ viewId,
260
+ context,
261
+ params,
262
+ opts: { ...opts, data: [curData] },
263
+ };
264
+ }
265
+ throw new RuntimeModelError(refView, `未配置实际引用视图`);
266
+ } else {
267
+ ibiz.log.error(
268
+ '重定向视图引用有:',
269
+ allRefViews?.map(({ refAppViewId, name, realTitle }) => ({
270
+ viewId: refAppViewId,
271
+ tag: name,
272
+ title: realTitle,
273
+ })),
274
+ );
275
+ throw new RuntimeModelError(
276
+ appView,
277
+ `未找到重定向标识[${rdTag}]或[${deRdTag}]或工作流[${wfRdTag}]对应视图`,
278
+ );
279
+ }
280
+ }
281
+ if (viewId) {
282
+ return {
283
+ type: 'view',
284
+ viewId,
285
+ context,
286
+ params,
287
+ opts: { ...opts, data: [curData] },
288
+ };
261
289
  }
290
+ throw new RuntimeModelError(appView, `标识[${rdTag}]未匹配到实际引用视图`);
262
291
  }
263
292
 
264
293
  /**
@@ -335,8 +364,12 @@ export async function calcDERdTag(
335
364
  // 自定义重定向
336
365
  if (typeFieldId) {
337
366
  const { codeName } = findFieldById(entity, typeFieldId)!;
338
- const value = data[codeName!.toLowerCase()];
367
+ const value: string = data[codeName!.toLowerCase()];
339
368
  if (notNilEmpty(value)) {
369
+ // 如果是 view://协议开头直接返回,示例: view://{app}/{viewcodename}?srfwftag={wftag}
370
+ if (value.startsWith('view://')) {
371
+ return value;
372
+ }
340
373
  // 因为平台发布出来的标识全都是大写,所以这里也全部转大写
341
374
  return `${value.toUpperCase()}`;
342
375
  }