neo-cmp-cli 1.5.6 → 1.6.0-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +62 -47
- package/package.json +1 -1
- package/src/cmpUtils/createCmpByTemplate.js +2 -2
- package/src/cmpUtils/createCmpByZip.js +87 -0
- package/src/cmpUtils/pullCmp.js +96 -0
- package/src/cmpUtils/pushCmp.js +76 -67
- package/src/module/index.js +54 -5
- package/src/module/main.js +7 -1
- package/src/neo/NeoUMDContent.js +1 -0
- package/src/neo/neoService.js +148 -40
- package/src/projectUtils/createCmpProjectZip.js +18 -18
- package/src/projectUtils/hasNeoProject.js +2 -2
- package/src/template/antd-custom-cmp-template/neo.config.js +7 -4
- package/src/template/antd-custom-cmp-template/package.json +1 -0
- package/src/template/echarts-custom-cmp-template/neo.config.js +7 -4
- package/src/template/echarts-custom-cmp-template/package.json +1 -0
- package/src/template/empty-custom-cmp-template/neo.config.js +7 -4
- package/src/template/empty-custom-cmp-template/package.json +1 -0
- package/src/template/neo-custom-cmp-template/neo.config.js +12 -9
- package/src/template/neo-custom-cmp-template/package.json +2 -1
- package/src/template/neo-custom-cmp-template/pushCmp.js +166 -0
- package/src/template/react-custom-cmp-template/neo.config.js +7 -4
- package/src/template/react-custom-cmp-template/package.json +1 -0
- package/src/template/react-ts-custom-cmp-template/neo.config.js +7 -4
- package/src/template/react-ts-custom-cmp-template/package.json +1 -0
- package/src/template/vue2-custom-cmp-template/neo.config.js +7 -4
- package/src/template/vue2-custom-cmp-template/package.json +1 -0
- package/src/utils/common.js +48 -0
package/src/module/index.js
CHANGED
|
@@ -2,6 +2,7 @@ const figlet = require('figlet'); // 用于输出图形文字
|
|
|
2
2
|
const yargs = require('yargs'); // 命令行工具
|
|
3
3
|
const chalk = require('chalk'); // 带样式的log输出
|
|
4
4
|
const inquirer = require('inquirer'); // 问答式交互
|
|
5
|
+
const ora = require('ora');
|
|
5
6
|
|
|
6
7
|
const neoInit = require('./neoInit.js');
|
|
7
8
|
const neoInitByCopy = require('./neoInitByCopy.js');
|
|
@@ -10,6 +11,7 @@ const neoConfigInit = require('../utils/neoConfigInit.js');
|
|
|
10
11
|
const { validateProjectName } = require('../utils/projectNameValidator.js');
|
|
11
12
|
const mainAction = require('./main.js'); // 入口文件
|
|
12
13
|
const getCmpTypeByDir = require('../cmpUtils/getCmpTypeByDir.js');
|
|
14
|
+
const NeoService = require('../neo/neoService.js');
|
|
13
15
|
|
|
14
16
|
// neo 的 package 文件
|
|
15
17
|
const neoPackage = require('../../package.json');
|
|
@@ -67,6 +69,11 @@ yargs
|
|
|
67
69
|
value: 'react-ts',
|
|
68
70
|
short: 'react-ts'
|
|
69
71
|
},
|
|
72
|
+
{
|
|
73
|
+
name: 'Neo 自定义组件(使用平台实体数据源)',
|
|
74
|
+
value: 'neo',
|
|
75
|
+
short: 'neo'
|
|
76
|
+
},
|
|
70
77
|
{
|
|
71
78
|
name: 'antd 自定义组件',
|
|
72
79
|
value: 'antd',
|
|
@@ -77,11 +84,6 @@ yargs
|
|
|
77
84
|
value: 'echarts',
|
|
78
85
|
short: 'echarts'
|
|
79
86
|
},
|
|
80
|
-
{
|
|
81
|
-
name: 'Neo 自定义组件',
|
|
82
|
-
value: 'neo',
|
|
83
|
-
short: 'neo'
|
|
84
|
-
},
|
|
85
87
|
/*
|
|
86
88
|
// 暂不提供 react js 模板(react js 模板已废弃)
|
|
87
89
|
{
|
|
@@ -227,6 +229,53 @@ yargs
|
|
|
227
229
|
}
|
|
228
230
|
}
|
|
229
231
|
)
|
|
232
|
+
.command(
|
|
233
|
+
'pullCmp [options]',
|
|
234
|
+
'拉取线上自定义组件',
|
|
235
|
+
(yargs) => {
|
|
236
|
+
yargs
|
|
237
|
+
.reset()
|
|
238
|
+
.usage(titleTip('Usage') + ': $0 preview [options]')
|
|
239
|
+
.option('name', {
|
|
240
|
+
alias: 'n',
|
|
241
|
+
describe: '自定义组件名称'
|
|
242
|
+
})
|
|
243
|
+
.alias('h', 'help');
|
|
244
|
+
},
|
|
245
|
+
async (argv) => {
|
|
246
|
+
if (argv.name) {
|
|
247
|
+
mainAction.pullCmp(argv.name);
|
|
248
|
+
} else {
|
|
249
|
+
// 创建 neoService 实例
|
|
250
|
+
const neoService = new NeoService(authConfig);
|
|
251
|
+
const spinner = ora('正在获取自定义组件列表...').start();
|
|
252
|
+
const cmpList = await neoService.getCustomCmpList();
|
|
253
|
+
if (cmpList.length === 0) {
|
|
254
|
+
console.error('当前租户暂无任何自定义组件。');
|
|
255
|
+
process.exit(1);
|
|
256
|
+
}
|
|
257
|
+
spinner.clear();
|
|
258
|
+
const cmpTypeChoices = cmpList.map((cmpType) => ({
|
|
259
|
+
name: cmpType,
|
|
260
|
+
value: cmpType
|
|
261
|
+
}));
|
|
262
|
+
questions.push({
|
|
263
|
+
name: 'cmpType',
|
|
264
|
+
type: 'list',
|
|
265
|
+
message: '请选择要拉取的自定义组件:',
|
|
266
|
+
choices: cmpTypeChoices
|
|
267
|
+
});
|
|
268
|
+
inquirer.prompt(questions).then((ans) => {
|
|
269
|
+
if (!ans.name) {
|
|
270
|
+
console.error('自定义组件名称不能为空。');
|
|
271
|
+
process.exit(1);
|
|
272
|
+
} else {
|
|
273
|
+
mainAction.pullCmp(ans.name, neoService);
|
|
274
|
+
}
|
|
275
|
+
});
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
)
|
|
230
279
|
.command(
|
|
231
280
|
'preview [options]',
|
|
232
281
|
'预览指定自定义组件(仅预览组件本身内容)',
|
package/src/module/main.js
CHANGED
|
@@ -17,6 +17,7 @@ const { getExternalsByNeoCommonModules } = require('../neo/neoRequire');
|
|
|
17
17
|
const createCommonModulesCode = require('../cmpUtils/createCommonModulesCode');
|
|
18
18
|
const createCmpByTemplate = require('../cmpUtils/createCmpByTemplate');
|
|
19
19
|
const createCmpProjectByTemplate = require('../projectUtils/createCmpProjectByTemplate');
|
|
20
|
+
const pullCmp = require('../cmpUtils/pullCmp');
|
|
20
21
|
|
|
21
22
|
const getValue = (originValue, defaultValue) => {
|
|
22
23
|
return originValue !== undefined ? originValue : defaultValue;
|
|
@@ -277,8 +278,9 @@ module.exports = {
|
|
|
277
278
|
},
|
|
278
279
|
// 发布组件到 NeoCRM 平台
|
|
279
280
|
pushCmp: (cmpType) => {
|
|
281
|
+
const { neoConfig, pushCmp: _pushCmpConfig } = curConfig;
|
|
282
|
+
const pushCmpConfig = Object.assign({}, _pushCmpConfig, neoConfig);
|
|
280
283
|
// 将 pushCmp 相关配置设置给 build2lib
|
|
281
|
-
const pushCmpConfig = curConfig.pushCmp;
|
|
282
284
|
curConfig.build2lib = Object.assign(curConfig.build2lib, pushCmpConfig);
|
|
283
285
|
|
|
284
286
|
const curEntry = curConfig.build2lib.entry;
|
|
@@ -363,5 +365,9 @@ module.exports = {
|
|
|
363
365
|
pushCmp(pushCmpConfig, cmpType);
|
|
364
366
|
});
|
|
365
367
|
},
|
|
368
|
+
// 从 NeoCRM 平台拉取组件
|
|
369
|
+
pullCmp: (cmpType, neoService) => {
|
|
370
|
+
pullCmp(cmpType, curConfig.neoConfig, neoService);
|
|
371
|
+
},
|
|
366
372
|
build2esm: (fileName) => akfun.build2esm(fileName, curConfig, consoleTag) // 构建esm输出模块
|
|
367
373
|
};
|
package/src/neo/NeoUMDContent.js
CHANGED
package/src/neo/neoService.js
CHANGED
|
@@ -2,17 +2,44 @@ const axios = require('axios');
|
|
|
2
2
|
const FormData = require('form-data');
|
|
3
3
|
const fs = require('fs');
|
|
4
4
|
const path = require('path');
|
|
5
|
+
const ora = require('ora');
|
|
5
6
|
const _ = require('lodash');
|
|
7
|
+
const { resolve } = require('akfun');
|
|
6
8
|
const updatePublishLog = require('../projectUtils/updatePublishLog');
|
|
9
|
+
const { getFramework } = require('../utils/common');
|
|
7
10
|
|
|
8
11
|
// NeoCRM 平台默认 API 配置
|
|
9
12
|
const NeoCrmAPI = {
|
|
10
13
|
neoBaseURL: 'https://crm.xiaoshouyi.com', // 平台根地址
|
|
11
14
|
tokenAPI: 'https://login.xiaoshouyi.com/auc/oauth2/token', // Token 获取接口地址
|
|
12
15
|
uploadAPI: '/rest/metadata/v3.0/ui/customComponents/actions/upload', // 文件上传接口地址
|
|
16
|
+
delete: '/rest/metadata/v3.0/ui/customComponents',
|
|
17
|
+
query: '/rest/metadata/v3.0/ui/customComponents/actions/queryCustomComponents', // 带分页
|
|
18
|
+
queryAll: '/rest/metadata/v3.0/ui/customComponents/actions/queryAllCustomComponents', // 不带分页
|
|
13
19
|
saveAPI: '/rest/metadata/v3.0/ui/customComponents/actions/saveOrUpdateComponent' // 创建或者保存接口地址
|
|
14
20
|
};
|
|
15
21
|
|
|
22
|
+
const cmpFields = [
|
|
23
|
+
'cmpType',
|
|
24
|
+
'label',
|
|
25
|
+
'componentCategory',
|
|
26
|
+
'description',
|
|
27
|
+
'framework',
|
|
28
|
+
'icon',
|
|
29
|
+
'orderNo',
|
|
30
|
+
'version',
|
|
31
|
+
'propsSchema',
|
|
32
|
+
'defaultProps',
|
|
33
|
+
'previewProps',
|
|
34
|
+
'events',
|
|
35
|
+
'actions',
|
|
36
|
+
'asset',
|
|
37
|
+
'plugin',
|
|
38
|
+
'modelAsset',
|
|
39
|
+
'cssAsset',
|
|
40
|
+
'codeLib',
|
|
41
|
+
];
|
|
42
|
+
|
|
16
43
|
/**
|
|
17
44
|
* Neo 平台服务类
|
|
18
45
|
* 提供 token 管理、文件上传、组件更新等功能
|
|
@@ -23,32 +50,34 @@ class NeoService {
|
|
|
23
50
|
* @param {object} config 配置信息
|
|
24
51
|
* @param {string} config.neoBaseURL Neo 平台根地址
|
|
25
52
|
* @param {string} config.tokenAPI Token 获取接口地址
|
|
26
|
-
* @param {object} config.
|
|
27
|
-
* @param {string} config.
|
|
28
|
-
* @param {string} config.
|
|
29
|
-
* @param {string} config.
|
|
30
|
-
* @param {string} config.
|
|
53
|
+
* @param {object} config.auth 授权信息
|
|
54
|
+
* @param {string} config.auth.client_id 客户端 ID
|
|
55
|
+
* @param {string} config.auth.client_secret 客户端密钥
|
|
56
|
+
* @param {string} config.auth.username 用户名
|
|
57
|
+
* @param {string} config.auth.password 密码
|
|
31
58
|
*/
|
|
32
59
|
constructor(config = {}) {
|
|
33
|
-
const { assetsRoot, neoBaseURL, tokenAPI,
|
|
34
|
-
if (!
|
|
35
|
-
throw new Error('
|
|
60
|
+
const { assetsRoot, neoBaseURL, tokenAPI, auth } = config;
|
|
61
|
+
if (!auth) {
|
|
62
|
+
throw new Error('auth 不能为空');
|
|
36
63
|
}
|
|
37
64
|
if (
|
|
38
|
-
!
|
|
39
|
-
!
|
|
40
|
-
!
|
|
41
|
-
!
|
|
65
|
+
!auth.client_id ||
|
|
66
|
+
!auth.client_secret ||
|
|
67
|
+
!auth.username ||
|
|
68
|
+
!auth.password
|
|
42
69
|
) {
|
|
43
70
|
throw new Error(
|
|
44
|
-
'
|
|
71
|
+
'auth 配置不完整,需要包含 client_id、client_secret、username、password'
|
|
45
72
|
);
|
|
46
73
|
}
|
|
47
74
|
|
|
48
|
-
this.assetsRoot = assetsRoot;
|
|
75
|
+
this.assetsRoot = assetsRoot || resolve('dist');
|
|
49
76
|
this.neoBaseURL = neoBaseURL || NeoCrmAPI.neoBaseURL;
|
|
50
77
|
this.tokenAPI = tokenAPI || NeoCrmAPI.tokenAPI;
|
|
51
|
-
this.
|
|
78
|
+
this.auth = auth;
|
|
79
|
+
this.cmpList = [];
|
|
80
|
+
this.cmpInfoMap = {};
|
|
52
81
|
|
|
53
82
|
// Token 缓存
|
|
54
83
|
this.tokenCache = {
|
|
@@ -96,20 +125,20 @@ class NeoService {
|
|
|
96
125
|
* @returns {Promise<string>} token
|
|
97
126
|
*/
|
|
98
127
|
async getToken() {
|
|
128
|
+
const spinner = ora('获取 token...').start();
|
|
99
129
|
// 检查缓存是否有效
|
|
100
130
|
if (!this.isTokenExpired()) {
|
|
101
|
-
|
|
131
|
+
spinner.succeed('使用缓存的 token。');
|
|
102
132
|
return this.tokenCache.token;
|
|
103
133
|
}
|
|
104
|
-
console.info('获取 token...');
|
|
105
134
|
|
|
106
135
|
// 构建表单数据格式的请求参数
|
|
107
136
|
const formData = new URLSearchParams();
|
|
108
137
|
formData.append('grant_type', 'password');
|
|
109
|
-
formData.append('client_id', this.
|
|
110
|
-
formData.append('client_secret', this.
|
|
111
|
-
formData.append('username', this.
|
|
112
|
-
formData.append('password', this.
|
|
138
|
+
formData.append('client_id', this.auth.client_id);
|
|
139
|
+
formData.append('client_secret', this.auth.client_secret);
|
|
140
|
+
formData.append('username', this.auth.username);
|
|
141
|
+
formData.append('password', this.auth.password);
|
|
113
142
|
|
|
114
143
|
const tokenUrl = this.buildFullUrl(this.tokenAPI);
|
|
115
144
|
|
|
@@ -123,7 +152,7 @@ class NeoService {
|
|
|
123
152
|
const { access_token, expires_in } = response.data || {};
|
|
124
153
|
|
|
125
154
|
if (!access_token) {
|
|
126
|
-
|
|
155
|
+
spinner.fail('获取 token 失败(授权配置错误):响应中未包含 access_token,', response.data);
|
|
127
156
|
process.exit(1);
|
|
128
157
|
}
|
|
129
158
|
|
|
@@ -133,6 +162,7 @@ class NeoService {
|
|
|
133
162
|
token: access_token,
|
|
134
163
|
expiresAt: Date.now() + (expiresIn - 60) * 1000
|
|
135
164
|
};
|
|
165
|
+
spinner.succeed('获取 token 成功。');
|
|
136
166
|
return access_token;
|
|
137
167
|
} catch (error) {
|
|
138
168
|
console.error('\n获取 token 失败:', error.message);
|
|
@@ -167,8 +197,10 @@ class NeoService {
|
|
|
167
197
|
if (!this.tokenCache.token) {
|
|
168
198
|
return await this.getToken();
|
|
169
199
|
} else if (this.isTokenExpired()) {
|
|
170
|
-
|
|
171
|
-
|
|
200
|
+
const spinner = ora('token 已过期,正在刷新...').start();
|
|
201
|
+
const token = await this.refreshToken();
|
|
202
|
+
spinner.succeed('token 刷新成功。');
|
|
203
|
+
return token;
|
|
172
204
|
}
|
|
173
205
|
return this.tokenCache.token;
|
|
174
206
|
}
|
|
@@ -216,13 +248,13 @@ class NeoService {
|
|
|
216
248
|
|
|
217
249
|
const fileName = path.basename(filePath);
|
|
218
250
|
const fileSizeKB = (fileStat.size / 1024).toFixed(2);
|
|
219
|
-
|
|
251
|
+
const spinner = ora(`正在上传文件: ${fileName} (${fileSizeKB}KB)...`).start();
|
|
220
252
|
|
|
221
253
|
try {
|
|
222
254
|
// 创建 FormData
|
|
223
255
|
const formData = new FormData();
|
|
224
256
|
const fieldName = options.fieldName || 'customComponentCode';
|
|
225
|
-
|
|
257
|
+
|
|
226
258
|
// 使用文件流而不是读取整个文件到内存(对大文件更友好)
|
|
227
259
|
const fileContent = fs.createReadStream(filePath);
|
|
228
260
|
|
|
@@ -265,7 +297,11 @@ class NeoService {
|
|
|
265
297
|
resultData = responseData.trim();
|
|
266
298
|
} else if (responseData && typeof responseData === 'object') {
|
|
267
299
|
// 检查是否有错误码
|
|
268
|
-
if (
|
|
300
|
+
if (
|
|
301
|
+
responseData.code !== undefined &&
|
|
302
|
+
responseData.code !== 200 &&
|
|
303
|
+
responseData.code !== 0
|
|
304
|
+
) {
|
|
269
305
|
const errorMsg = responseData.message || responseData.msg || '未知错误';
|
|
270
306
|
throw new Error(`上传失败: ${errorMsg} (code: ${responseData.code})`);
|
|
271
307
|
}
|
|
@@ -296,36 +332,35 @@ class NeoService {
|
|
|
296
332
|
} else if (resultData && typeof resultData === 'object' && resultData.url) {
|
|
297
333
|
fileUrl = resultData.url;
|
|
298
334
|
}
|
|
299
|
-
|
|
335
|
+
spinner.succeed(`文件上传成功: ${fileName} -> ${fileUrl}`);
|
|
300
336
|
return fileUrl;
|
|
301
337
|
} catch (error) {
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
338
|
+
spinner.fail(`上传文件失败: ${error.message}, 文件路径: ${filePath}`);
|
|
339
|
+
|
|
305
340
|
// 输出详细的错误信息
|
|
306
341
|
if (error.response) {
|
|
307
342
|
const status = error.response.status;
|
|
308
343
|
const statusText = error.response.statusText;
|
|
309
344
|
const responseData = error.response.data;
|
|
310
345
|
const requestUrl = error.config?.url || this.uploadAPI();
|
|
311
|
-
|
|
346
|
+
|
|
312
347
|
console.error(`\n========== 上传请求详情 ==========`);
|
|
313
348
|
console.error(`请求 URL: ${requestUrl}`);
|
|
314
349
|
console.error(`HTTP 状态码: ${status} ${statusText}`);
|
|
315
350
|
console.error(`响应数据:`, responseData);
|
|
316
351
|
console.error(`==================================\n`);
|
|
317
|
-
|
|
352
|
+
|
|
318
353
|
if (status === 404) {
|
|
319
354
|
throw new Error(
|
|
320
355
|
`上传 API 不存在 (404): ${requestUrl}\n` +
|
|
321
|
-
|
|
322
|
-
|
|
356
|
+
`请检查 neo.config.js 中的 neoBaseURL 配置是否正确,或者 API 路径是否存在。\n` +
|
|
357
|
+
`当前配置的 API 路径: ${NeoCrmAPI.uploadAPI}`
|
|
323
358
|
);
|
|
324
359
|
}
|
|
325
360
|
} else if (error.request) {
|
|
326
361
|
console.error('请求已发送但未收到响应,请检查网络连接或代理配置。');
|
|
327
362
|
}
|
|
328
|
-
|
|
363
|
+
|
|
329
364
|
throw error;
|
|
330
365
|
}
|
|
331
366
|
}
|
|
@@ -410,7 +445,7 @@ class NeoService {
|
|
|
410
445
|
throw new Error('componentData 不能为空');
|
|
411
446
|
}
|
|
412
447
|
|
|
413
|
-
|
|
448
|
+
const spinner = ora('正在更新自定义组件...').start();
|
|
414
449
|
|
|
415
450
|
try {
|
|
416
451
|
const fullUpdateAPI = this.saveAPI();
|
|
@@ -421,15 +456,15 @@ class NeoService {
|
|
|
421
456
|
'Content-Type': 'application/json'
|
|
422
457
|
}
|
|
423
458
|
});
|
|
424
|
-
const {code, message} = response.data || {};
|
|
459
|
+
const { code, message } = response.data || {};
|
|
425
460
|
|
|
426
461
|
if (code && code !== 200) {
|
|
427
462
|
throw new Error(`更新组件失败: ${response.data.message || '未知错误'}`);
|
|
428
463
|
}
|
|
429
|
-
|
|
430
464
|
|
|
431
|
-
|
|
465
|
+
spinner.succeed(message ? `组件更新成功: ${message}。` : '组件更新成功。');
|
|
432
466
|
} catch (error) {
|
|
467
|
+
spinner.fail('更新组件失败。');
|
|
433
468
|
if (error.message) {
|
|
434
469
|
console.error('更新组件失败:', error.message);
|
|
435
470
|
} else {
|
|
@@ -439,6 +474,79 @@ class NeoService {
|
|
|
439
474
|
}
|
|
440
475
|
}
|
|
441
476
|
|
|
477
|
+
/**
|
|
478
|
+
* 获取线上自定义组件列表
|
|
479
|
+
* @returns {Promise<array>} 自定义组件列表
|
|
480
|
+
*/
|
|
481
|
+
async getCustomCmpList() {
|
|
482
|
+
// 确保 token 有效
|
|
483
|
+
const token = await this.ensureValidToken();
|
|
484
|
+
|
|
485
|
+
/*
|
|
486
|
+
// 如果自定义组件列表已存在,则直接返回
|
|
487
|
+
if (this.cmpList && this.cmpList.length > 0) {
|
|
488
|
+
return this.cmpList;
|
|
489
|
+
}
|
|
490
|
+
*/
|
|
491
|
+
|
|
492
|
+
try {
|
|
493
|
+
let queryAllAPI = this.buildFullUrl(NeoCrmAPI.queryAll);
|
|
494
|
+
queryAllAPI += `?fields=${cmpFields.join(',')}`;
|
|
495
|
+
const response = await axios.post(queryAllAPI, {}, {
|
|
496
|
+
headers: {
|
|
497
|
+
Authorization: `Bearer ${token}`,
|
|
498
|
+
'xsy-inner-source': 'bff',
|
|
499
|
+
'Content-Type': 'application/json'
|
|
500
|
+
}
|
|
501
|
+
});
|
|
502
|
+
const { code, message } = response.data || {};
|
|
503
|
+
|
|
504
|
+
if (code && code !== 200) {
|
|
505
|
+
throw new Error(`获取自定义组件列表失败: ${message || '未知错误'}`);
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
this.updateCustomCmpList(response.data.data || []);
|
|
509
|
+
|
|
510
|
+
} catch (error) {
|
|
511
|
+
if (error.message) {
|
|
512
|
+
console.error('获取自定义组件列表失败:', error.message);
|
|
513
|
+
} else {
|
|
514
|
+
console.error('响应数据:', error);
|
|
515
|
+
}
|
|
516
|
+
process.exit(1);
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
return this.cmpList || [];
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
// 获取指定框架的自定义组件列表
|
|
523
|
+
getCmpListByFramework(framework) {
|
|
524
|
+
if (!framework) {
|
|
525
|
+
return this.cmpList;
|
|
526
|
+
}
|
|
527
|
+
const curFramework = getFramework(framework);
|
|
528
|
+
return this.cmpList.filter((cmp) => cmp.framework === curFramework);
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
// 获取自定义组件信息
|
|
532
|
+
getCmpInfoByCmpType(cmpType) {
|
|
533
|
+
if (!cmpType) {
|
|
534
|
+
return null;
|
|
535
|
+
}
|
|
536
|
+
return this.cmpInfoMap[cmpType] || null;
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
// 更新自定义组件 Map
|
|
540
|
+
updateCustomCmpList(cmpList) {
|
|
541
|
+
if (!cmpList || !Array.isArray(cmpList)) {
|
|
542
|
+
return;
|
|
543
|
+
}
|
|
544
|
+
this.cmpList = cmpList;
|
|
545
|
+
cmpList.forEach((cmp) => {
|
|
546
|
+
this.cmpInfoMap[cmp.cmpType] = cmp;
|
|
547
|
+
});
|
|
548
|
+
}
|
|
549
|
+
|
|
442
550
|
/**
|
|
443
551
|
* 通用请求方法(确保 token 有效)
|
|
444
552
|
* @param {string} method HTTP 方法
|
|
@@ -13,7 +13,7 @@ const hasNeoProject = require('./hasNeoProject');
|
|
|
13
13
|
module.exports = function (cmpType, _projectPath, assetsRoot) {
|
|
14
14
|
const projectRoot = _projectPath || process.cwd();
|
|
15
15
|
const finalAssetsRoot = assetsRoot || path.join(projectRoot, 'dist');
|
|
16
|
-
|
|
16
|
+
|
|
17
17
|
if (!hasNeoProject(_projectPath)) {
|
|
18
18
|
console.error(`${consoleTag}当前目录不是自定义组件项目,请在自定义组件项目目录下执行。`);
|
|
19
19
|
process.exit(1);
|
|
@@ -25,11 +25,11 @@ module.exports = function (cmpType, _projectPath, assetsRoot) {
|
|
|
25
25
|
}
|
|
26
26
|
|
|
27
27
|
const zip = new AdmZip();
|
|
28
|
-
|
|
28
|
+
|
|
29
29
|
// 需要排除的目录和文件
|
|
30
30
|
const excludeDirs = ['node_modules', '.neo-cli', 'dist'];
|
|
31
31
|
const excludeFiles = ['.eslintcache', 'auth.config.js'];
|
|
32
|
-
|
|
32
|
+
|
|
33
33
|
/**
|
|
34
34
|
* 判断文件/目录是否应该被排除
|
|
35
35
|
* @param {string} filePath 文件路径
|
|
@@ -39,17 +39,17 @@ module.exports = function (cmpType, _projectPath, assetsRoot) {
|
|
|
39
39
|
const shouldExclude = (filePath, relativePath) => {
|
|
40
40
|
const name = path.basename(filePath);
|
|
41
41
|
const stat = fs.statSync(filePath);
|
|
42
|
-
|
|
42
|
+
|
|
43
43
|
// 排除指定的目录
|
|
44
44
|
if (stat.isDirectory() && excludeDirs.includes(name)) {
|
|
45
45
|
return true;
|
|
46
46
|
}
|
|
47
|
-
|
|
47
|
+
|
|
48
48
|
// 排除指定的文件
|
|
49
49
|
if (stat.isFile() && excludeFiles.includes(name)) {
|
|
50
50
|
return true;
|
|
51
51
|
}
|
|
52
|
-
|
|
52
|
+
|
|
53
53
|
// 对于 src/components 目录,只包含 cmpType 子目录
|
|
54
54
|
// 处理逻辑:如果路径是 src/components/xxx,且 xxx 不是 cmpType,则排除
|
|
55
55
|
if (relativePath.startsWith('src/components')) {
|
|
@@ -63,10 +63,10 @@ module.exports = function (cmpType, _projectPath, assetsRoot) {
|
|
|
63
63
|
}
|
|
64
64
|
}
|
|
65
65
|
}
|
|
66
|
-
|
|
66
|
+
|
|
67
67
|
return false;
|
|
68
68
|
};
|
|
69
|
-
|
|
69
|
+
|
|
70
70
|
/**
|
|
71
71
|
* 递归遍历目录并添加到 zip
|
|
72
72
|
* @param {string} dirPath 目录路径
|
|
@@ -75,18 +75,18 @@ module.exports = function (cmpType, _projectPath, assetsRoot) {
|
|
|
75
75
|
const addDirectoryToZip = (dirPath, relativePath = '') => {
|
|
76
76
|
try {
|
|
77
77
|
const items = fs.readdirSync(dirPath);
|
|
78
|
-
|
|
78
|
+
|
|
79
79
|
items.forEach((item) => {
|
|
80
80
|
const itemPath = path.join(dirPath, item);
|
|
81
81
|
const itemRelativePath = relativePath ? path.join(relativePath, item) : item;
|
|
82
|
-
|
|
82
|
+
|
|
83
83
|
// 检查是否应该排除
|
|
84
84
|
if (shouldExclude(itemPath, itemRelativePath)) {
|
|
85
85
|
return;
|
|
86
86
|
}
|
|
87
|
-
|
|
87
|
+
|
|
88
88
|
const stat = fs.statSync(itemPath);
|
|
89
|
-
|
|
89
|
+
|
|
90
90
|
if (stat.isDirectory()) {
|
|
91
91
|
// 递归处理子目录
|
|
92
92
|
addDirectoryToZip(itemPath, itemRelativePath);
|
|
@@ -100,23 +100,23 @@ module.exports = function (cmpType, _projectPath, assetsRoot) {
|
|
|
100
100
|
console.error(`${consoleTag}遍历目录失败 (${dirPath}):`, error.message);
|
|
101
101
|
}
|
|
102
102
|
};
|
|
103
|
-
|
|
103
|
+
|
|
104
104
|
// 开始遍历项目根目录
|
|
105
105
|
addDirectoryToZip(projectRoot);
|
|
106
|
-
|
|
106
|
+
|
|
107
107
|
// 生成 zip 文件名
|
|
108
108
|
const zipFileName = `${_.camelCase(cmpType)}Source.zip`;
|
|
109
109
|
const zipPath = path.join(finalAssetsRoot, zipFileName);
|
|
110
|
-
|
|
110
|
+
|
|
111
111
|
// 如果已存在同名 zip 文件,先删除
|
|
112
112
|
if (fs.existsSync(zipPath)) {
|
|
113
113
|
fs.removeSync(zipPath);
|
|
114
114
|
}
|
|
115
|
-
|
|
115
|
+
|
|
116
116
|
// 写入 zip 文件
|
|
117
117
|
zip.writeZip(zipPath);
|
|
118
|
-
|
|
118
|
+
|
|
119
119
|
console.log(`${consoleTag}已创建自定义组件源码 zip 包: ${zipFileName}`);
|
|
120
|
-
|
|
120
|
+
|
|
121
121
|
return zipPath;
|
|
122
122
|
};
|
|
@@ -2,8 +2,8 @@ const fs = require('fs-extra');
|
|
|
2
2
|
const path = require('path');
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
|
-
* 判断当前是否存在
|
|
6
|
-
* 备注:neo.config.js 和 package.json 必须同时存在才算作
|
|
5
|
+
* 判断当前是否存在 自定义组件项目
|
|
6
|
+
* 备注:neo.config.js 和 package.json 必须同时存在才算作 自定义组件项目
|
|
7
7
|
*/
|
|
8
8
|
module.exports = function (_projectPath) {
|
|
9
9
|
const projectPath = _projectPath || process.cwd();
|
|
@@ -97,12 +97,12 @@ module.exports = {
|
|
|
97
97
|
}
|
|
98
98
|
*/
|
|
99
99
|
},
|
|
100
|
-
|
|
101
|
-
|
|
100
|
+
// NeoCRM 平台配置
|
|
101
|
+
neoConfig: {
|
|
102
102
|
neoBaseURL: 'https://crm-cd.xiaoshouyi.com', // 平台根地址(默认:https://crm.xiaoshouyi.com)
|
|
103
103
|
tokenAPI: 'https://login-cd.xiaoshouyi.com/auc/oauth2/token', // Token 获取接口地址(默认:https://login.xiaoshouyi.com/auc/oauth2/token)
|
|
104
104
|
// NeoCRM 授权配置
|
|
105
|
-
|
|
105
|
+
auth: {
|
|
106
106
|
client_id: 'xx', // 客户端 ID,从创建连接器的客户端信息中获取(Client_Id)
|
|
107
107
|
client_secret: 'xxx', // 客户端秘钥,从创建连接器的客户端信息中获取(Client_Secret)
|
|
108
108
|
username: 'xx', // 用户在销售易系统中的用户名
|
|
@@ -111,7 +111,10 @@ module.exports = {
|
|
|
111
111
|
* 例如,用户密码为 123456,安全令牌为 ABCDEFGH,则 password 的值应为 123456ABCDEFGH。
|
|
112
112
|
*/
|
|
113
113
|
password: 'xx xx' // 用户账户密码 + 8 位安全令牌
|
|
114
|
-
}
|
|
114
|
+
}
|
|
115
|
+
},
|
|
116
|
+
pushCmp: {
|
|
117
|
+
// 用于构建并发布至 NeoCRM 的相关配置
|
|
115
118
|
/*
|
|
116
119
|
【特别说明】以下配置项都自带默认值,非必填。如需自定义请自行配置。
|
|
117
120
|
NODE_ENV: 'production',
|
|
@@ -98,12 +98,12 @@ module.exports = {
|
|
|
98
98
|
}
|
|
99
99
|
*/
|
|
100
100
|
},
|
|
101
|
-
|
|
102
|
-
|
|
101
|
+
// NeoCRM 平台配置
|
|
102
|
+
neoConfig: {
|
|
103
103
|
neoBaseURL: 'https://crm-cd.xiaoshouyi.com', // 平台根地址(默认:https://crm.xiaoshouyi.com)
|
|
104
104
|
tokenAPI: 'https://login-cd.xiaoshouyi.com/auc/oauth2/token', // Token 获取接口地址(默认:https://login.xiaoshouyi.com/auc/oauth2/token)
|
|
105
105
|
// NeoCRM 授权配置
|
|
106
|
-
|
|
106
|
+
auth: {
|
|
107
107
|
client_id: 'xx', // 客户端 ID,从创建连接器的客户端信息中获取(Client_Id)
|
|
108
108
|
client_secret: 'xxx', // 客户端秘钥,从创建连接器的客户端信息中获取(Client_Secret)
|
|
109
109
|
username: 'xx', // 用户在销售易系统中的用户名
|
|
@@ -112,7 +112,10 @@ module.exports = {
|
|
|
112
112
|
* 例如,用户密码为 123456,安全令牌为 ABCDEFGH,则 password 的值应为 123456ABCDEFGH。
|
|
113
113
|
*/
|
|
114
114
|
password: 'xx xx' // 用户账户密码 + 8 位安全令牌
|
|
115
|
-
}
|
|
115
|
+
}
|
|
116
|
+
},
|
|
117
|
+
pushCmp: {
|
|
118
|
+
// 用于构建并发布至 NeoCRM 的相关配置
|
|
116
119
|
/*
|
|
117
120
|
【特别说明】以下配置项都自带默认值,非必填。如需自定义请自行配置。
|
|
118
121
|
NODE_ENV: 'production',
|