cloudcc-cli 2.3.3 → 2.3.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/settings.json +28 -1
- package/.cursor/skills/cloudcc-cli-dev/SKILL.md +175 -0
- package/.cursor/skills/cloudcc-dev-skill/SKILL.md +71 -0
- package/README.md +65 -7
- package/bin/cc.js +106 -28
- package/bin/index.js +54 -53
- package/mcp/cliRunner.js +11 -4
- package/mcp/index.js +12 -2
- package/mcp/tools/CloudCC Development Overview/handler.js +1 -1
- package/mcp/tools/JSP Migrator/handler.js +46 -0
- package/package.json +4 -5
- package/src/button/create.js +169 -0
- package/src/button/delete.js +35 -0
- package/src/button/doc.js +36 -0
- package/src/button/docs/devguide.md +133 -0
- package/src/button/docs/introduction.md +60 -0
- package/src/button/get.js +60 -0
- package/src/button/index.js +20 -0
- package/src/classes/docs/introduction.md +0 -20
- package/src/fields/create.js +12 -0
- package/src/identityProvider/create.js +78 -0
- package/src/identityProvider/delete.js +61 -0
- package/src/identityProvider/doc.js +46 -0
- package/src/identityProvider/docs/devguide.md +107 -0
- package/src/identityProvider/docs/introduction.md +31 -0
- package/src/identityProvider/download.js +105 -0
- package/src/identityProvider/get.js +70 -0
- package/src/identityProvider/index.js +12 -0
- package/src/menu/create-object.js +1 -0
- package/src/menu/create-page.js +1 -0
- package/src/menu/create-script.js +1 -0
- package/src/menu/create-site.js +1 -0
- package/src/object/create.js +2 -1
- package/src/object/docs/devguide.md +1 -5
- package/src/permission/add.js +164 -0
- package/src/permission/assign.js +84 -0
- package/src/permission/docs/devguide.md +238 -0
- package/src/permission/docs/introduction.md +200 -0
- package/src/permission/get.js +107 -0
- package/src/permission/index.js +10 -0
- package/src/permission/remove.js +145 -0
- package/src/project/docs/devguide.md +7 -6
- package/src/role/create.js +2 -1
- package/src/role/delete.js +1 -0
- package/src/singleSignOn/delete.js +61 -0
- package/src/singleSignOn/doc.js +46 -0
- package/src/singleSignOn/docs/devguide.md +61 -0
- package/src/singleSignOn/docs/introduction.md +3 -0
- package/src/singleSignOn/get.js +70 -0
- package/src/singleSignOn/index.js +10 -0
- package/src/staticResource/docs/introduction.md +44 -1
- package/src/user/create.js +502 -19
- package/src/validationRule/create.js +153 -0
- package/src/validationRule/delete.js +60 -0
- package/src/validationRule/doc.js +46 -0
- package/src/validationRule/docs/devguide.md +76 -0
- package/src/validationRule/docs/introduction.md +122 -0
- package/src/validationRule/get.js +47 -0
- package/src/validationRule/index.js +10 -0
- package/src/version/actionHelp.js +25 -0
- package/src/version/docs.js +26 -0
- package/src/version/doctor.js +25 -0
- package/src/version/get.js +7 -1
- package/src/version/help.js +47 -0
- package/src/version/index.js +9 -2
- package/src/version/initHelp.js +13 -0
- package/src/version/listModuleCommands.js +241 -0
- package/src/version/stats.js +44 -0
- package/src/version/uninstall.js +30 -0
- package/src/version/update.js +13 -0
- package/utils/checkVersion.js +31 -2
- package/utils/commandStats.js +94 -0
- package/utils/formatReleaseNotes.js +312 -0
- package/utils/readmeReleases.js +69 -0
- package/.cloudcc-cache.json +0 -38
- package/.cursor/skills/cloudcc-cli-dev.zip +0 -0
- package/.cursor/skills/cloudcc-cli-usage/SKILL.md +0 -68
- package/build/component-CCPlugin1774500425584.common.js +0 -831
- package/build/component-CCPlugin1774500425584.common.js.map +0 -1
- package/build/component-CCPlugin1774500425584.css +0 -1
- package/build/component-CCPlugin1774500425584.umd.js +0 -874
- package/build/component-CCPlugin1774500425584.umd.js.map +0 -1
- package/build/component-CCPlugin1774500425584.umd.min.js +0 -8
- package/build/component-CCPlugin1774500425584.umd.min.js.map +0 -1
- package/build/demo.html +0 -1
package/src/user/create.js
CHANGED
|
@@ -1,48 +1,531 @@
|
|
|
1
1
|
const chalk = require('chalk');
|
|
2
|
+
const inquirer = require('inquirer');
|
|
3
|
+
const { postClass } = require("../../utils/http");
|
|
4
|
+
const { getPackageJson } = require("../../utils/config");
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* 获取字段标签
|
|
8
|
+
* @param {Object} field - 字段定义
|
|
9
|
+
* @returns {string}
|
|
10
|
+
*/
|
|
11
|
+
function getFieldLabel(field) {
|
|
12
|
+
if (field.fieldProperty && field.fieldProperty.label) {
|
|
13
|
+
return field.fieldProperty.label;
|
|
14
|
+
}
|
|
15
|
+
return field.apiName;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* 获取字段默认值
|
|
20
|
+
* @param {Object} field - 字段定义
|
|
21
|
+
* @returns {any}
|
|
22
|
+
*/
|
|
23
|
+
function getFieldDefaultValue(field) {
|
|
24
|
+
if (field.fieldProperty && field.fieldProperty.defaultvalue !== null && field.fieldProperty.defaultvalue !== undefined) {
|
|
25
|
+
// 布尔类型转换
|
|
26
|
+
if (field.type === 'B') {
|
|
27
|
+
return field.fieldProperty.defaultvalue === 'true' || field.fieldProperty.defaultvalue === true;
|
|
28
|
+
}
|
|
29
|
+
return field.fieldProperty.defaultvalue;
|
|
30
|
+
}
|
|
31
|
+
return undefined;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* 检查字段是否必填
|
|
36
|
+
* @param {Object} field - 字段定义
|
|
37
|
+
* @returns {boolean}
|
|
38
|
+
*/
|
|
39
|
+
function isFieldRequired(field) {
|
|
40
|
+
return field.fieldProperty && field.fieldProperty.required === '1';
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* 检查字段是否只读
|
|
45
|
+
* @param {Object} field - 字段定义
|
|
46
|
+
* @returns {boolean}
|
|
47
|
+
*/
|
|
48
|
+
function isFieldReadonly(field) {
|
|
49
|
+
return field.fieldProperty && field.fieldProperty.readonly === '1';
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* 获取查找字段的选项
|
|
54
|
+
* @param {Object} field - 字段定义
|
|
55
|
+
* @param {Object} config - 项目配置
|
|
56
|
+
* @returns {Promise<Array>}
|
|
57
|
+
*/
|
|
58
|
+
async function getLookupOptions(field, config) {
|
|
59
|
+
try {
|
|
60
|
+
const lookupObj = field.lookupObj;
|
|
61
|
+
if (!lookupObj) return [];
|
|
62
|
+
|
|
63
|
+
// 角色查询
|
|
64
|
+
if (lookupObj === 'role') {
|
|
65
|
+
const res = await postClass(
|
|
66
|
+
config.setupSvc + "/api/role/queryRoleList",
|
|
67
|
+
{ start: 0, limit: 1000 },
|
|
68
|
+
config.accessToken
|
|
69
|
+
);
|
|
70
|
+
if (res && res.result && res.data) {
|
|
71
|
+
const roles = Array.isArray(res.data) ? res.data : (res.data.list || []);
|
|
72
|
+
return roles.map(r => ({
|
|
73
|
+
name: r.name || r.roleName || r.id,
|
|
74
|
+
value: r.id
|
|
75
|
+
}));
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// 简档查询
|
|
80
|
+
if (lookupObj === 'aaa') {
|
|
81
|
+
const res = await postClass(
|
|
82
|
+
config.setupSvc + "/api/profile/query",
|
|
83
|
+
{ start: 0, limit: 1000 },
|
|
84
|
+
config.accessToken
|
|
85
|
+
);
|
|
86
|
+
if (res && res.result && res.data) {
|
|
87
|
+
const profiles = Array.isArray(res.data) ? res.data : (res.data.list || []);
|
|
88
|
+
return profiles.map(p => ({
|
|
89
|
+
name: p.name || p.profileName || p.id,
|
|
90
|
+
value: p.id
|
|
91
|
+
}));
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// 用户查询 (manager, delegated_approver等)
|
|
96
|
+
if (lookupObj === '005') {
|
|
97
|
+
const res = await postClass(
|
|
98
|
+
config.setupSvc + "/api/usermange/queryUserList",
|
|
99
|
+
{ start: 0, limit: 1000, keyword: "" },
|
|
100
|
+
config.accessToken
|
|
101
|
+
);
|
|
102
|
+
if (res && res.result && res.data) {
|
|
103
|
+
const users = Array.isArray(res.data) ? res.data : (res.data.list || []);
|
|
104
|
+
return users.map(u => ({
|
|
105
|
+
name: `${u.name || u.loginName || u.id} (${u.loginName || u.email || ''})`,
|
|
106
|
+
value: u.id
|
|
107
|
+
}));
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// 客户查询 (usercontact)
|
|
112
|
+
if (lookupObj === '003') {
|
|
113
|
+
const res = await postClass(
|
|
114
|
+
config.setupSvc + "/api/account/query",
|
|
115
|
+
{ start: 0, limit: 1000 },
|
|
116
|
+
config.accessToken
|
|
117
|
+
);
|
|
118
|
+
if (res && res.result && res.data) {
|
|
119
|
+
const accounts = Array.isArray(res.data) ? res.data : (res.data.list || []);
|
|
120
|
+
return accounts.map(a => ({
|
|
121
|
+
name: a.name || a.accountName || a.id,
|
|
122
|
+
value: a.id
|
|
123
|
+
}));
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
return [];
|
|
128
|
+
} catch (error) {
|
|
129
|
+
console.error(chalk.yellow(`Warning: 获取 ${field.apiName} 选项失败: ${error.message}`));
|
|
130
|
+
return [];
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* 获取列表字段选项
|
|
136
|
+
* @param {Object} field - 字段定义
|
|
137
|
+
* @returns {Array}
|
|
138
|
+
*/
|
|
139
|
+
function getListOptions(field) {
|
|
140
|
+
if (field.fieldProperty && field.fieldProperty.selectOptions) {
|
|
141
|
+
try {
|
|
142
|
+
const options = JSON.parse(field.fieldProperty.selectOptions);
|
|
143
|
+
return options.map(opt => ({
|
|
144
|
+
name: opt.label || opt.name || opt.value,
|
|
145
|
+
value: opt.value
|
|
146
|
+
}));
|
|
147
|
+
} catch (e) {
|
|
148
|
+
return [];
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
return [];
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* 构建 inquirer 问题
|
|
156
|
+
* @param {Object} field - 字段定义
|
|
157
|
+
* @param {Object} config - 项目配置
|
|
158
|
+
* @returns {Promise<Object|null>}
|
|
159
|
+
*/
|
|
160
|
+
async function buildQuestion(field, config) {
|
|
161
|
+
// 跳过只读字段
|
|
162
|
+
if (isFieldReadonly(field)) {
|
|
163
|
+
return null;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
const type = field.type;
|
|
167
|
+
const label = getFieldLabel(field);
|
|
168
|
+
const apiName = field.apiName;
|
|
169
|
+
const required = isFieldRequired(field);
|
|
170
|
+
const defaultValue = getFieldDefaultValue(field);
|
|
171
|
+
|
|
172
|
+
const baseQuestion = {
|
|
173
|
+
name: apiName,
|
|
174
|
+
message: required ? `${label} (${apiName}) *` : `${label} (${apiName})`,
|
|
175
|
+
};
|
|
176
|
+
|
|
177
|
+
// 根据类型构建不同的问题
|
|
178
|
+
switch (type) {
|
|
179
|
+
case 'S': // 文本
|
|
180
|
+
case 'D': // 日期
|
|
181
|
+
case 'IMG': // 图片
|
|
182
|
+
return {
|
|
183
|
+
...baseQuestion,
|
|
184
|
+
type: 'input',
|
|
185
|
+
default: defaultValue,
|
|
186
|
+
validate: required ? (v) => v.trim().length > 0 || `${label}不能为空` : undefined
|
|
187
|
+
};
|
|
188
|
+
|
|
189
|
+
case 'E': // 邮箱
|
|
190
|
+
return {
|
|
191
|
+
...baseQuestion,
|
|
192
|
+
type: 'input',
|
|
193
|
+
default: defaultValue,
|
|
194
|
+
validate: (v) => {
|
|
195
|
+
if (required && !v.trim()) return `${label}不能为空`;
|
|
196
|
+
if (v && !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(v)) return '请输入有效的邮箱地址';
|
|
197
|
+
return true;
|
|
198
|
+
}
|
|
199
|
+
};
|
|
200
|
+
|
|
201
|
+
case 'H': // 手机
|
|
202
|
+
return {
|
|
203
|
+
...baseQuestion,
|
|
204
|
+
type: 'input',
|
|
205
|
+
default: defaultValue,
|
|
206
|
+
validate: required ? (v) => v.trim().length > 0 || `${label}不能为空` : undefined
|
|
207
|
+
};
|
|
208
|
+
|
|
209
|
+
case 'N': // 数字
|
|
210
|
+
case 'c': // 货币
|
|
211
|
+
return {
|
|
212
|
+
...baseQuestion,
|
|
213
|
+
type: 'number',
|
|
214
|
+
default: defaultValue ? parseFloat(defaultValue) : undefined,
|
|
215
|
+
validate: required ? (v) => v !== undefined && v !== null && v !== '' || `${label}不能为空` : undefined
|
|
216
|
+
};
|
|
217
|
+
|
|
218
|
+
case 'B': // 布尔
|
|
219
|
+
return {
|
|
220
|
+
...baseQuestion,
|
|
221
|
+
type: 'confirm',
|
|
222
|
+
default: defaultValue !== undefined ? defaultValue : true
|
|
223
|
+
};
|
|
224
|
+
|
|
225
|
+
case 'Y': // 查找
|
|
226
|
+
const lookupOptions = await getLookupOptions(field, config);
|
|
227
|
+
if (lookupOptions.length === 0) {
|
|
228
|
+
// 如果没有选项,使用文本输入
|
|
229
|
+
return {
|
|
230
|
+
...baseQuestion,
|
|
231
|
+
type: 'input',
|
|
232
|
+
default: defaultValue,
|
|
233
|
+
validate: required ? (v) => v.trim().length > 0 || `${label}不能为空` : undefined
|
|
234
|
+
};
|
|
235
|
+
}
|
|
236
|
+
return {
|
|
237
|
+
...baseQuestion,
|
|
238
|
+
type: required ? 'list' : 'expand', // 必填用list,非必填用expand可以选skip
|
|
239
|
+
choices: required ? lookupOptions : [{ name: '(不选择)', value: '' }, ...lookupOptions],
|
|
240
|
+
default: defaultValue
|
|
241
|
+
};
|
|
242
|
+
|
|
243
|
+
case 'L': // 列表
|
|
244
|
+
const listOptions = getListOptions(field);
|
|
245
|
+
if (listOptions.length === 0) {
|
|
246
|
+
return {
|
|
247
|
+
...baseQuestion,
|
|
248
|
+
type: 'input',
|
|
249
|
+
default: defaultValue,
|
|
250
|
+
validate: required ? (v) => v.trim().length > 0 || `${label}不能为空` : undefined
|
|
251
|
+
};
|
|
252
|
+
}
|
|
253
|
+
return {
|
|
254
|
+
...baseQuestion,
|
|
255
|
+
type: required ? 'list' : 'expand',
|
|
256
|
+
choices: required ? listOptions : [{ name: '(不选择)', value: '' }, ...listOptions],
|
|
257
|
+
default: defaultValue
|
|
258
|
+
};
|
|
259
|
+
|
|
260
|
+
default:
|
|
261
|
+
return {
|
|
262
|
+
...baseQuestion,
|
|
263
|
+
type: 'input',
|
|
264
|
+
default: defaultValue,
|
|
265
|
+
validate: required ? (v) => v.trim().length > 0 || `${label}不能为空` : undefined
|
|
266
|
+
};
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
/**
|
|
271
|
+
* 获取用户创建字段配置
|
|
272
|
+
* @param {Object} config - 项目配置
|
|
273
|
+
* @returns {Promise<Object>}
|
|
274
|
+
*/
|
|
275
|
+
async function getAddUserFields(config) {
|
|
276
|
+
const res = await postClass(
|
|
277
|
+
config.setupSvc + "/api/usermange/addUserQuery",
|
|
278
|
+
{},
|
|
279
|
+
config.accessToken
|
|
280
|
+
);
|
|
281
|
+
|
|
282
|
+
if (res && res.result && res.data) {
|
|
283
|
+
return res.data;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
const msg = res && (res.returnInfo || res.message) ? (res.returnInfo || res.message) : "Unknown error";
|
|
287
|
+
throw new Error("获取用户字段配置失败: " + msg);
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
/**
|
|
291
|
+
* 保存用户
|
|
292
|
+
* @param {Object} userData - 用户数据
|
|
293
|
+
* @param {Object} config - 项目配置
|
|
294
|
+
* @returns {Promise<Object>}
|
|
295
|
+
*/
|
|
296
|
+
async function saveUser(userData, config) {
|
|
297
|
+
const dataJson = JSON.stringify(userData);
|
|
298
|
+
|
|
299
|
+
const saveRes = await postClass(
|
|
300
|
+
config.setupSvc + "/api/usermange/saveUser",
|
|
301
|
+
{ dataJson },
|
|
302
|
+
config.accessToken
|
|
303
|
+
);
|
|
304
|
+
|
|
305
|
+
if (saveRes && saveRes.result) {
|
|
306
|
+
return saveRes;
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
const msg = saveRes && (saveRes.returnInfo || saveRes.message) ? (saveRes.returnInfo || saveRes.message) : "Unknown error";
|
|
310
|
+
throw new Error("Save User Failed: " + msg);
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
/**
|
|
314
|
+
* 交互式创建用户
|
|
315
|
+
* @param {Object} config - 项目配置
|
|
316
|
+
* @param {Object} fieldConfig - 字段配置
|
|
317
|
+
* @returns {Promise<Object>}
|
|
318
|
+
*/
|
|
319
|
+
async function interactiveCreate(config, fieldConfig) {
|
|
320
|
+
console.error();
|
|
321
|
+
console.error(chalk.green('=== 创建新用户 ==='));
|
|
322
|
+
console.error(chalk.gray('根据系统配置,请填写以下信息:'));
|
|
323
|
+
console.error();
|
|
324
|
+
|
|
325
|
+
// 提取所有字段
|
|
326
|
+
const allFields = [];
|
|
327
|
+
|
|
328
|
+
// 从 fieldOrder 中提取字段
|
|
329
|
+
if (fieldConfig.fieldOrder && Array.isArray(fieldConfig.fieldOrder)) {
|
|
330
|
+
fieldConfig.fieldOrder.forEach(section => {
|
|
331
|
+
if (section.list && Array.isArray(section.list)) {
|
|
332
|
+
section.list.forEach(item => {
|
|
333
|
+
if (item.fieldProperty) {
|
|
334
|
+
allFields.push({
|
|
335
|
+
...item.fieldProperty,
|
|
336
|
+
apiName: item.fieldProperty.otherName || item.fieldProperty.name,
|
|
337
|
+
type: item.fieldProperty.type
|
|
338
|
+
});
|
|
339
|
+
}
|
|
340
|
+
});
|
|
341
|
+
}
|
|
342
|
+
});
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
// 如果没有 fieldOrder,从 fieldReltaion 中提取
|
|
346
|
+
if (allFields.length === 0 && fieldConfig.fieldReltaion && Array.isArray(fieldConfig.fieldReltaion)) {
|
|
347
|
+
fieldConfig.fieldReltaion.forEach(field => {
|
|
348
|
+
allFields.push(field);
|
|
349
|
+
});
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
// 按行号排序
|
|
353
|
+
allFields.sort((a, b) => {
|
|
354
|
+
const rowA = a.row || 0;
|
|
355
|
+
const rowB = b.row || 0;
|
|
356
|
+
return rowA - rowB;
|
|
357
|
+
});
|
|
358
|
+
|
|
359
|
+
// 去重(根据 apiName)
|
|
360
|
+
const seen = new Set();
|
|
361
|
+
const uniqueFields = allFields.filter(field => {
|
|
362
|
+
const apiName = field.apiName || (field.fieldProperty && field.fieldProperty.otherName);
|
|
363
|
+
if (seen.has(apiName)) return false;
|
|
364
|
+
seen.add(apiName);
|
|
365
|
+
return true;
|
|
366
|
+
});
|
|
367
|
+
|
|
368
|
+
// 构建问题
|
|
369
|
+
const questions = [];
|
|
370
|
+
for (const field of uniqueFields) {
|
|
371
|
+
const question = await buildQuestion(field, config);
|
|
372
|
+
if (question) {
|
|
373
|
+
questions.push(question);
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
// 交互式提问
|
|
378
|
+
const answers = await inquirer.prompt(questions);
|
|
379
|
+
|
|
380
|
+
// 转换布尔值为字符串
|
|
381
|
+
Object.keys(answers).forEach(key => {
|
|
382
|
+
if (typeof answers[key] === 'boolean') {
|
|
383
|
+
answers[key] = answers[key].toString();
|
|
384
|
+
}
|
|
385
|
+
});
|
|
386
|
+
|
|
387
|
+
// 确认提交
|
|
388
|
+
console.error();
|
|
389
|
+
console.error(chalk.blue('即将创建用户,信息如下:'));
|
|
390
|
+
console.error(chalk.gray(JSON.stringify(answers, null, 2)));
|
|
391
|
+
console.error();
|
|
392
|
+
|
|
393
|
+
const { confirm } = await inquirer.prompt([{
|
|
394
|
+
type: 'confirm',
|
|
395
|
+
name: 'confirm',
|
|
396
|
+
message: '确认创建?',
|
|
397
|
+
default: true
|
|
398
|
+
}]);
|
|
399
|
+
|
|
400
|
+
if (!confirm) {
|
|
401
|
+
console.error(chalk.yellow('已取消创建'));
|
|
402
|
+
return null;
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
return answers;
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
/**
|
|
409
|
+
* 快速创建用户(命令行参数方式)
|
|
410
|
+
* @param {string} userName - 用户名
|
|
411
|
+
* @param {string} profileId - 简档ID
|
|
412
|
+
* @param {string} email - 邮箱
|
|
413
|
+
* @param {Object} config - 项目配置
|
|
414
|
+
* @param {Object} fieldConfig - 字段配置
|
|
415
|
+
* @returns {Promise<Object>}
|
|
416
|
+
*/
|
|
417
|
+
async function quickCreate(userName, profileId, email, config, fieldConfig) {
|
|
418
|
+
// 构建基本用户数据
|
|
419
|
+
const userData = {
|
|
420
|
+
name: userName,
|
|
421
|
+
loginName: email || userName,
|
|
422
|
+
profileId: profileId,
|
|
423
|
+
email: email || '',
|
|
424
|
+
isusing: 'true'
|
|
425
|
+
};
|
|
426
|
+
|
|
427
|
+
// 获取必填字段并提示
|
|
428
|
+
const requiredFields = [];
|
|
429
|
+
|
|
430
|
+
if (fieldConfig.fieldReltaion && Array.isArray(fieldConfig.fieldReltaion)) {
|
|
431
|
+
fieldConfig.fieldReltaion.forEach(field => {
|
|
432
|
+
if (field.fieldProperty && field.fieldProperty.required === '1') {
|
|
433
|
+
const apiName = field.apiName;
|
|
434
|
+
if (!userData[apiName] && apiName !== 'name' && apiName !== 'loginName' && apiName !== 'profileId' && apiName !== 'email') {
|
|
435
|
+
requiredFields.push(field);
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
});
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
// 如果有其他必填字段,需要交互式填写
|
|
442
|
+
if (requiredFields.length > 0) {
|
|
443
|
+
console.error();
|
|
444
|
+
console.error(chalk.yellow('以下字段为必填项,需要补充信息:'));
|
|
445
|
+
|
|
446
|
+
const questions = [];
|
|
447
|
+
for (const field of requiredFields) {
|
|
448
|
+
const question = await buildQuestion(field, config);
|
|
449
|
+
if (question) {
|
|
450
|
+
questions.push(question);
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
if (questions.length > 0) {
|
|
455
|
+
const answers = await inquirer.prompt(questions);
|
|
456
|
+
Object.assign(userData, answers);
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
return userData;
|
|
461
|
+
}
|
|
2
462
|
|
|
3
463
|
/**
|
|
4
464
|
* 创建用户
|
|
5
|
-
* 用法:cc create user <path>
|
|
465
|
+
* 用法:cc create user <path> [userName] [profileId] [email]
|
|
6
466
|
* @param {Array} argvs - 命令行参数数组
|
|
7
467
|
* @returns {Promise<Object>} 创建结果
|
|
8
468
|
*/
|
|
9
469
|
async function create(argvs) {
|
|
10
470
|
try {
|
|
11
|
-
// 命令行参数格式:cc create user <path>
|
|
471
|
+
// 命令行参数格式:cc create user <path> [userName] [profileId] [email]
|
|
12
472
|
const projectPath = argvs[2] || process.cwd();
|
|
13
473
|
const userName = argvs[3];
|
|
14
474
|
const profileId = argvs[4];
|
|
15
475
|
const email = argvs[5] || '';
|
|
16
476
|
|
|
17
|
-
|
|
477
|
+
const config = await getPackageJson(projectPath);
|
|
478
|
+
if (!config || !config.accessToken) {
|
|
18
479
|
console.error();
|
|
19
|
-
console.error(chalk.red('Error:
|
|
20
|
-
console.error('用法: cc create user <path> <userName> <profileId> [email]');
|
|
21
|
-
console.error('示例:');
|
|
22
|
-
console.error(' cc create user . "张三" a0I9D000000XXXXUAI');
|
|
23
|
-
console.error(' cc create user . "李四" a0I9D000000XXXXUAI "lisi@example.com"');
|
|
480
|
+
console.error(chalk.red('Error: 配置未找到或 accessToken 缺失'));
|
|
24
481
|
console.error();
|
|
25
|
-
throw new Error('
|
|
482
|
+
throw new Error('配置未找到或 accessToken 缺失');
|
|
26
483
|
}
|
|
27
484
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
485
|
+
console.error();
|
|
486
|
+
console.error(chalk.blue('正在获取用户字段配置...'));
|
|
487
|
+
|
|
488
|
+
// 获取字段配置
|
|
489
|
+
const fieldConfig = await getAddUserFields(config);
|
|
490
|
+
|
|
491
|
+
let userData;
|
|
492
|
+
|
|
493
|
+
// 判断是否使用交互模式
|
|
494
|
+
if (!userName || !profileId) {
|
|
495
|
+
// 交互模式
|
|
496
|
+
userData = await interactiveCreate(config, fieldConfig);
|
|
497
|
+
if (!userData) {
|
|
498
|
+
return { result: false, message: '用户取消' };
|
|
499
|
+
}
|
|
500
|
+
} else {
|
|
501
|
+
// 快速创建模式
|
|
502
|
+
userData = await quickCreate(userName, profileId, email, config, fieldConfig);
|
|
34
503
|
}
|
|
35
504
|
|
|
36
505
|
console.error();
|
|
37
|
-
console.error(chalk.green(
|
|
506
|
+
console.error(chalk.green('正在保存用户...'));
|
|
507
|
+
|
|
508
|
+
// 保存用户
|
|
509
|
+
const saveRes = await saveUser(userData, config);
|
|
510
|
+
|
|
511
|
+
console.error();
|
|
512
|
+
console.error(chalk.green('✓ 用户创建成功!'));
|
|
513
|
+
console.error(` 用户名称: ${userData.name}`);
|
|
514
|
+
console.error(` 登录名: ${userData.loginName || userData.loginname || ''}`);
|
|
515
|
+
console.error(` 邮箱: ${userData.email || '(空)'}`);
|
|
516
|
+
if (saveRes.data) {
|
|
517
|
+
const userId = typeof saveRes.data === 'object'
|
|
518
|
+
? (saveRes.data.id || saveRes.data.userid || JSON.stringify(saveRes.data))
|
|
519
|
+
: saveRes.data;
|
|
520
|
+
console.error(` 用户ID: ${userId}`);
|
|
521
|
+
}
|
|
38
522
|
console.error();
|
|
39
523
|
|
|
40
|
-
|
|
41
|
-
console.error(chalk.yellow('创建用户功能待实现'));
|
|
524
|
+
return saveRes;
|
|
42
525
|
|
|
43
526
|
} catch (error) {
|
|
44
527
|
console.error();
|
|
45
|
-
console.error(chalk.red("用户创建失败:"), error);
|
|
528
|
+
console.error(chalk.red("用户创建失败:"), error.message || error);
|
|
46
529
|
throw error;
|
|
47
530
|
}
|
|
48
531
|
}
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
const chalk = require('chalk');
|
|
2
|
+
const inquirer = require('inquirer');
|
|
3
|
+
const { postClass } = require("../../utils/http");
|
|
4
|
+
const { getPackageJson } = require("../../utils/config");
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* 创建验证规则
|
|
8
|
+
* 用法:cc create validationRule <path> <objectPrefix> [ruleName] [ruleContent] [errorMessage]
|
|
9
|
+
* 流程:
|
|
10
|
+
* 1. 调用 validateRule/queryByPrefix 获取对象ID和现有规则列表
|
|
11
|
+
* 2. 交互式输入规则名称、规则内容、错误信息(未指定时)
|
|
12
|
+
* 3. 调用 validateRule/validateFunction 保存新规则
|
|
13
|
+
* @param {Array} argvs - 命令行参数数组
|
|
14
|
+
* @returns {Promise<Object>} 创建结果
|
|
15
|
+
*/
|
|
16
|
+
async function create(argvs) {
|
|
17
|
+
try {
|
|
18
|
+
// 命令行参数格式:cc create validationRule <path> <objectPrefix> [ruleName] [ruleContent] [errorMessage]
|
|
19
|
+
const projectPath = argvs[2] || process.cwd();
|
|
20
|
+
const objectPrefix = argvs[3];
|
|
21
|
+
let ruleName = argvs[4] || '';
|
|
22
|
+
let ruleContent = argvs[5] || '';
|
|
23
|
+
let errorMessage = argvs[6] || '';
|
|
24
|
+
|
|
25
|
+
if (!objectPrefix) {
|
|
26
|
+
console.error();
|
|
27
|
+
console.error(chalk.red('Error: 缺少对象前缀'));
|
|
28
|
+
console.error('用法: cc create validationRule <path> <objectPrefix> [ruleName] [ruleContent] [errorMessage]');
|
|
29
|
+
console.error('示例:');
|
|
30
|
+
console.error(' cc create validationRule . "b00" # 交互式输入所有信息');
|
|
31
|
+
console.error(' cc create validationRule . "b00" "规则1" "Batch_Size__c__f==5" "数量必须是5"');
|
|
32
|
+
console.error();
|
|
33
|
+
throw new Error('缺少必需参数: objectPrefix');
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const config = await getPackageJson(projectPath);
|
|
37
|
+
if (!config || !config.accessToken) {
|
|
38
|
+
console.error();
|
|
39
|
+
console.error(chalk.red('Error: 配置未找到或 accessToken 缺失'));
|
|
40
|
+
console.error();
|
|
41
|
+
throw new Error('配置未找到或 accessToken 缺失');
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
console.error();
|
|
45
|
+
console.error(chalk.green(`Creating validation rule for object (${objectPrefix}), please wait...`));
|
|
46
|
+
console.error();
|
|
47
|
+
|
|
48
|
+
// 步骤1:调用 queryByPrefix 获取对象ID
|
|
49
|
+
console.error(chalk.blue('Step 1: 获取对象信息...'));
|
|
50
|
+
const queryRes = await postClass(
|
|
51
|
+
config.setupSvc + "/api/validateRule/queryByPrefix",
|
|
52
|
+
{ prefix: objectPrefix },
|
|
53
|
+
config.accessToken
|
|
54
|
+
);
|
|
55
|
+
|
|
56
|
+
if (!queryRes || !queryRes.result) {
|
|
57
|
+
const msg = queryRes && (queryRes.returnInfo || queryRes.message)
|
|
58
|
+
? (queryRes.returnInfo || queryRes.message)
|
|
59
|
+
: "获取对象信息失败";
|
|
60
|
+
throw new Error(msg);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const objId = queryRes.data?.objid;
|
|
64
|
+
if (!objId) {
|
|
65
|
+
throw new Error('无法获取对象ID,请检查对象前缀是否正确');
|
|
66
|
+
}
|
|
67
|
+
console.error(chalk.blue(`对象ID: ${objId}`));
|
|
68
|
+
|
|
69
|
+
// 步骤2:交互式输入规则信息
|
|
70
|
+
if (!ruleName) {
|
|
71
|
+
const result = await inquirer.prompt([
|
|
72
|
+
{
|
|
73
|
+
type: 'input',
|
|
74
|
+
name: 'ruleName',
|
|
75
|
+
message: '请输入规则名称:',
|
|
76
|
+
validate: (input) => input.trim() !== '' || '规则名称不能为空'
|
|
77
|
+
}
|
|
78
|
+
]);
|
|
79
|
+
ruleName = result.ruleName;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
if (!ruleContent) {
|
|
83
|
+
const result = await inquirer.prompt([
|
|
84
|
+
{
|
|
85
|
+
type: 'input',
|
|
86
|
+
name: 'ruleContent',
|
|
87
|
+
message: '请输入规则内容(例如: Batch_Size__c__f==5):',
|
|
88
|
+
validate: (input) => input.trim() !== '' || '规则内容不能为空'
|
|
89
|
+
}
|
|
90
|
+
]);
|
|
91
|
+
ruleContent = result.ruleContent;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
if (!errorMessage) {
|
|
95
|
+
const result = await inquirer.prompt([
|
|
96
|
+
{
|
|
97
|
+
type: 'input',
|
|
98
|
+
name: 'errorMessage',
|
|
99
|
+
message: '请输入错误提示信息:',
|
|
100
|
+
validate: (input) => input.trim() !== '' || '错误提示信息不能为空'
|
|
101
|
+
}
|
|
102
|
+
]);
|
|
103
|
+
errorMessage = result.errorMessage;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
console.error();
|
|
107
|
+
|
|
108
|
+
// 步骤3:调用 validateFunction 保存规则
|
|
109
|
+
console.error(chalk.blue('Step 2: 保存验证规则...'));
|
|
110
|
+
const validateData = {
|
|
111
|
+
objid: objId,
|
|
112
|
+
validate: {
|
|
113
|
+
name: ruleName,
|
|
114
|
+
description: "",
|
|
115
|
+
isactive: "true",
|
|
116
|
+
functionCode: ruleContent,
|
|
117
|
+
msgLocation: "top",
|
|
118
|
+
errorMessage: errorMessage,
|
|
119
|
+
objId: objId
|
|
120
|
+
}
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
const saveRes = await postClass(
|
|
124
|
+
config.setupSvc + "/api/validateRule/save",
|
|
125
|
+
validateData,
|
|
126
|
+
config.accessToken
|
|
127
|
+
);
|
|
128
|
+
|
|
129
|
+
if (saveRes && (saveRes.result === true || saveRes.result === "true" || saveRes.returnCode === "1")) {
|
|
130
|
+
console.error();
|
|
131
|
+
console.error(chalk.green('Success! Validation rule created.'));
|
|
132
|
+
console.error(` 规则名称: ${ruleName}`);
|
|
133
|
+
console.error(` 对象前缀: ${objectPrefix}`);
|
|
134
|
+
console.error(` 对象ID: ${objId}`);
|
|
135
|
+
console.error(` 规则内容: ${ruleContent}`);
|
|
136
|
+
console.error(` 错误信息: ${errorMessage}`);
|
|
137
|
+
console.error();
|
|
138
|
+
return saveRes;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
const msg = saveRes && (saveRes.returnInfo || saveRes.message)
|
|
142
|
+
? (saveRes.returnInfo || saveRes.message)
|
|
143
|
+
: "Unknown error";
|
|
144
|
+
throw new Error("Save ValidationRule Failed: " + msg);
|
|
145
|
+
|
|
146
|
+
} catch (error) {
|
|
147
|
+
console.error();
|
|
148
|
+
console.error(chalk.red("验证规则创建失败:"), error.message || error);
|
|
149
|
+
throw error;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
module.exports = create;
|