midway-fatcms 0.0.1-beta.60 → 0.0.1-beta.63
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/config/config.default.js +2 -2
- package/dist/controller/gateway/FileController.d.ts +2 -0
- package/dist/controller/gateway/FileController.js +15 -0
- package/dist/controller/gateway/PublicApiController.d.ts +4 -0
- package/dist/controller/gateway/PublicApiController.js +19 -2
- package/dist/libs/crud-pro/interfaces.d.ts +2 -0
- package/dist/libs/crud-pro/models/keys.d.ts +4 -0
- package/dist/libs/crud-pro/models/keys.js +5 -0
- package/dist/libs/crud-pro/services/CrudProExecuteFuncService.js +13 -0
- package/dist/libs/crud-pro/services/CrudProGenSqlCondition.js +15 -0
- package/dist/libs/crud-pro/utils/ModelUtils.js +6 -1
- package/dist/service/crudstd/CrudStdRelationService.js +20 -11
- package/dist/service/curd/CurdMixByAccountService.js +28 -7
- package/dist/service/curd/CurdMixUtils.d.ts +7 -1
- package/dist/service/curd/CurdMixUtils.js +59 -5
- package/package.json +1 -1
- package/src/config/config.default.ts +2 -2
- package/src/controller/gateway/FileController.ts +15 -1
- package/src/controller/gateway/PublicApiController.ts +17 -0
- package/src/libs/crud-pro/interfaces.ts +3 -0
- package/src/libs/crud-pro/models/keys.ts +6 -0
- package/src/libs/crud-pro/services/CrudProExecuteFuncService.ts +17 -0
- package/src/libs/crud-pro/services/CrudProGenSqlCondition.ts +22 -2
- package/src/libs/crud-pro/utils/ModelUtils.ts +6 -1
- package/src/service/crudstd/CrudStdRelationService.ts +25 -12
- package/src/service/curd/CurdMixByAccountService.ts +31 -8
- package/src/service/curd/CurdMixUtils.ts +74 -5
|
@@ -35,7 +35,7 @@ exports.default = (appInfo) => {
|
|
|
35
35
|
jsonLimit: '10mb',
|
|
36
36
|
textLimit: '10mb',
|
|
37
37
|
xmlLimit: '10mb',
|
|
38
|
-
ignore: ['/ns/gw/proxy/*', '/ns/gw/file/uploadFile', '/ns/api/manage/deploy/uploadAssets'], // 忽略代理路径的 body 解析
|
|
38
|
+
ignore: ['/ns/gw/proxy/*', '/ns/gw/file/uploadFile', '/ns/gw/file/uploadFilePublic', '/ns/api/manage/deploy/uploadAssets'], // 忽略代理路径的 body 解析
|
|
39
39
|
},
|
|
40
40
|
mysql2: {
|
|
41
41
|
fatcms: {
|
|
@@ -119,7 +119,7 @@ exports.default = (appInfo) => {
|
|
|
119
119
|
// base64: boolean,设置原始body是否是base64格式,默认为false,一般用于腾讯云的兼容
|
|
120
120
|
base64: false,
|
|
121
121
|
// 仅在匹配路径到 /api/upload 的时候去解析 body 中的文件信息
|
|
122
|
-
match: ['/ns/gw/file/uploadFile', '/ns/api/manage/deploy/uploadAssets'],
|
|
122
|
+
match: ['/ns/gw/file/uploadFile', '/ns/gw/file/uploadFilePublic', '/ns/api/manage/deploy/uploadAssets'],
|
|
123
123
|
},
|
|
124
124
|
view: {
|
|
125
125
|
rootDir: {
|
|
@@ -8,6 +8,7 @@ import { CommonResult } from '../../libs/utils/common-dto';
|
|
|
8
8
|
export declare class FileController extends BaseApiController {
|
|
9
9
|
protected ctx: Context;
|
|
10
10
|
protected fileCenterService: FileCenterService;
|
|
11
|
+
uploadFilePublic(files: any, fields: any, queryData: any): Promise<CommonResult>;
|
|
11
12
|
/**
|
|
12
13
|
* 上传普通文件。必须是登录用户才能上传。
|
|
13
14
|
* @param files
|
|
@@ -15,6 +16,7 @@ export declare class FileController extends BaseApiController {
|
|
|
15
16
|
* @param queryData
|
|
16
17
|
*/
|
|
17
18
|
uploadFile(files: any, fields: any, queryData: any): Promise<CommonResult>;
|
|
19
|
+
private uploadFilePrivate;
|
|
18
20
|
/**
|
|
19
21
|
* 文件下载或预览
|
|
20
22
|
* @param byMethod
|
|
@@ -29,6 +29,9 @@ function isTrue(obj) {
|
|
|
29
29
|
* 文件上传下载服务
|
|
30
30
|
*/
|
|
31
31
|
let FileController = class FileController extends BaseApiController_1.BaseApiController {
|
|
32
|
+
async uploadFilePublic(files, fields, queryData) {
|
|
33
|
+
return this.uploadFilePrivate(files, fields, queryData);
|
|
34
|
+
}
|
|
32
35
|
/**
|
|
33
36
|
* 上传普通文件。必须是登录用户才能上传。
|
|
34
37
|
* @param files
|
|
@@ -36,6 +39,9 @@ let FileController = class FileController extends BaseApiController_1.BaseApiCon
|
|
|
36
39
|
* @param queryData
|
|
37
40
|
*/
|
|
38
41
|
async uploadFile(files, fields, queryData) {
|
|
42
|
+
return this.uploadFilePrivate(files, fields, queryData);
|
|
43
|
+
}
|
|
44
|
+
async uploadFilePrivate(files, fields, queryData) {
|
|
39
45
|
const accessType = (queryData === null || queryData === void 0 ? void 0 : queryData.accessType) || (fields === null || fields === void 0 ? void 0 : fields.accessType) || bizmodels_1.AccessType.open;
|
|
40
46
|
const referer = this.ctx.req.headers.referer;
|
|
41
47
|
if (!Object.keys(bizmodels_1.AccessType).includes(accessType)) {
|
|
@@ -106,6 +112,15 @@ __decorate([
|
|
|
106
112
|
(0, core_1.Inject)(),
|
|
107
113
|
__metadata("design:type", FileCenterService_1.FileCenterService)
|
|
108
114
|
], FileController.prototype, "fileCenterService", void 0);
|
|
115
|
+
__decorate([
|
|
116
|
+
(0, core_1.Post)('/uploadFilePublic', { middleware: [(0, permission_middleware_1.checkLogin)()] }),
|
|
117
|
+
__param(0, (0, core_1.Files)()),
|
|
118
|
+
__param(1, (0, core_1.Fields)()),
|
|
119
|
+
__param(2, (0, core_1.Query)()),
|
|
120
|
+
__metadata("design:type", Function),
|
|
121
|
+
__metadata("design:paramtypes", [Object, Object, Object]),
|
|
122
|
+
__metadata("design:returntype", Promise)
|
|
123
|
+
], FileController.prototype, "uploadFilePublic", null);
|
|
109
124
|
__decorate([
|
|
110
125
|
(0, core_1.Post)('/uploadFile', { middleware: [(0, permission_middleware_1.checkPermission)([SystemPerm_1.SystemFuncCode.DocMangeWrite, SystemPerm_1.SystemFuncCode.FileMangeWrite, SystemPerm_1.SystemFuncCode.UserAccountMangeWrite])] }),
|
|
111
126
|
__param(0, (0, core_1.Files)()),
|
|
@@ -24,4 +24,8 @@ export declare class PublicApiController extends BaseApiController {
|
|
|
24
24
|
* 获取配置的枚举项信息: 都是无需鉴权的
|
|
25
25
|
*/
|
|
26
26
|
getEnumInfo(): Promise<CommonResult>;
|
|
27
|
+
/**
|
|
28
|
+
* 获取应用配置信息
|
|
29
|
+
*/
|
|
30
|
+
getSysAppInfoByAppCode(): Promise<import("../../libs/crud-pro/models/ExecuteContext").ExecuteContext>;
|
|
27
31
|
}
|
|
@@ -12,6 +12,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
12
12
|
exports.PublicApiController = void 0;
|
|
13
13
|
const core_1 = require("@midwayjs/core");
|
|
14
14
|
const _ = require("lodash");
|
|
15
|
+
const keys_1 = require("../../libs/crud-pro/models/keys");
|
|
15
16
|
const BaseApiController_1 = require("../base/BaseApiController");
|
|
16
17
|
const SystemTables_1 = require("../../models/SystemTables");
|
|
17
18
|
const EnumInfoService_1 = require("../../service/EnumInfoService");
|
|
@@ -19,7 +20,7 @@ const common_dto_1 = require("../../libs/utils/common-dto");
|
|
|
19
20
|
const functions_1 = require("../../libs/utils/functions");
|
|
20
21
|
const WorkbenchService_1 = require("../../service/WorkbenchService");
|
|
21
22
|
const SystemPerm_1 = require("../../models/SystemPerm");
|
|
22
|
-
const
|
|
23
|
+
const keys_2 = require("../../libs/crud-pro/models/keys");
|
|
23
24
|
/**
|
|
24
25
|
* 公开的API,无需鉴权,所有人可以直接访问
|
|
25
26
|
*/
|
|
@@ -71,7 +72,7 @@ let PublicApiController = class PublicApiController extends BaseApiController_1.
|
|
|
71
72
|
// 特殊的devops菜单
|
|
72
73
|
map['devops'] = {
|
|
73
74
|
menu_list: [],
|
|
74
|
-
hasPermission: this.ctx.userSession.isAuthPass(
|
|
75
|
+
hasPermission: this.ctx.userSession.isAuthPass(keys_2.KeysOfAuthType.byRoleCode, [SystemPerm_1.SystemRoleCode.DevOpsWriter, SystemPerm_1.SystemRoleCode.DevOpsViewer, SystemPerm_1.SystemRoleCode.SuperAdmin]),
|
|
75
76
|
};
|
|
76
77
|
return common_dto_1.CommonResult.successRes(map);
|
|
77
78
|
}
|
|
@@ -119,6 +120,16 @@ let PublicApiController = class PublicApiController extends BaseApiController_1.
|
|
|
119
120
|
const enumInfos = await this.enumInfoService.queryEnumInfo(codeList, refreshCache);
|
|
120
121
|
return common_dto_1.CommonResult.successRes(enumInfos);
|
|
121
122
|
}
|
|
123
|
+
/**
|
|
124
|
+
* 获取应用配置信息
|
|
125
|
+
*/
|
|
126
|
+
async getSysAppInfoByAppCode() {
|
|
127
|
+
return this.executeSysSimpleSQL('sys_app', keys_1.KeysOfSimpleSQL.SIMPLE_QUERY_ONE, {
|
|
128
|
+
validateCfg: {
|
|
129
|
+
'condition.app_code': [keys_1.KeysOfValidators.REQUIRED, keys_1.KeysOfValidators.STRING],
|
|
130
|
+
},
|
|
131
|
+
});
|
|
132
|
+
}
|
|
122
133
|
};
|
|
123
134
|
__decorate([
|
|
124
135
|
(0, core_1.Inject)(),
|
|
@@ -156,6 +167,12 @@ __decorate([
|
|
|
156
167
|
__metadata("design:paramtypes", []),
|
|
157
168
|
__metadata("design:returntype", Promise)
|
|
158
169
|
], PublicApiController.prototype, "getEnumInfo", null);
|
|
170
|
+
__decorate([
|
|
171
|
+
(0, core_1.Post)('/getSysAppInfoByAppCode'),
|
|
172
|
+
__metadata("design:type", Function),
|
|
173
|
+
__metadata("design:paramtypes", []),
|
|
174
|
+
__metadata("design:returntype", Promise)
|
|
175
|
+
], PublicApiController.prototype, "getSysAppInfoByAppCode", null);
|
|
159
176
|
PublicApiController = __decorate([
|
|
160
177
|
(0, core_1.Controller)('/ns/gw/api/publicApi')
|
|
161
178
|
], PublicApiController);
|
|
@@ -105,6 +105,8 @@ export interface IFuncCfgModel extends Record<any, any> {
|
|
|
105
105
|
contextAsString?: string;
|
|
106
106
|
contextAsNumber?: string;
|
|
107
107
|
contextAsBool?: string;
|
|
108
|
+
executeExpressReturnObject?: string;
|
|
109
|
+
executeExpressReturnString?: string;
|
|
108
110
|
message?: string;
|
|
109
111
|
}
|
|
110
112
|
export interface ISqlCfgModel extends IBaseCfgModel {
|
|
@@ -101,6 +101,10 @@ export declare const KeysOfConditions: {
|
|
|
101
101
|
$NOT_LIKE_INCLUDE: string;
|
|
102
102
|
$MATCH: string;
|
|
103
103
|
$MATCH_BOOL: string;
|
|
104
|
+
/**
|
|
105
|
+
* SELECT * FROM tms_biz.表 WHERE JSON_CONTAINS(`related_user1`, JSON_ARRAY('2512274'), '$');
|
|
106
|
+
*/
|
|
107
|
+
$JSON_ARRAY_CONTAINS: string;
|
|
104
108
|
COMPARE_KEYS: Set<string>;
|
|
105
109
|
ALL_KEYS: Set<string>;
|
|
106
110
|
};
|
|
@@ -115,6 +115,10 @@ exports.KeysOfConditions = {
|
|
|
115
115
|
$NOT_LIKE_INCLUDE: '$notLikeInclude',
|
|
116
116
|
$MATCH: '$match',
|
|
117
117
|
$MATCH_BOOL: '$matchBool',
|
|
118
|
+
/**
|
|
119
|
+
* SELECT * FROM tms_biz.表 WHERE JSON_CONTAINS(`related_user1`, JSON_ARRAY('2512274'), '$');
|
|
120
|
+
*/
|
|
121
|
+
$JSON_ARRAY_CONTAINS: '$jsonArrayContains',
|
|
118
122
|
COMPARE_KEYS: new Set([]),
|
|
119
123
|
ALL_KEYS: new Set([]),
|
|
120
124
|
};
|
|
@@ -137,6 +141,7 @@ function initKeysOfConditions() {
|
|
|
137
141
|
addIgnoreCase(exports.KeysOfConditions.COMPARE_KEYS, exports.KeysOfConditions.$LIKE_INCLUDE);
|
|
138
142
|
addIgnoreCase(exports.KeysOfConditions.COMPARE_KEYS, exports.KeysOfConditions.$NOT_LIKE);
|
|
139
143
|
addIgnoreCase(exports.KeysOfConditions.COMPARE_KEYS, exports.KeysOfConditions.$NOT_LIKE_INCLUDE);
|
|
144
|
+
addIgnoreCase(exports.KeysOfConditions.COMPARE_KEYS, exports.KeysOfConditions.$JSON_ARRAY_CONTAINS);
|
|
140
145
|
addIgnoreCase(exports.KeysOfConditions.COMPARE_KEYS, exports.KeysOfConditions.$MATCH);
|
|
141
146
|
addIgnoreCase(exports.KeysOfConditions.COMPARE_KEYS, exports.KeysOfConditions.$MATCH_BOOL);
|
|
142
147
|
addIgnoreCase(exports.KeysOfConditions.COMPARE_KEYS, exports.KeysOfConditions.$RANGE);
|
|
@@ -5,6 +5,8 @@ const CrudProServiceBase_1 = require("./CrudProServiceBase");
|
|
|
5
5
|
const TypeUtils_1 = require("../utils/TypeUtils");
|
|
6
6
|
const MixinUtils_1 = require("../utils/MixinUtils");
|
|
7
7
|
const _ = require("lodash");
|
|
8
|
+
const moment = require("moment");
|
|
9
|
+
const ejs = require("ejs");
|
|
8
10
|
const exceptions_1 = require("../exceptions");
|
|
9
11
|
const keys_1 = require("../models/keys");
|
|
10
12
|
const { isNil, isNumeric } = TypeUtils_1.TypeUtils;
|
|
@@ -20,6 +22,17 @@ class CrudProExecuteFuncService extends CrudProServiceBase_1.CrudProServiceBase
|
|
|
20
22
|
if (funCfg.___PLAIN_OBJECT___ === true) {
|
|
21
23
|
return funCfg;
|
|
22
24
|
}
|
|
25
|
+
const funcContextAny = funcContext;
|
|
26
|
+
funcContextAny.moment = moment;
|
|
27
|
+
funcContextAny._ = _;
|
|
28
|
+
if (isNotNil(funCfg.executeExpressReturnString)) {
|
|
29
|
+
const expressResult = ejs.render(funCfg.executeExpressReturnString, funcContextAny);
|
|
30
|
+
return expressResult;
|
|
31
|
+
}
|
|
32
|
+
if (isNotNil(funCfg.executeExpressReturnObject)) {
|
|
33
|
+
const expressResult = ejs.render(funCfg.executeExpressReturnObject, funcContextAny);
|
|
34
|
+
return JSON.parse(expressResult);
|
|
35
|
+
}
|
|
23
36
|
if (isNotNil(funCfg.const)) {
|
|
24
37
|
return funCfg.const;
|
|
25
38
|
}
|
|
@@ -208,6 +208,16 @@ class CrudProGenSqlCondition {
|
|
|
208
208
|
tmpSql = `${toSqlColumnName(key)} like concat('%', ?::text, '%')`; // like包含
|
|
209
209
|
}
|
|
210
210
|
}
|
|
211
|
+
else if (equalsIgnoreCase(keys_1.KeysOfConditions.$JSON_ARRAY_CONTAINS, compare)) {
|
|
212
|
+
if (this.sqlCfg.sqlDbType === keys_1.SqlDbType.mysql) {
|
|
213
|
+
tmpArgList.push(value0);
|
|
214
|
+
tmpSql = `JSON_CONTAINS( ${toSqlColumnName(key)} , JSON_ARRAY(?), '$')`; // MYSQL JSON_CONTAINS包含
|
|
215
|
+
}
|
|
216
|
+
if (this.sqlCfg.sqlDbType === keys_1.SqlDbType.postgres) {
|
|
217
|
+
tmpArgList.push(value0);
|
|
218
|
+
tmpSql = `${toSqlColumnName(key)} @> ('["' || ? || '"]')::jsonb`; // POSTGRES JSON_CONTAINS包含
|
|
219
|
+
}
|
|
220
|
+
}
|
|
211
221
|
else if (equalsIgnoreCase(keys_1.KeysOfConditions.$NOT_LIKE_INCLUDE, compare)) {
|
|
212
222
|
tmpArgList.push(value0);
|
|
213
223
|
tmpSql = `${toSqlColumnName(key)} COLLATE UTF8MB4_GENERAL_CI not like concat('%',?, '%')`; // like不包含
|
|
@@ -308,6 +318,11 @@ class CrudProGenSqlCondition {
|
|
|
308
318
|
throwCommonException(keys_1.KeysOfConditions.$NOT_LIKE_INCLUDE, '字符串');
|
|
309
319
|
}
|
|
310
320
|
}
|
|
321
|
+
else if (equalsIgnoreCase(keys_1.KeysOfConditions.$JSON_ARRAY_CONTAINS, compare)) {
|
|
322
|
+
if (!isBasicType(value0)) {
|
|
323
|
+
throwCommonException(keys_1.KeysOfConditions.$JSON_ARRAY_CONTAINS, '字符串或数字');
|
|
324
|
+
}
|
|
325
|
+
}
|
|
311
326
|
else if (equalsIgnoreCase(keys_1.KeysOfConditions.$MATCH, compare)) {
|
|
312
327
|
if (!isBasicType(value0)) {
|
|
313
328
|
throwCommonException(keys_1.KeysOfConditions.$MATCH, '字符串');
|
|
@@ -36,7 +36,12 @@ const ModelUtils = {
|
|
|
36
36
|
return defaultConfigs_1.DEFAULT_MAX_LIMIT;
|
|
37
37
|
},
|
|
38
38
|
checkFuncCfgValid(cfgModel) {
|
|
39
|
-
const arr = [
|
|
39
|
+
const arr = [
|
|
40
|
+
cfgModel.functionName, cfgModel.const, cfgModel.constString, cfgModel.constNumber,
|
|
41
|
+
cfgModel.constBool, cfgModel.context,
|
|
42
|
+
cfgModel.contextAsString, cfgModel.contextAsNumber, cfgModel.contextAsBool,
|
|
43
|
+
cfgModel.executeExpressReturnObject, cfgModel.executeExpressReturnString
|
|
44
|
+
];
|
|
40
45
|
for (let i = 0; i < arr.length; i++) {
|
|
41
46
|
const arrElement = arr[i];
|
|
42
47
|
if (typeof arrElement !== 'undefined') {
|
|
@@ -65,6 +65,16 @@ class ColumnsRelationMaker {
|
|
|
65
65
|
}
|
|
66
66
|
}
|
|
67
67
|
}
|
|
68
|
+
function addMarkerColumnRelation(maker, dataIndex, componentName) {
|
|
69
|
+
// 关联用户信息
|
|
70
|
+
if (componentName === CrudStdConstant_1.tableColumnRenders.RenderUserInfo) {
|
|
71
|
+
maker.addColumnRelationByAccount(dataIndex);
|
|
72
|
+
}
|
|
73
|
+
// 关联枚举文案/状态标签颜色
|
|
74
|
+
if (componentName === CrudStdConstant_1.tableColumnRenders.RenderDictEnumText || componentName === CrudStdConstant_1.tableColumnRenders.RenderDictEnumStatus) {
|
|
75
|
+
maker.addColumnRelationByDictEnumStatus(dataIndex);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
68
78
|
let CrudStdRelationService = class CrudStdRelationService extends BaseService_1.BaseService {
|
|
69
79
|
async addCfgModelColumnsRelation(cfgModel, appInfo) {
|
|
70
80
|
var _a;
|
|
@@ -77,22 +87,21 @@ let CrudStdRelationService = class CrudStdRelationService extends BaseService_1.
|
|
|
77
87
|
const tableColumn = tableColumns[i];
|
|
78
88
|
const dataIndex = _.get(tableColumn, 'dataIndex');
|
|
79
89
|
const componentName = _.get(tableColumn, 'component.componentName');
|
|
80
|
-
|
|
81
|
-
if (componentName === CrudStdConstant_1.tableColumnRenders.RenderUserInfo) {
|
|
82
|
-
maker.addColumnRelationByAccount(dataIndex);
|
|
83
|
-
}
|
|
84
|
-
// 关联枚举文案/状态标签颜色
|
|
85
|
-
if (componentName === CrudStdConstant_1.tableColumnRenders.RenderDictEnumText || componentName === CrudStdConstant_1.tableColumnRenders.RenderDictEnumStatus) {
|
|
86
|
-
maker.addColumnRelationByDictEnumStatus(dataIndex);
|
|
87
|
-
}
|
|
90
|
+
addMarkerColumnRelation(maker, dataIndex, componentName);
|
|
88
91
|
// 子属性的配置
|
|
89
92
|
const balloonTipFields = _.get(tableColumn, 'component.props.balloonTipFields');
|
|
90
93
|
if (Array.isArray(balloonTipFields) && balloonTipFields.length > 0) {
|
|
91
94
|
for (let j = 0; j < balloonTipFields.length; j++) {
|
|
92
95
|
const { component, name } = balloonTipFields[j] || {};
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
+
addMarkerColumnRelation(maker, name, component);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
// 子属性的配置
|
|
100
|
+
const linkDataConfig = _.get(tableColumn, 'component.props.linkDataConfig');
|
|
101
|
+
if (Array.isArray(linkDataConfig) && linkDataConfig.length > 0) {
|
|
102
|
+
for (let j = 0; j < linkDataConfig.length; j++) {
|
|
103
|
+
const { component, name } = linkDataConfig[j] || {};
|
|
104
|
+
addMarkerColumnRelation(maker, name, component);
|
|
96
105
|
}
|
|
97
106
|
}
|
|
98
107
|
}
|
|
@@ -20,21 +20,29 @@ const MixinUtils_1 = require("../../libs/crud-pro/utils/MixinUtils");
|
|
|
20
20
|
const global_config_1 = require("../../libs/global-config/global-config");
|
|
21
21
|
const dictMixUtils = new CurdMixUtils_1.CrudMixUtils(CurdMixUtils_1.RelatedType.accountBasic);
|
|
22
22
|
const TMP_CTX_KEY = _.uniqueId('CurdMixByAccountService');
|
|
23
|
+
const TMP_CTX_KEY2 = _.uniqueId('CurdMixByAccountService2');
|
|
23
24
|
let CurdMixByAccountService = class CurdMixByAccountService {
|
|
24
25
|
async handleExecuteContextPrepare(executeContext) {
|
|
25
|
-
const { SystemDbName, SystemDbType
|
|
26
|
+
const { SystemDbName, SystemDbType } = global_config_1.GLOBAL_STATIC_CONFIG.getConfig();
|
|
26
27
|
const relations = dictMixUtils.pickColumnRelations(executeContext);
|
|
27
28
|
if (!relations || relations.length === 0) {
|
|
28
29
|
return;
|
|
29
30
|
}
|
|
31
|
+
const isArrayModeMap = new Map();
|
|
30
32
|
const accountIds = new Set();
|
|
31
33
|
dictMixUtils.forEachRowAndColumnsRelation(executeContext, (row, columnRelation) => {
|
|
32
34
|
const { sourceColumn } = columnRelation;
|
|
33
35
|
if (sourceColumn) {
|
|
34
36
|
const accountId = _.get(row, sourceColumn);
|
|
35
37
|
if (accountId) {
|
|
36
|
-
const fatcmsUserAccountId =
|
|
37
|
-
|
|
38
|
+
const { isArray, fatcmsUserAccountIdList, fatcmsUserAccountId } = (0, CurdMixUtils_1.toFatcmsUserAccountIdList)(accountId);
|
|
39
|
+
if (isArray) {
|
|
40
|
+
isArrayModeMap.set(sourceColumn, true);
|
|
41
|
+
fatcmsUserAccountIdList.forEach(item => accountIds.add(item));
|
|
42
|
+
}
|
|
43
|
+
else if (fatcmsUserAccountId) {
|
|
44
|
+
accountIds.add(fatcmsUserAccountId);
|
|
45
|
+
}
|
|
38
46
|
}
|
|
39
47
|
}
|
|
40
48
|
});
|
|
@@ -59,9 +67,11 @@ let CurdMixByAccountService = class CurdMixByAccountService {
|
|
|
59
67
|
const res = await this.curdProService.executeCrudByCfg(reqJson, cfgModel);
|
|
60
68
|
const userInfos = res.getResRows();
|
|
61
69
|
executeContext[TMP_CTX_KEY] = MixinUtils_1.MixinUtils.toNewMap(userInfos, (obj) => obj.account_id);
|
|
70
|
+
executeContext[TMP_CTX_KEY2] = isArrayModeMap;
|
|
62
71
|
}
|
|
63
72
|
async handleExecuteContext(executeContext) {
|
|
64
73
|
const userInfoMap = executeContext[TMP_CTX_KEY];
|
|
74
|
+
const isArrayModeMap = executeContext[TMP_CTX_KEY2];
|
|
65
75
|
if (!userInfoMap || userInfoMap.size === 0) {
|
|
66
76
|
return;
|
|
67
77
|
}
|
|
@@ -69,10 +79,21 @@ let CurdMixByAccountService = class CurdMixByAccountService {
|
|
|
69
79
|
const sourceColumn = columnRelation.sourceColumn;
|
|
70
80
|
const targetColumns = columnRelation.targetColumns;
|
|
71
81
|
if (!Array.isArray(targetColumns) || targetColumns.length === 0) {
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
82
|
+
const isArrayMode = isArrayModeMap.get(sourceColumn) || false;
|
|
83
|
+
if (isArrayMode === true) {
|
|
84
|
+
columnRelation.targetColumns = [
|
|
85
|
+
{ from: 'nick_name', to: `${sourceColumn}_array_info[$ARRAY_INDEX].nick_name` },
|
|
86
|
+
{ from: 'avatar', to: `${sourceColumn}_array_info[$ARRAY_INDEX].avatar` },
|
|
87
|
+
{ from: 'account_id', to: `${sourceColumn}_array_info[$ARRAY_INDEX].account_id` },
|
|
88
|
+
];
|
|
89
|
+
}
|
|
90
|
+
else {
|
|
91
|
+
columnRelation.targetColumns = [
|
|
92
|
+
{ from: 'nick_name', to: `${sourceColumn}_user.nick_name` },
|
|
93
|
+
{ from: 'avatar', to: `${sourceColumn}_user.avatar` },
|
|
94
|
+
{ from: 'account_id', to: `${sourceColumn}_user.account_id` },
|
|
95
|
+
];
|
|
96
|
+
}
|
|
76
97
|
}
|
|
77
98
|
dictMixUtils.copyUserInfoToRowNoRelatedCode(row, userInfoMap, columnRelation);
|
|
78
99
|
});
|
|
@@ -9,6 +9,12 @@ declare enum RelatedType {
|
|
|
9
9
|
workbenchBasic = "workbenchBasic"
|
|
10
10
|
}
|
|
11
11
|
declare type FuncRowColumnRelation = (row: any, columnRelation: ColumnRelation) => void;
|
|
12
|
+
interface IFatcmsUserAccountIdList {
|
|
13
|
+
isArray: boolean;
|
|
14
|
+
fatcmsUserAccountId?: string;
|
|
15
|
+
fatcmsUserAccountIdList?: string[];
|
|
16
|
+
}
|
|
17
|
+
declare function toFatcmsUserAccountIdList(accountId: any): IFatcmsUserAccountIdList;
|
|
12
18
|
declare class CrudMixUtils {
|
|
13
19
|
private readonly relatedType;
|
|
14
20
|
constructor(relatedType: RelatedType);
|
|
@@ -48,4 +54,4 @@ declare class CrudMixUtils {
|
|
|
48
54
|
*/
|
|
49
55
|
copyUserInfoToRowNoRelatedCode(row: any, map: Map<string, any>, columnRelation: ColumnRelation): void;
|
|
50
56
|
}
|
|
51
|
-
export { CrudMixUtils, RelatedType, FuncRowColumnRelation };
|
|
57
|
+
export { CrudMixUtils, RelatedType, FuncRowColumnRelation, toFatcmsUserAccountIdList };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.RelatedType = exports.CrudMixUtils = void 0;
|
|
3
|
+
exports.toFatcmsUserAccountIdList = exports.RelatedType = exports.CrudMixUtils = void 0;
|
|
4
4
|
const keys_1 = require("../../libs/crud-pro/models/keys");
|
|
5
5
|
const MixinUtils_1 = require("../../libs/crud-pro/utils/MixinUtils");
|
|
6
6
|
const global_config_1 = require("../../libs/global-config/global-config");
|
|
@@ -94,6 +94,59 @@ function copyByArraySourceValue(row, sourceValue, targetColumns, getValue) {
|
|
|
94
94
|
}
|
|
95
95
|
return resultObj.isSetArray;
|
|
96
96
|
}
|
|
97
|
+
function toFatcmsUserAccountIdList(accountId) {
|
|
98
|
+
const { toFatcmsUserAccountId } = global_config_1.GLOBAL_STATIC_CONFIG.getConfig();
|
|
99
|
+
if (!accountId) {
|
|
100
|
+
return {
|
|
101
|
+
isArray: false,
|
|
102
|
+
fatcmsUserAccountId: null
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
// 数字形式
|
|
106
|
+
if (typeof accountId === 'number') {
|
|
107
|
+
return {
|
|
108
|
+
isArray: false,
|
|
109
|
+
fatcmsUserAccountId: toFatcmsUserAccountId("" + accountId),
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
if (typeof accountId === 'string') {
|
|
113
|
+
const json = (0, functions_1.parseJsonObject)(accountId);
|
|
114
|
+
// 数组形式
|
|
115
|
+
if (json && Array.isArray(json) && json.length > 0) {
|
|
116
|
+
return {
|
|
117
|
+
isArray: true,
|
|
118
|
+
fatcmsUserAccountIdList: json.map(item => {
|
|
119
|
+
if (typeof item === 'string' || typeof item === 'number') {
|
|
120
|
+
return toFatcmsUserAccountId("" + item);
|
|
121
|
+
}
|
|
122
|
+
return null;
|
|
123
|
+
}).filter(item => item !== null),
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
// 单值形式
|
|
127
|
+
return {
|
|
128
|
+
isArray: false,
|
|
129
|
+
fatcmsUserAccountId: toFatcmsUserAccountId(accountId),
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
// 数组形式
|
|
133
|
+
if (Array.isArray(accountId)) {
|
|
134
|
+
return {
|
|
135
|
+
isArray: true,
|
|
136
|
+
fatcmsUserAccountIdList: accountId.map(item => {
|
|
137
|
+
if (typeof item === 'string' || typeof item === 'number') {
|
|
138
|
+
return toFatcmsUserAccountId("" + item);
|
|
139
|
+
}
|
|
140
|
+
return null;
|
|
141
|
+
}).filter(item => item !== null),
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
return {
|
|
145
|
+
isArray: false,
|
|
146
|
+
fatcmsUserAccountId: null
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
exports.toFatcmsUserAccountIdList = toFatcmsUserAccountIdList;
|
|
97
150
|
class CrudMixUtils {
|
|
98
151
|
constructor(relatedType) {
|
|
99
152
|
this.relatedType = relatedType;
|
|
@@ -257,8 +310,7 @@ class CrudMixUtils {
|
|
|
257
310
|
if (!accountId) {
|
|
258
311
|
return;
|
|
259
312
|
}
|
|
260
|
-
const {
|
|
261
|
-
const fatcmsUserAccountId = toFatcmsUserAccountId(accountId);
|
|
313
|
+
const { isArray, fatcmsUserAccountIdList, fatcmsUserAccountId } = toFatcmsUserAccountIdList(accountId);
|
|
262
314
|
const getValue = (code) => {
|
|
263
315
|
if (!map) {
|
|
264
316
|
return null;
|
|
@@ -268,8 +320,10 @@ class CrudMixUtils {
|
|
|
268
320
|
}
|
|
269
321
|
return map[code];
|
|
270
322
|
};
|
|
271
|
-
|
|
272
|
-
|
|
323
|
+
if (isArray) {
|
|
324
|
+
copyByArraySourceValue(row, fatcmsUserAccountIdList, targetColumns, getValue);
|
|
325
|
+
}
|
|
326
|
+
else if (fatcmsUserAccountId) {
|
|
273
327
|
copyBySingleSourceValue(row, fatcmsUserAccountId, targetColumns, getValue);
|
|
274
328
|
}
|
|
275
329
|
}
|
package/package.json
CHANGED
|
@@ -41,7 +41,7 @@ export default (appInfo: any) => {
|
|
|
41
41
|
jsonLimit: '10mb',
|
|
42
42
|
textLimit: '10mb',
|
|
43
43
|
xmlLimit: '10mb',
|
|
44
|
-
ignore: ['/ns/gw/proxy/*', '/ns/gw/file/uploadFile', '/ns/api/manage/deploy/uploadAssets'], // 忽略代理路径的 body 解析
|
|
44
|
+
ignore: ['/ns/gw/proxy/*', '/ns/gw/file/uploadFile', '/ns/gw/file/uploadFilePublic', '/ns/api/manage/deploy/uploadAssets'], // 忽略代理路径的 body 解析
|
|
45
45
|
},
|
|
46
46
|
|
|
47
47
|
mysql2: {
|
|
@@ -130,7 +130,7 @@ export default (appInfo: any) => {
|
|
|
130
130
|
// base64: boolean,设置原始body是否是base64格式,默认为false,一般用于腾讯云的兼容
|
|
131
131
|
base64: false,
|
|
132
132
|
// 仅在匹配路径到 /api/upload 的时候去解析 body 中的文件信息
|
|
133
|
-
match: ['/ns/gw/file/uploadFile', '/ns/api/manage/deploy/uploadAssets'],
|
|
133
|
+
match: ['/ns/gw/file/uploadFile', '/ns/gw/file/uploadFilePublic', '/ns/api/manage/deploy/uploadAssets'],
|
|
134
134
|
},
|
|
135
135
|
|
|
136
136
|
view: {
|
|
@@ -5,7 +5,7 @@ import { BaseApiController } from '../base/BaseApiController';
|
|
|
5
5
|
import { BizException } from '@/models/devops';
|
|
6
6
|
import { AccessType, FILE_GET_TYPES } from '@/models/bizmodels';
|
|
7
7
|
import { FileCenterService, PATH_PREFIX, toDownloadPaths, isImageFile } from '@/service/FileCenterService';
|
|
8
|
-
import { checkPermission } from '@/middleware/permission.middleware';
|
|
8
|
+
import { checkLogin, checkPermission } from '@/middleware/permission.middleware';
|
|
9
9
|
import { CommonResult } from '@/libs/utils/common-dto';
|
|
10
10
|
import { SystemFuncCode } from '@/models/SystemPerm';
|
|
11
11
|
|
|
@@ -24,6 +24,13 @@ export class FileController extends BaseApiController {
|
|
|
24
24
|
@Inject()
|
|
25
25
|
protected fileCenterService: FileCenterService;
|
|
26
26
|
|
|
27
|
+
@Post('/uploadFilePublic', { middleware: [checkLogin()] })
|
|
28
|
+
async uploadFilePublic(@Files() files, @Fields() fields, @Query() queryData): Promise<CommonResult> {
|
|
29
|
+
return this.uploadFilePrivate(files, fields, queryData);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
|
|
27
34
|
/**
|
|
28
35
|
* 上传普通文件。必须是登录用户才能上传。
|
|
29
36
|
* @param files
|
|
@@ -32,6 +39,13 @@ export class FileController extends BaseApiController {
|
|
|
32
39
|
*/
|
|
33
40
|
@Post('/uploadFile', { middleware: [checkPermission([SystemFuncCode.DocMangeWrite, SystemFuncCode.FileMangeWrite, SystemFuncCode.UserAccountMangeWrite])] })
|
|
34
41
|
async uploadFile(@Files() files, @Fields() fields, @Query() queryData): Promise<CommonResult> {
|
|
42
|
+
return this.uploadFilePrivate(files, fields, queryData);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
private async uploadFilePrivate(files: any, fields: any, queryData: any) {
|
|
35
49
|
const accessType = queryData?.accessType || fields?.accessType || AccessType.open;
|
|
36
50
|
const referer = this.ctx.req.headers.referer;
|
|
37
51
|
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Controller, Get, Inject, Post } from '@midwayjs/core';
|
|
2
2
|
import { Context } from '@midwayjs/koa';
|
|
3
3
|
import * as _ from 'lodash';
|
|
4
|
+
import { KeysOfSimpleSQL, KeysOfValidators } from '@/libs/crud-pro/models/keys';
|
|
4
5
|
import { BaseApiController } from '../base/BaseApiController';
|
|
5
6
|
import { SystemTables } from '@/models/SystemTables';
|
|
6
7
|
import { EnumInfoService } from '@/service/EnumInfoService';
|
|
@@ -137,4 +138,20 @@ export class PublicApiController extends BaseApiController {
|
|
|
137
138
|
const enumInfos = await this.enumInfoService.queryEnumInfo(codeList, refreshCache);
|
|
138
139
|
return CommonResult.successRes(enumInfos);
|
|
139
140
|
}
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* 获取应用配置信息
|
|
146
|
+
*/
|
|
147
|
+
@Post('/getSysAppInfoByAppCode')
|
|
148
|
+
async getSysAppInfoByAppCode() {
|
|
149
|
+
return this.executeSysSimpleSQL('sys_app', KeysOfSimpleSQL.SIMPLE_QUERY_ONE, {
|
|
150
|
+
validateCfg: {
|
|
151
|
+
'condition.app_code': [KeysOfValidators.REQUIRED, KeysOfValidators.STRING],
|
|
152
|
+
},
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
|
|
140
157
|
}
|
|
@@ -125,6 +125,9 @@ export interface IFuncCfgModel extends Record<any, any> {
|
|
|
125
125
|
contextAsNumber?: string; // 从context中取值
|
|
126
126
|
contextAsBool?: string; // 从context中取值
|
|
127
127
|
|
|
128
|
+
executeExpressReturnObject?: string; // 执行表达式,返回对象。可以包含context中的变量。
|
|
129
|
+
executeExpressReturnString?: string; // 执行表达式,返回字符串。可以包含context中的变量。
|
|
130
|
+
|
|
128
131
|
message?: string; // 在校验阶段有用,其他阶段没有用
|
|
129
132
|
}
|
|
130
133
|
|
|
@@ -121,6 +121,11 @@ export const KeysOfConditions = {
|
|
|
121
121
|
$MATCH: '$match', // 全文索引 {age:1, name:{"$match":"张"} }
|
|
122
122
|
$MATCH_BOOL: '$matchBool', // 全文索引 {age:1, name:{"$matchBool":"张"} }
|
|
123
123
|
|
|
124
|
+
/**
|
|
125
|
+
* SELECT * FROM tms_biz.表 WHERE JSON_CONTAINS(`related_user1`, JSON_ARRAY('2512274'), '$');
|
|
126
|
+
*/
|
|
127
|
+
$JSON_ARRAY_CONTAINS: '$jsonArrayContains', // 全文索引 { related_user1:{"$jsonArrayContains":"2512274"} }
|
|
128
|
+
|
|
124
129
|
COMPARE_KEYS: new Set<string>([]),
|
|
125
130
|
ALL_KEYS: new Set<string>([]),
|
|
126
131
|
};
|
|
@@ -145,6 +150,7 @@ function initKeysOfConditions() {
|
|
|
145
150
|
addIgnoreCase(KeysOfConditions.COMPARE_KEYS, KeysOfConditions.$LIKE_INCLUDE);
|
|
146
151
|
addIgnoreCase(KeysOfConditions.COMPARE_KEYS, KeysOfConditions.$NOT_LIKE);
|
|
147
152
|
addIgnoreCase(KeysOfConditions.COMPARE_KEYS, KeysOfConditions.$NOT_LIKE_INCLUDE);
|
|
153
|
+
addIgnoreCase(KeysOfConditions.COMPARE_KEYS, KeysOfConditions.$JSON_ARRAY_CONTAINS);
|
|
148
154
|
addIgnoreCase(KeysOfConditions.COMPARE_KEYS, KeysOfConditions.$MATCH);
|
|
149
155
|
addIgnoreCase(KeysOfConditions.COMPARE_KEYS, KeysOfConditions.$MATCH_BOOL);
|
|
150
156
|
addIgnoreCase(KeysOfConditions.COMPARE_KEYS, KeysOfConditions.$RANGE);
|
|
@@ -4,6 +4,8 @@ import { FuncContext } from '../models/FuncContext';
|
|
|
4
4
|
import { TypeUtils } from '../utils/TypeUtils';
|
|
5
5
|
import { MixinUtils } from '../utils/MixinUtils';
|
|
6
6
|
import * as _ from 'lodash';
|
|
7
|
+
import * as moment from 'moment';
|
|
8
|
+
import * as ejs from 'ejs';
|
|
7
9
|
import { CommonException, Exceptions } from '../exceptions';
|
|
8
10
|
import { KeysOfFunCtx } from '../models/keys';
|
|
9
11
|
|
|
@@ -24,6 +26,21 @@ class CrudProExecuteFuncService extends CrudProServiceBase {
|
|
|
24
26
|
return funCfg;
|
|
25
27
|
}
|
|
26
28
|
|
|
29
|
+
const funcContextAny: any = funcContext;
|
|
30
|
+
funcContextAny.moment = moment;
|
|
31
|
+
funcContextAny._ = _;
|
|
32
|
+
|
|
33
|
+
if (isNotNil(funCfg.executeExpressReturnString)) {
|
|
34
|
+
const expressResult = ejs.render(funCfg.executeExpressReturnString, funcContextAny);
|
|
35
|
+
return expressResult;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
if (isNotNil(funCfg.executeExpressReturnObject)) {
|
|
39
|
+
const expressResult = ejs.render(funCfg.executeExpressReturnObject, funcContextAny);
|
|
40
|
+
return JSON.parse(expressResult);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
|
|
27
44
|
if (isNotNil(funCfg.const)) {
|
|
28
45
|
return funCfg.const;
|
|
29
46
|
}
|
|
@@ -227,7 +227,22 @@ class CrudProGenSqlCondition {
|
|
|
227
227
|
if (this.sqlCfg.sqlDbType === SqlDbType.postgres) {
|
|
228
228
|
tmpSql = `${toSqlColumnName(key)} like concat('%', ?::text, '%')`; // like包含
|
|
229
229
|
}
|
|
230
|
-
}
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
else if (equalsIgnoreCase(KeysOfConditions.$JSON_ARRAY_CONTAINS, compare)) {
|
|
233
|
+
if (this.sqlCfg.sqlDbType === SqlDbType.mysql) {
|
|
234
|
+
tmpArgList.push(value0);
|
|
235
|
+
tmpSql = `JSON_CONTAINS( ${toSqlColumnName(key)} , JSON_ARRAY(?), '$')`; // MYSQL JSON_CONTAINS包含
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
if (this.sqlCfg.sqlDbType === SqlDbType.postgres) {
|
|
239
|
+
tmpArgList.push(value0);
|
|
240
|
+
tmpSql = `${toSqlColumnName(key)} @> ('["' || ? || '"]')::jsonb`; // POSTGRES JSON_CONTAINS包含
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
else if (equalsIgnoreCase(KeysOfConditions.$NOT_LIKE_INCLUDE, compare)) {
|
|
231
246
|
tmpArgList.push(value0);
|
|
232
247
|
tmpSql = `${toSqlColumnName(key)} COLLATE UTF8MB4_GENERAL_CI not like concat('%',?, '%')`; // like不包含
|
|
233
248
|
|
|
@@ -323,7 +338,12 @@ class CrudProGenSqlCondition {
|
|
|
323
338
|
if (!isBasicType(value0)) {
|
|
324
339
|
throwCommonException(KeysOfConditions.$NOT_LIKE_INCLUDE, '字符串');
|
|
325
340
|
}
|
|
326
|
-
} else if (equalsIgnoreCase(KeysOfConditions.$
|
|
341
|
+
} else if (equalsIgnoreCase(KeysOfConditions.$JSON_ARRAY_CONTAINS, compare)) {
|
|
342
|
+
if (!isBasicType(value0)) {
|
|
343
|
+
throwCommonException(KeysOfConditions.$JSON_ARRAY_CONTAINS, '字符串或数字');
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
else if (equalsIgnoreCase(KeysOfConditions.$MATCH, compare)) {
|
|
327
347
|
if (!isBasicType(value0)) {
|
|
328
348
|
throwCommonException(KeysOfConditions.$MATCH, '字符串');
|
|
329
349
|
}
|
|
@@ -41,7 +41,12 @@ const ModelUtils = {
|
|
|
41
41
|
return DEFAULT_MAX_LIMIT;
|
|
42
42
|
},
|
|
43
43
|
checkFuncCfgValid(cfgModel: IFuncCfgModel): boolean {
|
|
44
|
-
const arr = [
|
|
44
|
+
const arr = [
|
|
45
|
+
cfgModel.functionName, cfgModel.const, cfgModel.constString, cfgModel.constNumber,
|
|
46
|
+
cfgModel.constBool, cfgModel.context,
|
|
47
|
+
cfgModel.contextAsString, cfgModel.contextAsNumber, cfgModel.contextAsBool,
|
|
48
|
+
cfgModel.executeExpressReturnObject, cfgModel.executeExpressReturnString
|
|
49
|
+
];
|
|
45
50
|
for (let i = 0; i < arr.length; i++) {
|
|
46
51
|
const arrElement = arr[i];
|
|
47
52
|
if (typeof arrElement !== 'undefined') {
|
|
@@ -68,6 +68,19 @@ class ColumnsRelationMaker {
|
|
|
68
68
|
}
|
|
69
69
|
|
|
70
70
|
|
|
71
|
+
function addMarkerColumnRelation(maker: ColumnsRelationMaker, dataIndex: string, componentName: string) {
|
|
72
|
+
// 关联用户信息
|
|
73
|
+
if (componentName === tableColumnRenders.RenderUserInfo) {
|
|
74
|
+
maker.addColumnRelationByAccount(dataIndex);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// 关联枚举文案/状态标签颜色
|
|
78
|
+
if (componentName === tableColumnRenders.RenderDictEnumText || componentName === tableColumnRenders.RenderDictEnumStatus) {
|
|
79
|
+
maker.addColumnRelationByDictEnumStatus(dataIndex);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
|
|
71
84
|
@Provide()
|
|
72
85
|
export class CrudStdRelationService extends BaseService {
|
|
73
86
|
@Inject()
|
|
@@ -90,24 +103,24 @@ export class CrudStdRelationService extends BaseService {
|
|
|
90
103
|
const dataIndex = _.get(tableColumn, 'dataIndex');
|
|
91
104
|
const componentName = _.get(tableColumn, 'component.componentName');
|
|
92
105
|
|
|
93
|
-
|
|
94
|
-
if (componentName === tableColumnRenders.RenderUserInfo) {
|
|
95
|
-
maker.addColumnRelationByAccount(dataIndex);
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
// 关联枚举文案/状态标签颜色
|
|
99
|
-
if (componentName === tableColumnRenders.RenderDictEnumText || componentName === tableColumnRenders.RenderDictEnumStatus) {
|
|
100
|
-
maker.addColumnRelationByDictEnumStatus(dataIndex);
|
|
101
|
-
}
|
|
106
|
+
addMarkerColumnRelation(maker, dataIndex, componentName);
|
|
102
107
|
|
|
103
108
|
// 子属性的配置
|
|
104
109
|
const balloonTipFields = _.get(tableColumn, 'component.props.balloonTipFields');
|
|
105
110
|
if (Array.isArray(balloonTipFields) && balloonTipFields.length > 0) {
|
|
106
111
|
for (let j = 0; j < balloonTipFields.length; j++) {
|
|
107
112
|
const { component, name } = balloonTipFields[j] || {};
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
113
|
+
addMarkerColumnRelation(maker, name, component);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
// 子属性的配置
|
|
119
|
+
const linkDataConfig = _.get(tableColumn, 'component.props.linkDataConfig');
|
|
120
|
+
if (Array.isArray(linkDataConfig) && linkDataConfig.length > 0) {
|
|
121
|
+
for (let j = 0; j < linkDataConfig.length; j++) {
|
|
122
|
+
const { component, name } = linkDataConfig[j] || {};
|
|
123
|
+
addMarkerColumnRelation(maker, name, component);
|
|
111
124
|
}
|
|
112
125
|
}
|
|
113
126
|
|
|
@@ -3,7 +3,7 @@ import { Context } from '@midwayjs/koa';
|
|
|
3
3
|
import * as _ from 'lodash';
|
|
4
4
|
import { CurdProService } from './CurdProService';
|
|
5
5
|
import { HandleExecuteContextType, IExecuteContextHandler } from '@/libs/crud-pro/models/ExecuteContext';
|
|
6
|
-
import { CrudMixUtils, RelatedType } from './CurdMixUtils';
|
|
6
|
+
import { CrudMixUtils, RelatedType, toFatcmsUserAccountIdList } from './CurdMixUtils';
|
|
7
7
|
import { SystemTables } from '@/models/SystemTables';
|
|
8
8
|
import { KeysOfSimpleSQL } from '@/libs/crud-pro/models/keys';
|
|
9
9
|
import { ColumnRelation, IRequestCfgModel, IRequestModel } from '@/libs/crud-pro/interfaces';
|
|
@@ -13,6 +13,9 @@ import { GLOBAL_STATIC_CONFIG } from '@/libs/global-config/global-config';
|
|
|
13
13
|
const dictMixUtils = new CrudMixUtils(RelatedType.accountBasic);
|
|
14
14
|
|
|
15
15
|
const TMP_CTX_KEY = _.uniqueId('CurdMixByAccountService');
|
|
16
|
+
const TMP_CTX_KEY2 = _.uniqueId('CurdMixByAccountService2');
|
|
17
|
+
|
|
18
|
+
|
|
16
19
|
|
|
17
20
|
@Provide()
|
|
18
21
|
export class CurdMixByAccountService implements IExecuteContextHandler {
|
|
@@ -23,21 +26,28 @@ export class CurdMixByAccountService implements IExecuteContextHandler {
|
|
|
23
26
|
protected curdProService: CurdProService;
|
|
24
27
|
|
|
25
28
|
async handleExecuteContextPrepare(executeContext: HandleExecuteContextType) {
|
|
26
|
-
const { SystemDbName, SystemDbType
|
|
29
|
+
const { SystemDbName, SystemDbType } = GLOBAL_STATIC_CONFIG.getConfig();
|
|
27
30
|
|
|
28
31
|
const relations = dictMixUtils.pickColumnRelations(executeContext);
|
|
29
32
|
if (!relations || relations.length === 0) {
|
|
30
33
|
return;
|
|
31
34
|
}
|
|
32
35
|
|
|
36
|
+
const isArrayModeMap = new Map<string, boolean>();
|
|
37
|
+
|
|
33
38
|
const accountIds = new Set<string>();
|
|
34
39
|
dictMixUtils.forEachRowAndColumnsRelation(executeContext, (row: any, columnRelation: ColumnRelation) => {
|
|
35
40
|
const { sourceColumn } = columnRelation;
|
|
36
41
|
if (sourceColumn) {
|
|
37
42
|
const accountId = _.get(row, sourceColumn);
|
|
38
43
|
if (accountId) {
|
|
39
|
-
const fatcmsUserAccountId =
|
|
40
|
-
|
|
44
|
+
const { isArray, fatcmsUserAccountIdList, fatcmsUserAccountId } = toFatcmsUserAccountIdList(accountId);
|
|
45
|
+
if(isArray) {
|
|
46
|
+
isArrayModeMap.set(sourceColumn, true);
|
|
47
|
+
fatcmsUserAccountIdList.forEach(item => accountIds.add(item));
|
|
48
|
+
} else if(fatcmsUserAccountId) {
|
|
49
|
+
accountIds.add(fatcmsUserAccountId);
|
|
50
|
+
}
|
|
41
51
|
}
|
|
42
52
|
}
|
|
43
53
|
});
|
|
@@ -66,10 +76,13 @@ export class CurdMixByAccountService implements IExecuteContextHandler {
|
|
|
66
76
|
const res = await this.curdProService.executeCrudByCfg(reqJson, cfgModel);
|
|
67
77
|
const userInfos = res.getResRows();
|
|
68
78
|
executeContext[TMP_CTX_KEY] = MixinUtils.toNewMap(userInfos, (obj: any) => obj.account_id);
|
|
79
|
+
executeContext[TMP_CTX_KEY2] = isArrayModeMap;
|
|
69
80
|
}
|
|
70
81
|
|
|
71
82
|
async handleExecuteContext(executeContext: HandleExecuteContextType): Promise<void> {
|
|
72
83
|
const userInfoMap = executeContext[TMP_CTX_KEY] as Map<string, any>;
|
|
84
|
+
const isArrayModeMap = executeContext[TMP_CTX_KEY2] as Map<string, boolean>;
|
|
85
|
+
|
|
73
86
|
if (!userInfoMap || userInfoMap.size === 0) {
|
|
74
87
|
return;
|
|
75
88
|
}
|
|
@@ -78,10 +91,20 @@ export class CurdMixByAccountService implements IExecuteContextHandler {
|
|
|
78
91
|
const sourceColumn = columnRelation.sourceColumn;
|
|
79
92
|
const targetColumns = columnRelation.targetColumns;
|
|
80
93
|
if (!Array.isArray(targetColumns) || targetColumns.length === 0) {
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
94
|
+
const isArrayMode = isArrayModeMap.get(sourceColumn) || false;
|
|
95
|
+
if(isArrayMode === true) {
|
|
96
|
+
columnRelation.targetColumns = [
|
|
97
|
+
{ from: 'nick_name', to: `${sourceColumn}_array_info[$ARRAY_INDEX].nick_name` },
|
|
98
|
+
{ from: 'avatar', to: `${sourceColumn}_array_info[$ARRAY_INDEX].avatar` },
|
|
99
|
+
{ from: 'account_id', to: `${sourceColumn}_array_info[$ARRAY_INDEX].account_id` },
|
|
100
|
+
];
|
|
101
|
+
} else {
|
|
102
|
+
columnRelation.targetColumns = [
|
|
103
|
+
{ from: 'nick_name', to: `${sourceColumn}_user.nick_name` },
|
|
104
|
+
{ from: 'avatar', to: `${sourceColumn}_user.avatar` },
|
|
105
|
+
{ from: 'account_id', to: `${sourceColumn}_user.account_id` },
|
|
106
|
+
];
|
|
107
|
+
}
|
|
85
108
|
}
|
|
86
109
|
dictMixUtils.copyUserInfoToRowNoRelatedCode(row, userInfoMap, columnRelation);
|
|
87
110
|
});
|
|
@@ -104,6 +104,74 @@ function copyByArraySourceValue(row: any, sourceValue: any, targetColumns: CopyA
|
|
|
104
104
|
return resultObj.isSetArray;
|
|
105
105
|
}
|
|
106
106
|
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
interface IFatcmsUserAccountIdList {
|
|
110
|
+
isArray: boolean;
|
|
111
|
+
fatcmsUserAccountId?: string;
|
|
112
|
+
fatcmsUserAccountIdList?: string[];
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function toFatcmsUserAccountIdList(accountId: any): IFatcmsUserAccountIdList {
|
|
116
|
+
const { toFatcmsUserAccountId } = GLOBAL_STATIC_CONFIG.getConfig();
|
|
117
|
+
|
|
118
|
+
if (!accountId) {
|
|
119
|
+
return {
|
|
120
|
+
isArray: false,
|
|
121
|
+
fatcmsUserAccountId: null
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// 数字形式
|
|
126
|
+
if (typeof accountId === 'number') {
|
|
127
|
+
return {
|
|
128
|
+
isArray: false,
|
|
129
|
+
fatcmsUserAccountId: toFatcmsUserAccountId("" + accountId),
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
if (typeof accountId === 'string') {
|
|
134
|
+
const json = parseJsonObject(accountId);
|
|
135
|
+
|
|
136
|
+
// 数组形式
|
|
137
|
+
if (json && Array.isArray(json) && json.length > 0) {
|
|
138
|
+
return {
|
|
139
|
+
isArray: true,
|
|
140
|
+
fatcmsUserAccountIdList: json.map(item => {
|
|
141
|
+
if (typeof item === 'string' || typeof item === 'number') {
|
|
142
|
+
return toFatcmsUserAccountId("" + item)
|
|
143
|
+
}
|
|
144
|
+
return null;
|
|
145
|
+
}).filter(item => item !== null),
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
// 单值形式
|
|
149
|
+
return {
|
|
150
|
+
isArray: false,
|
|
151
|
+
fatcmsUserAccountId: toFatcmsUserAccountId(accountId),
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// 数组形式
|
|
156
|
+
if (Array.isArray(accountId)) {
|
|
157
|
+
return {
|
|
158
|
+
isArray: true,
|
|
159
|
+
fatcmsUserAccountIdList: accountId.map(item => {
|
|
160
|
+
if (typeof item === 'string' || typeof item === 'number') {
|
|
161
|
+
return toFatcmsUserAccountId("" + item)
|
|
162
|
+
}
|
|
163
|
+
return null;
|
|
164
|
+
}).filter(item => item !== null),
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
return {
|
|
169
|
+
isArray: false,
|
|
170
|
+
fatcmsUserAccountId: null
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
|
|
107
175
|
class CrudMixUtils {
|
|
108
176
|
private readonly relatedType: RelatedType;
|
|
109
177
|
constructor(relatedType: RelatedType) {
|
|
@@ -291,8 +359,7 @@ class CrudMixUtils {
|
|
|
291
359
|
return;
|
|
292
360
|
}
|
|
293
361
|
|
|
294
|
-
const {
|
|
295
|
-
const fatcmsUserAccountId = toFatcmsUserAccountId(accountId);
|
|
362
|
+
const { isArray, fatcmsUserAccountIdList, fatcmsUserAccountId } = toFatcmsUserAccountIdList(accountId);
|
|
296
363
|
|
|
297
364
|
const getValue = (code: string) => {
|
|
298
365
|
if (!map) {
|
|
@@ -304,11 +371,13 @@ class CrudMixUtils {
|
|
|
304
371
|
return map[code];
|
|
305
372
|
};
|
|
306
373
|
|
|
307
|
-
|
|
308
|
-
|
|
374
|
+
if (isArray) {
|
|
375
|
+
copyByArraySourceValue(row, fatcmsUserAccountIdList, targetColumns, getValue);
|
|
376
|
+
} else if (fatcmsUserAccountId) {
|
|
309
377
|
copyBySingleSourceValue(row, fatcmsUserAccountId, targetColumns, getValue);
|
|
310
378
|
}
|
|
379
|
+
|
|
311
380
|
}
|
|
312
381
|
}
|
|
313
382
|
|
|
314
|
-
export { CrudMixUtils, RelatedType, FuncRowColumnRelation };
|
|
383
|
+
export { CrudMixUtils, RelatedType, FuncRowColumnRelation, toFatcmsUserAccountIdList };
|