neo-cmp-cli 1.5.1 → 1.5.2
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 +52 -15
- package/package.json +1 -1
- package/src/cmpUtils/createCmpByTemplate.js +52 -0
- package/src/cmpUtils/createCommonModulesCode.js +15 -15
- package/src/cmpUtils/{getCmpModelRegister.js → getCmpModelRegisterCode.js} +2 -2
- package/src/cmpUtils/{getCmpPreview.js → getCmpPreviewCode.js} +2 -2
- package/src/cmpUtils/{getCmpRegister.js → getCmpRegisterCode.js} +2 -2
- package/src/cmpUtils/getCmpTypeByDir.js +41 -0
- package/src/cmpUtils/hasCmpTypeByDir.js +11 -0
- package/src/{module → cmpUtils}/previewCmp.js +2 -2
- package/src/cmpUtils/{publishCmp.js → pushCmp.js} +54 -42
- package/src/config/default.config.js +14 -2
- package/src/module/index.js +144 -21
- package/src/module/main.js +17 -13
- package/src/module/neoInit.js +3 -0
- package/src/module/neoInitByCopy.js +3 -0
- package/src/neo/NeoUMDContent.js +29 -0
- package/src/neo/neoRequire.js +7 -7
- package/src/neo/neoService.js +174 -72
- package/src/neo/wrapperContent.js +2 -1
- package/src/oss/publish2oss.js +1 -1
- package/src/plugins/AddNeoRequirePlugin.js +5 -2
- package/src/projectUtils/createCmpProjectByTemplate.js +49 -0
- package/src/{cmpUtils → projectUtils}/getEntriesWithAutoRegister.js +4 -4
- package/src/template/antd-custom-cmp-template/README.md +2 -2
- package/src/template/antd-custom-cmp-template/neo.config.js +22 -14
- package/src/template/antd-custom-cmp-template/package.json +3 -3
- package/src/template/develop/neo-custom-cmp-template/neo.config.js +1 -1
- package/src/template/echarts-custom-cmp-template/README.md +2 -2
- package/src/template/echarts-custom-cmp-template/neo.config.js +19 -13
- package/src/template/echarts-custom-cmp-template/package.json +3 -3
- package/src/template/empty-cmp/index.tsx +51 -0
- package/src/template/empty-cmp/model.ts +77 -0
- package/src/template/empty-cmp/style.scss +72 -0
- package/src/template/empty-custom-cmp-template/.prettierrc.js +12 -0
- package/src/template/empty-custom-cmp-template/README.md +45 -0
- package/src/template/empty-custom-cmp-template/commitlint.config.js +59 -0
- package/src/template/empty-custom-cmp-template/neo.config.js +126 -0
- package/src/template/empty-custom-cmp-template/package.json +57 -0
- package/src/template/empty-custom-cmp-template/public/css/base.css +283 -0
- package/src/template/empty-custom-cmp-template/public/scripts/app/bluebird.js +6679 -0
- package/src/template/empty-custom-cmp-template/public/template.html +13 -0
- package/src/template/empty-custom-cmp-template/src/assets/css/common.scss +127 -0
- package/src/template/empty-custom-cmp-template/src/assets/css/mixin.scss +47 -0
- package/src/template/empty-custom-cmp-template/src/assets/img/NeoCRM.jpg +0 -0
- package/src/template/empty-custom-cmp-template/src/assets/img/custom-widget.svg +1 -0
- package/src/template/empty-custom-cmp-template/src/assets/img/favicon.png +0 -0
- package/src/template/empty-custom-cmp-template/src/assets/img/map.svg +1 -0
- package/src/template/empty-custom-cmp-template/src/components/README.md +3 -0
- package/src/template/empty-custom-cmp-template/tsconfig.json +68 -0
- package/src/template/neo-custom-cmp-template/README.md +2 -2
- package/src/template/neo-custom-cmp-template/neo.config.js +6 -26
- package/src/template/neo-custom-cmp-template/package.json +3 -4
- package/src/template/react-custom-cmp-template/README.md +2 -2
- package/src/template/react-custom-cmp-template/neo.config.js +20 -15
- package/src/template/react-custom-cmp-template/package.json +3 -3
- package/src/template/react-ts-custom-cmp-template/README.md +2 -2
- package/src/template/react-ts-custom-cmp-template/neo.config.js +19 -14
- package/src/template/react-ts-custom-cmp-template/package.json +3 -3
- package/src/template/vue2-custom-cmp-template/README.md +2 -2
- package/src/template/vue2-custom-cmp-template/neo.config.js +20 -15
- package/src/template/vue2-custom-cmp-template/package.json +3 -3
- package/src/utils/autoEntryRootDir.js +75 -0
- package/src/utils/replaceInFilesByMap.js +54 -0
- package/test/demo.js +2 -2
- package/src/template/neo-custom-cmp-template/auth.config.js +0 -12
- /package/src/{cmpUtils → projectUtils}/getEntries.js +0 -0
- /package/src/{cmpUtils → projectUtils}/updatePublishLog.js +0 -0
package/src/neo/neoService.js
CHANGED
|
@@ -3,14 +3,14 @@ const FormData = require('form-data');
|
|
|
3
3
|
const fs = require('fs');
|
|
4
4
|
const path = require('path');
|
|
5
5
|
const _ = require('lodash');
|
|
6
|
-
const updatePublishLog = require('../
|
|
6
|
+
const updatePublishLog = require('../projectUtils/updatePublishLog');
|
|
7
7
|
|
|
8
8
|
// NeoCRM 平台默认 API 配置
|
|
9
9
|
const NeoCrmAPI = {
|
|
10
10
|
neoBaseURL: 'https://crm.xiaoshouyi.com', // 平台根地址
|
|
11
|
-
tokenAPI: 'https://login.
|
|
11
|
+
tokenAPI: 'https://login.xiaoshouyi.com/auc/oauth2/token', // Token 获取接口地址
|
|
12
12
|
uploadAPI: '/rest/metadata/v3.0/ui/customComponents/actions/upload', // 文件上传接口地址
|
|
13
|
-
saveAPI: '/rest/metadata/v3.0/ui/customComponents/actions/
|
|
13
|
+
saveAPI: '/rest/metadata/v3.0/ui/customComponents/actions/saveOrUpdateComponent' // 创建或者保存接口地址
|
|
14
14
|
};
|
|
15
15
|
|
|
16
16
|
/**
|
|
@@ -23,32 +23,32 @@ class NeoService {
|
|
|
23
23
|
* @param {object} config 配置信息
|
|
24
24
|
* @param {string} config.neoBaseURL Neo 平台根地址
|
|
25
25
|
* @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.
|
|
26
|
+
* @param {object} config.authConfig 授权信息
|
|
27
|
+
* @param {string} config.authConfig.client_id 客户端 ID
|
|
28
|
+
* @param {string} config.authConfig.client_secret 客户端密钥
|
|
29
|
+
* @param {string} config.authConfig.username 用户名
|
|
30
|
+
* @param {string} config.authConfig.password 密码
|
|
31
31
|
*/
|
|
32
32
|
constructor(config = {}) {
|
|
33
|
-
const { assetsRoot, neoBaseURL, tokenAPI,
|
|
34
|
-
if (!
|
|
35
|
-
throw new Error('
|
|
33
|
+
const { assetsRoot, neoBaseURL, tokenAPI, authConfig } = config;
|
|
34
|
+
if (!authConfig) {
|
|
35
|
+
throw new Error('authConfig 不能为空');
|
|
36
36
|
}
|
|
37
37
|
if (
|
|
38
|
-
!
|
|
39
|
-
!
|
|
40
|
-
!
|
|
41
|
-
!
|
|
38
|
+
!authConfig.client_id ||
|
|
39
|
+
!authConfig.client_secret ||
|
|
40
|
+
!authConfig.username ||
|
|
41
|
+
!authConfig.password
|
|
42
42
|
) {
|
|
43
43
|
throw new Error(
|
|
44
|
-
'
|
|
44
|
+
'authConfig 配置不完整,需要包含 client_id、client_secret、username、password'
|
|
45
45
|
);
|
|
46
46
|
}
|
|
47
47
|
|
|
48
48
|
this.assetsRoot = assetsRoot;
|
|
49
49
|
this.neoBaseURL = neoBaseURL || NeoCrmAPI.neoBaseURL;
|
|
50
50
|
this.tokenAPI = tokenAPI || NeoCrmAPI.tokenAPI;
|
|
51
|
-
this.
|
|
51
|
+
this.authConfig = authConfig;
|
|
52
52
|
|
|
53
53
|
// Token 缓存
|
|
54
54
|
this.tokenCache = {
|
|
@@ -101,29 +101,30 @@ class NeoService {
|
|
|
101
101
|
console.info('使用缓存的 token');
|
|
102
102
|
return this.tokenCache.token;
|
|
103
103
|
}
|
|
104
|
+
console.info('获取 token...');
|
|
104
105
|
|
|
105
|
-
|
|
106
|
+
// 构建表单数据格式的请求参数
|
|
107
|
+
const formData = new URLSearchParams();
|
|
108
|
+
formData.append('grant_type', 'password');
|
|
109
|
+
formData.append('client_id', this.authConfig.client_id);
|
|
110
|
+
formData.append('client_secret', this.authConfig.client_secret);
|
|
111
|
+
formData.append('username', this.authConfig.username);
|
|
112
|
+
formData.append('password', this.authConfig.password);
|
|
113
|
+
|
|
114
|
+
const tokenUrl = this.buildFullUrl(this.tokenAPI);
|
|
106
115
|
|
|
107
116
|
try {
|
|
108
|
-
|
|
109
|
-
const params = new URLSearchParams();
|
|
110
|
-
params.append('grant_type', 'password');
|
|
111
|
-
params.append('client_id', this.authorization.client_id);
|
|
112
|
-
params.append('client_secret', this.authorization.client_secret);
|
|
113
|
-
params.append('username', this.authorization.username);
|
|
114
|
-
params.append('password', this.authorization.password);
|
|
115
|
-
|
|
116
|
-
const tokenUrl = this.buildFullUrl(this.tokenAPI);
|
|
117
|
-
const response = await axios.post(tokenUrl, params, {
|
|
117
|
+
const response = await axios.post(tokenUrl, formData.toString(), {
|
|
118
118
|
headers: {
|
|
119
119
|
'Content-Type': 'application/x-www-form-urlencoded'
|
|
120
120
|
}
|
|
121
121
|
});
|
|
122
122
|
|
|
123
|
-
const { access_token, expires_in } = response.data;
|
|
123
|
+
const { access_token, expires_in } = response.data || {};
|
|
124
124
|
|
|
125
125
|
if (!access_token) {
|
|
126
|
-
|
|
126
|
+
console.error('\n获取 token 失败:响应中未包含 access_token', response.data);
|
|
127
|
+
process.exit(1);
|
|
127
128
|
}
|
|
128
129
|
|
|
129
130
|
// 缓存 token(提前 60 秒过期,避免边缘情况)
|
|
@@ -132,15 +133,15 @@ class NeoService {
|
|
|
132
133
|
token: access_token,
|
|
133
134
|
expiresAt: Date.now() + (expiresIn - 60) * 1000
|
|
134
135
|
};
|
|
135
|
-
|
|
136
|
-
console.info('token 获取成功');
|
|
137
136
|
return access_token;
|
|
138
137
|
} catch (error) {
|
|
139
|
-
console.error('获取 token 失败:', error.message);
|
|
138
|
+
console.error('\n获取 token 失败:', error.message);
|
|
139
|
+
console.error('\ntoken 授权地址:', tokenUrl);
|
|
140
|
+
console.error('\ntoken 请求参数:', formData);
|
|
140
141
|
if (error.response) {
|
|
141
142
|
console.error('响应数据:', error.response.data);
|
|
142
143
|
}
|
|
143
|
-
|
|
144
|
+
process.exit(1);
|
|
144
145
|
}
|
|
145
146
|
}
|
|
146
147
|
|
|
@@ -163,7 +164,9 @@ class NeoService {
|
|
|
163
164
|
* @returns {Promise<string>} 有效的 token
|
|
164
165
|
*/
|
|
165
166
|
async ensureValidToken() {
|
|
166
|
-
if (this.
|
|
167
|
+
if (!this.tokenCache.token) {
|
|
168
|
+
return await this.getToken();
|
|
169
|
+
} else if (this.isTokenExpired()) {
|
|
167
170
|
console.info('token 已过期,正在刷新...');
|
|
168
171
|
return await this.refreshToken();
|
|
169
172
|
}
|
|
@@ -174,59 +177,155 @@ class NeoService {
|
|
|
174
177
|
* 上传文件到 Neo 平台
|
|
175
178
|
* @param {string} filePath 文件路径
|
|
176
179
|
* @param {object} options 可选配置
|
|
177
|
-
* @param {string} options.fieldName 表单字段名,默认为 '
|
|
180
|
+
* @param {string} options.fieldName 表单字段名,默认为 'customComponentCode'
|
|
181
|
+
* @param {number} options.maxSize 最大文件大小(字节),默认 50MB
|
|
182
|
+
* @param {number} options.timeout 超时时间(毫秒),默认 60000
|
|
178
183
|
* @returns {Promise<string>} CDN 地址或文件 URL
|
|
179
184
|
*/
|
|
180
185
|
async uploadFile(filePath, options = {}) {
|
|
181
186
|
// 确保 token 有效
|
|
182
187
|
const token = await this.ensureValidToken();
|
|
183
188
|
|
|
189
|
+
// 验证文件路径
|
|
190
|
+
if (!filePath || typeof filePath !== 'string') {
|
|
191
|
+
throw new Error(`文件路径无效: ${filePath}`);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// 检查文件是否存在
|
|
184
195
|
if (!fs.existsSync(filePath)) {
|
|
185
196
|
throw new Error(`文件不存在: ${filePath}`);
|
|
186
197
|
}
|
|
187
198
|
|
|
188
|
-
|
|
199
|
+
// 检查文件状态
|
|
200
|
+
const fileStat = fs.statSync(filePath);
|
|
201
|
+
if (!fileStat.isFile()) {
|
|
202
|
+
throw new Error(`路径不是文件: ${filePath}`);
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
// 检查文件大小
|
|
206
|
+
const maxSize = options.maxSize || 50 * 1024 * 1024; // 默认 50MB
|
|
207
|
+
if (fileStat.size > maxSize) {
|
|
208
|
+
const sizeMB = (fileStat.size / 1024 / 1024).toFixed(2);
|
|
209
|
+
const maxSizeMB = (maxSize / 1024 / 1024).toFixed(2);
|
|
210
|
+
throw new Error(`文件大小超过限制: ${sizeMB}MB > ${maxSizeMB}MB`);
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
if (fileStat.size === 0) {
|
|
214
|
+
throw new Error(`文件为空: ${filePath}`);
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
const fileName = path.basename(filePath);
|
|
218
|
+
const fileSizeKB = (fileStat.size / 1024).toFixed(2);
|
|
219
|
+
console.info(`正在上传文件: ${fileName} (${fileSizeKB}KB)...`);
|
|
189
220
|
|
|
190
221
|
try {
|
|
222
|
+
// 创建 FormData
|
|
191
223
|
const formData = new FormData();
|
|
192
224
|
const fieldName = options.fieldName || 'customComponentCode';
|
|
193
|
-
|
|
225
|
+
|
|
226
|
+
// 使用文件流而不是读取整个文件到内存(对大文件更友好)
|
|
227
|
+
const fileContent = fs.createReadStream(filePath);
|
|
228
|
+
|
|
229
|
+
// 追加文件到 FormData,第三个参数指定文件名
|
|
230
|
+
formData.append(fieldName, fileContent, fileName);
|
|
194
231
|
|
|
232
|
+
// 构建完整的上传 API 地址
|
|
195
233
|
const fullUploadAPI = this.uploadAPI();
|
|
196
|
-
|
|
234
|
+
|
|
235
|
+
// 配置请求选项
|
|
236
|
+
const timeout = options.timeout || 60000; // 默认 60 秒
|
|
237
|
+
const requestConfig = {
|
|
197
238
|
headers: {
|
|
198
239
|
Authorization: `Bearer ${token}`,
|
|
240
|
+
'xsy-inner-source': 'bff',
|
|
241
|
+
// 无需手动设置 Content-Type,formData.getHeaders() 会自动设置正确的 multipart/form-data 和 boundary
|
|
199
242
|
...formData.getHeaders()
|
|
200
|
-
}
|
|
201
|
-
|
|
243
|
+
},
|
|
244
|
+
timeout,
|
|
245
|
+
// 确保 axios 正确处理大文件和流
|
|
246
|
+
maxContentLength: Infinity, // 不限制响应内容长度
|
|
247
|
+
maxBodyLength: Infinity // 不限制请求体长度(适用于文件上传)
|
|
248
|
+
};
|
|
202
249
|
|
|
203
|
-
//
|
|
250
|
+
// 发送上传请求
|
|
251
|
+
const response = await axios.post(fullUploadAPI, formData, requestConfig);
|
|
252
|
+
|
|
253
|
+
// 处理响应数据
|
|
204
254
|
let resultData;
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
resultData = response.data.data;
|
|
211
|
-
} else {
|
|
212
|
-
resultData = response.data;
|
|
255
|
+
const responseData = response.data;
|
|
256
|
+
|
|
257
|
+
// 检查响应状态码
|
|
258
|
+
if (response.status !== 200 && response.status !== 201) {
|
|
259
|
+
throw new Error(`上传失败: HTTP ${response.status}`);
|
|
213
260
|
}
|
|
214
261
|
|
|
215
|
-
|
|
216
|
-
|
|
262
|
+
// 处理不同的响应格式
|
|
263
|
+
if (typeof responseData === 'string') {
|
|
264
|
+
// 如果响应是字符串,直接使用
|
|
265
|
+
resultData = responseData.trim();
|
|
266
|
+
} else if (responseData && typeof responseData === 'object') {
|
|
267
|
+
// 检查是否有错误码
|
|
268
|
+
if (responseData.code !== undefined && responseData.code !== 200 && responseData.code !== 0) {
|
|
269
|
+
const errorMsg = responseData.message || responseData.msg || '未知错误';
|
|
270
|
+
throw new Error(`上传失败: ${errorMsg} (code: ${responseData.code})`);
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
// 提取数据
|
|
274
|
+
if (responseData.data !== undefined) {
|
|
275
|
+
resultData = responseData.data;
|
|
276
|
+
} else if (responseData.url !== undefined) {
|
|
277
|
+
resultData = responseData.url;
|
|
278
|
+
} else if (responseData.fileUrl !== undefined) {
|
|
279
|
+
resultData = responseData.fileUrl;
|
|
280
|
+
} else {
|
|
281
|
+
resultData = responseData;
|
|
282
|
+
}
|
|
283
|
+
} else {
|
|
284
|
+
throw new Error(`响应数据格式不正确: ${typeof responseData}`);
|
|
217
285
|
}
|
|
218
286
|
|
|
219
|
-
|
|
220
|
-
|
|
287
|
+
// 验证返回的文件地址
|
|
288
|
+
if (!resultData) {
|
|
289
|
+
throw new Error(`返回的文件地址为空`);
|
|
221
290
|
}
|
|
222
291
|
|
|
223
|
-
|
|
292
|
+
// 格式化文件 URL
|
|
293
|
+
let fileUrl;
|
|
294
|
+
if (typeof resultData === 'string') {
|
|
295
|
+
fileUrl = resultData;
|
|
296
|
+
} else if (resultData && typeof resultData === 'object' && resultData.url) {
|
|
297
|
+
fileUrl = resultData.url;
|
|
298
|
+
}
|
|
299
|
+
console.info(`\n文件上传成功: ${fileName} -> ${fileUrl}`);
|
|
224
300
|
return fileUrl;
|
|
225
301
|
} catch (error) {
|
|
226
|
-
console.error(
|
|
302
|
+
console.error(`\n上传文件失败: ${error.message},`);
|
|
303
|
+
console.error(`文件路径: ${filePath}。\n`);
|
|
304
|
+
|
|
305
|
+
// 输出详细的错误信息
|
|
227
306
|
if (error.response) {
|
|
228
|
-
|
|
307
|
+
const status = error.response.status;
|
|
308
|
+
const statusText = error.response.statusText;
|
|
309
|
+
const responseData = error.response.data;
|
|
310
|
+
const requestUrl = error.config?.url || this.uploadAPI();
|
|
311
|
+
|
|
312
|
+
console.error(`\n========== 上传请求详情 ==========`);
|
|
313
|
+
console.error(`请求 URL: ${requestUrl}`);
|
|
314
|
+
console.error(`HTTP 状态码: ${status} ${statusText}`);
|
|
315
|
+
console.error(`响应数据:`, responseData);
|
|
316
|
+
console.error(`==================================\n`);
|
|
317
|
+
|
|
318
|
+
if (status === 404) {
|
|
319
|
+
throw new Error(
|
|
320
|
+
`上传 API 不存在 (404): ${requestUrl}\n` +
|
|
321
|
+
`请检查 neo.config.js 中的 neoBaseURL 配置是否正确,或者 API 路径是否存在。\n` +
|
|
322
|
+
`当前配置的 API 路径: ${NeoCrmAPI.uploadAPI}`
|
|
323
|
+
);
|
|
324
|
+
}
|
|
325
|
+
} else if (error.request) {
|
|
326
|
+
console.error('请求已发送但未收到响应,请检查网络连接或代理配置。');
|
|
229
327
|
}
|
|
328
|
+
|
|
230
329
|
throw error;
|
|
231
330
|
}
|
|
232
331
|
}
|
|
@@ -238,7 +337,7 @@ class NeoService {
|
|
|
238
337
|
* @param {array} fileExtensions 需要上传的文件类型,默认 ['.js', '.css']
|
|
239
338
|
*/
|
|
240
339
|
async publish2oss(cmpType, fileExtensions = ['.js', '.css']) {
|
|
241
|
-
if (!
|
|
340
|
+
if (!cmpType) {
|
|
242
341
|
console.error(`自定义组件名称不能为空: ${cmpType}`);
|
|
243
342
|
return;
|
|
244
343
|
}
|
|
@@ -262,7 +361,7 @@ class NeoService {
|
|
|
262
361
|
// const fileExt = path.extname(file);
|
|
263
362
|
const fileInfo = path.parse(filePath);
|
|
264
363
|
if (fileStat.isFile() && fileExtensions.includes(fileInfo.ext)) {
|
|
265
|
-
let widgetName = _.
|
|
364
|
+
let widgetName = _.camelCase(cmpType);
|
|
266
365
|
|
|
267
366
|
if (file.indexOf(widgetName) < 0) {
|
|
268
367
|
return;
|
|
@@ -271,7 +370,7 @@ class NeoService {
|
|
|
271
370
|
try {
|
|
272
371
|
// 上传文件
|
|
273
372
|
const fileUrl = await this.uploadFile(filePath);
|
|
274
|
-
|
|
373
|
+
|
|
275
374
|
if (file.indexOf('Model') > -1) {
|
|
276
375
|
curCmpInfo.modelAsset = fileUrl;
|
|
277
376
|
} else if (file.endsWith('.css')) {
|
|
@@ -279,15 +378,15 @@ class NeoService {
|
|
|
279
378
|
} else {
|
|
280
379
|
curCmpInfo.asset = fileUrl;
|
|
281
380
|
}
|
|
282
|
-
|
|
283
381
|
} catch (error) {
|
|
284
|
-
console.error(`文件上传失败(${file}):\n
|
|
382
|
+
console.error(`文件上传失败(${file}):\n`);
|
|
383
|
+
process.exit(1);
|
|
285
384
|
}
|
|
286
385
|
}
|
|
287
386
|
});
|
|
288
387
|
|
|
289
388
|
await Promise.all(uploadPromises);
|
|
290
|
-
|
|
389
|
+
|
|
291
390
|
if (curCmpInfo && curCmpInfo.cmpType) {
|
|
292
391
|
console.info('上传至 OSS 的文件信息:\n', curCmpInfo);
|
|
293
392
|
// 更新发布日志
|
|
@@ -298,7 +397,6 @@ class NeoService {
|
|
|
298
397
|
|
|
299
398
|
/**
|
|
300
399
|
* 更新自定义组件
|
|
301
|
-
* @param {string} updateAPI 更新接口地址(相对或绝对路径)
|
|
302
400
|
* @param {object} componentData 组件数据
|
|
303
401
|
* @returns {Promise<object>} 更新结果
|
|
304
402
|
*/
|
|
@@ -313,26 +411,29 @@ class NeoService {
|
|
|
313
411
|
console.info('正在更新自定义组件...');
|
|
314
412
|
|
|
315
413
|
try {
|
|
316
|
-
const fullUpdateAPI = this.
|
|
414
|
+
const fullUpdateAPI = this.saveAPI();
|
|
317
415
|
const response = await axios.post(fullUpdateAPI, componentData, {
|
|
318
416
|
headers: {
|
|
319
417
|
Authorization: `Bearer ${token}`,
|
|
418
|
+
'xsy-inner-source': 'bff',
|
|
320
419
|
'Content-Type': 'application/json'
|
|
321
420
|
}
|
|
322
421
|
});
|
|
422
|
+
const {code, message} = response.data || {};
|
|
323
423
|
|
|
324
|
-
if (
|
|
424
|
+
if (code && code !== 200) {
|
|
325
425
|
throw new Error(`更新组件失败: ${response.data.message || '未知错误'}`);
|
|
326
426
|
}
|
|
427
|
+
|
|
327
428
|
|
|
328
|
-
console.info('
|
|
329
|
-
return response.data;
|
|
429
|
+
console.info(message ? `组件更新成功: ${message}。` : '组件更新成功。');
|
|
330
430
|
} catch (error) {
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
431
|
+
if (error.message) {
|
|
432
|
+
console.error('更新组件失败:', error.message);
|
|
433
|
+
} else {
|
|
434
|
+
console.error('响应数据:', error);
|
|
334
435
|
}
|
|
335
|
-
|
|
436
|
+
process.exit(1);
|
|
336
437
|
}
|
|
337
438
|
}
|
|
338
439
|
|
|
@@ -361,6 +462,7 @@ class NeoService {
|
|
|
361
462
|
params,
|
|
362
463
|
headers: {
|
|
363
464
|
Authorization: `Bearer ${token}`,
|
|
465
|
+
'xsy-inner-source': 'bff',
|
|
364
466
|
...headers
|
|
365
467
|
}
|
|
366
468
|
});
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* 注入 neoRequire 函数
|
|
3
3
|
* 备注:用于实现和 Neo 平台共享依赖
|
|
4
|
+
* 特别说明:这个文件只是用于说明 AddNeoRequirePlugin 中会插入的代码内容,实际内容内置在 AddNeoRequirePlugin 方法中。
|
|
4
5
|
*/
|
|
5
6
|
(function(NeoCustomCmpFileFactory) {
|
|
6
7
|
if (!window.neoRequire) {
|
|
@@ -12,4 +13,4 @@
|
|
|
12
13
|
* 这里放自定义组件相关内容代码
|
|
13
14
|
* 备注: 自定义组件代码中的 require 函数 已被替换成 neoRequire 函数(require === neoRequire)。
|
|
14
15
|
*/
|
|
15
|
-
});
|
|
16
|
+
});
|
package/src/oss/publish2oss.js
CHANGED
|
@@ -4,7 +4,7 @@ const path = require('path');
|
|
|
4
4
|
const _ = require('lodash');
|
|
5
5
|
const { catchCurPackageJson } = require('../utils/pathUtils');
|
|
6
6
|
const getConfigObj = require('../utils/getConfigObj');
|
|
7
|
-
const updatePublishLog = require('../
|
|
7
|
+
const updatePublishLog = require('../projectUtils/updatePublishLog');
|
|
8
8
|
|
|
9
9
|
// 获取当前项目的package文件
|
|
10
10
|
const currentPackageJsonDir = catchCurPackageJson();
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
const { ConcatSource } = require('webpack-sources');
|
|
2
|
-
|
|
2
|
+
const fs = require('fs');
|
|
3
|
+
const path = require('path');
|
|
3
4
|
/**
|
|
4
5
|
* 注入 neoRequire 函数
|
|
5
6
|
* 备注:用于实现和 Neo 平台共享依赖
|
|
@@ -163,7 +164,9 @@ class AddNeoRequirePlugin {
|
|
|
163
164
|
})(function(require) {
|
|
164
165
|
`;
|
|
165
166
|
|
|
166
|
-
const
|
|
167
|
+
// const NeoUMDContent = fs.readFileSync(path.join(__dirname, '../neo/NeoUMDContent.js'), 'utf8');
|
|
168
|
+
// const Footer = `}); \n${NeoUMDContent}`;
|
|
169
|
+
const Footer = `});`;
|
|
167
170
|
|
|
168
171
|
// 创建新的资源
|
|
169
172
|
const newSource = new ConcatSource(Header, content, Footer);
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
const fs = require('fs-extra');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
const { consoleTag } = require('../utils/neoParams'); // 输出标记
|
|
4
|
+
const { replaceInPackage } = require('../utils/replaceInPackage');
|
|
5
|
+
const { resetPackageVersion } = require('../utils/resetPackageVersion');
|
|
6
|
+
const autoEntryRootDir = require('../utils/autoEntryRootDir');
|
|
7
|
+
|
|
8
|
+
const cmpTemplateList = {
|
|
9
|
+
'react-ts': {
|
|
10
|
+
projectName: 'empty-custom-cmp-template',
|
|
11
|
+
dir: path.resolve(__dirname, '../template/empty-custom-cmp-template')
|
|
12
|
+
}
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* 通过拷贝模板创建自定义组件
|
|
17
|
+
* @param {*} projectName 自定义组件项目名称
|
|
18
|
+
* @param {*} type 自定义组件类型
|
|
19
|
+
*/
|
|
20
|
+
module.exports = function (projectName, type = 'react-ts') {
|
|
21
|
+
const finalProjectPath = path.resolve(process.cwd(), projectName);
|
|
22
|
+
|
|
23
|
+
if (fs.existsSync(finalProjectPath)) {
|
|
24
|
+
console.error(`${consoleTag}创建自定义组件失败,当前已存在(${projectName})项目,请勿创建重名项目。`);
|
|
25
|
+
process.exit(1);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const curCmpTemplate = cmpTemplateList[type];
|
|
29
|
+
if (!curCmpTemplate) {
|
|
30
|
+
console.error(`${consoleTag}创建自定义组件失败,当前不支持${type}类型。`);
|
|
31
|
+
process.exit(1);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const currentTemplateDir = curCmpTemplate.dir;
|
|
35
|
+
const finalProjectName = projectName || 'neoCustomCmp';
|
|
36
|
+
|
|
37
|
+
fs.copy(currentTemplateDir, finalProjectPath)
|
|
38
|
+
.then(() => {
|
|
39
|
+
replaceInPackage(finalProjectPath, curCmpTemplate.projectName, finalProjectName);
|
|
40
|
+
replaceInPackage(finalProjectPath, 'wibetter', 'xxx');
|
|
41
|
+
replaceInPackage(finalProjectPath, 'neo自定义组件模板', 'neo自定义组件');
|
|
42
|
+
resetPackageVersion(finalProjectPath);
|
|
43
|
+
|
|
44
|
+
console.log(`${consoleTag}已创建自定义组件(${finalProjectName})!`);
|
|
45
|
+
// 自动切换到项目根目录
|
|
46
|
+
autoEntryRootDir(finalProjectPath);
|
|
47
|
+
})
|
|
48
|
+
.catch((err) => console.error(`${consoleTag}自定义组件模板下载失败:`, err));
|
|
49
|
+
};
|
|
@@ -2,8 +2,8 @@ const fs = require('fs');
|
|
|
2
2
|
const path = require('path');
|
|
3
3
|
const _ = require('lodash');
|
|
4
4
|
const { resolveToCurrentRoot } = require('../utils/pathUtils');
|
|
5
|
-
const
|
|
6
|
-
const
|
|
5
|
+
const getCmpRegisterCode = require('../cmpUtils/getCmpRegisterCode');
|
|
6
|
+
const getCmpModelRegisterCode = require('../cmpUtils/getCmpModelRegisterCode');
|
|
7
7
|
/**
|
|
8
8
|
* 从指定目录获取组件入口文件,并自动创建对应的注册文件
|
|
9
9
|
* @param {*} defaultComponentsDir 默认组件目录
|
|
@@ -68,7 +68,7 @@ module.exports = (defaultComponentsDir = './src/components', cmpType) => {
|
|
|
68
68
|
.forEach((filePath) => {
|
|
69
69
|
if (filePath.match(/index\.[tj]sx?$/)) {
|
|
70
70
|
// 自动创建对应的注册文件
|
|
71
|
-
const registerContent =
|
|
71
|
+
const registerContent = getCmpRegisterCode(componentsBaseDir, curCmpName);
|
|
72
72
|
const registerDir = `${cmpTempDir}/register.js`;
|
|
73
73
|
|
|
74
74
|
// 写入注册文件
|
|
@@ -78,7 +78,7 @@ module.exports = (defaultComponentsDir = './src/components', cmpType) => {
|
|
|
78
78
|
linkDebugEntries.index.push(registerDir);
|
|
79
79
|
} else if (filePath.match(/model\.[tj]sx?$/)) {
|
|
80
80
|
// 自动创建对应的模型注册文件
|
|
81
|
-
const modelRegisterContent =
|
|
81
|
+
const modelRegisterContent = getCmpModelRegisterCode(componentsBaseDir, curCmpName);
|
|
82
82
|
const modelRegisterDir = `${cmpTempDir}/model.js`;
|
|
83
83
|
|
|
84
84
|
// 写入模型注册文件
|
|
@@ -41,10 +41,12 @@ module.exports = {
|
|
|
41
41
|
// 用于添加 Neo 共享依赖模块和剔除模块
|
|
42
42
|
/*
|
|
43
43
|
neoCommonModule: {
|
|
44
|
-
remotes: ['chart-widget'], // 远程自定义组件,表示当前自定义组件会用到的远程组件
|
|
45
|
-
neoExternals: ['chart-widget'], // 自定义组件中需要剔除的模块,仅支持数组写法,需要和 remotes 配合使用
|
|
46
44
|
// neoExports: ['xxModule'], // 自定义组件 共享出来的模块,支持数组和对象形式
|
|
47
|
-
|
|
45
|
+
neoExports: { // 对象写法
|
|
46
|
+
'xx-module': path.resolve('./src/components/xx-module'), // 导出 xx组件 或 xx模块
|
|
47
|
+
},
|
|
48
|
+
// remoteDeps: ['xxCmpType'], // 远程依赖组件,表示当前自定义组件会用到的依赖组件,需要和 neoExternals 配合使用
|
|
49
|
+
// neoExternals: ['xxModule'], // 自定义组件中需要剔除的模块(仅支持数组写法)
|
|
48
50
|
},
|
|
49
51
|
*/
|
|
50
52
|
preview: {
|
|
@@ -95,23 +97,29 @@ module.exports = {
|
|
|
95
97
|
}
|
|
96
98
|
*/
|
|
97
99
|
},
|
|
98
|
-
|
|
99
|
-
// 用于构建并发布至
|
|
100
|
+
pushCmp: {
|
|
101
|
+
// 用于构建并发布至 NeoCRM 的相关配置
|
|
102
|
+
neoBaseURL: 'https://crm-cd.xiaoshouyi.com', // 平台根地址(默认:https://crm.xiaoshouyi.com)
|
|
103
|
+
tokenAPI: 'https://login-cd.xiaoshouyi.com/auc/oauth2/token', // Token 获取接口地址(默认:https://login.xiaoshouyi.com/auc/oauth2/token)
|
|
104
|
+
// NeoCRM 授权配置
|
|
105
|
+
authConfig: {
|
|
106
|
+
client_id: 'xx', // 客户端 ID,从创建连接器的客户端信息中获取(Client_Id)
|
|
107
|
+
client_secret: 'xxx', // 客户端秘钥,从创建连接器的客户端信息中获取(Client_Secret)
|
|
108
|
+
username: 'xx', // 用户在销售易系统中的用户名
|
|
109
|
+
/**
|
|
110
|
+
* password 为 用户在销售易系统中的账号密码加上 8 位安全令牌。
|
|
111
|
+
* 例如,用户密码为 123456,安全令牌为 ABCDEFGH,则 password 的值应为 123456ABCDEFGH。
|
|
112
|
+
*/
|
|
113
|
+
password: 'xx xx' // 用户账户密码 + 8 位安全令牌
|
|
114
|
+
},
|
|
100
115
|
/*
|
|
101
116
|
【特别说明】以下配置项都自带默认值,非必填。如需自定义请自行配置。
|
|
102
117
|
NODE_ENV: 'production',
|
|
103
118
|
entry: { // 根据 src/components 目录下的文件自动生成 entry 相关配置
|
|
104
|
-
InfoCardModel: './src/components/
|
|
105
|
-
infoCard: './src/components/
|
|
119
|
+
InfoCardModel: './src/components/entity-form/model.ts',
|
|
120
|
+
infoCard: './src/components/entity-form/register.ts'
|
|
106
121
|
},
|
|
107
122
|
cssExtract: false, // 不额外提取css文件
|
|
108
|
-
ossType: 'ali', // oss类型:ali、baidu
|
|
109
|
-
ossConfig: {
|
|
110
|
-
endpoint: 'https://oss-cn-beijing.aliyuncs.com',
|
|
111
|
-
AccessKeyId: 'xxx',
|
|
112
|
-
AccessKeySecret: 'xx',
|
|
113
|
-
bucket: 'neo-widgets' // 存储桶名称
|
|
114
|
-
},
|
|
115
123
|
assetsRoot: resolve('dist') // 上传指定目录下的脚本文件
|
|
116
124
|
*/
|
|
117
125
|
},
|
|
@@ -10,9 +10,9 @@
|
|
|
10
10
|
"author": "wibetter",
|
|
11
11
|
"license": "MIT",
|
|
12
12
|
"scripts": {
|
|
13
|
-
"preview": "neo preview
|
|
13
|
+
"preview": "neo preview",
|
|
14
14
|
"linkDebug": "neo linkDebug",
|
|
15
|
-
"
|
|
15
|
+
"pushCmp": "neo pushCmp",
|
|
16
16
|
"format": "prettier --write \"src/**/**/*.{js,jsx,ts,tsx,vue,scss,json}\""
|
|
17
17
|
},
|
|
18
18
|
"files": [
|
|
@@ -47,7 +47,7 @@
|
|
|
47
47
|
"@commitlint/config-conventional": "^9.1.1",
|
|
48
48
|
"@types/react": "^16.9.11",
|
|
49
49
|
"@types/react-dom": "^16.9.15",
|
|
50
|
-
"neo-cmp-cli": "^1.
|
|
50
|
+
"neo-cmp-cli": "^1.5.2",
|
|
51
51
|
"husky": "^4.2.5",
|
|
52
52
|
"lint-staged": "^10.2.9",
|
|
53
53
|
"prettier": "^2.0.5"
|
|
@@ -46,8 +46,8 @@ module.exports = {
|
|
|
46
46
|
'chart-widget': path.resolve('./src/components/chart-widget'), // 导出图表自定义组件
|
|
47
47
|
'neo-register': 'neo-register', // 导出 Neo 注册模块
|
|
48
48
|
},
|
|
49
|
+
// remoteDeps: ['xxModule'], // 远程依赖组件,表示当前自定义组件会用到的远程依赖组件,需要和 neoExternals 配合使用
|
|
49
50
|
// neoExternals: ['xxModule'], // 自定义组件中需要剔除的模块,仅支持数组写法
|
|
50
|
-
// remotes: ['xxModule'], // 远程组件,表示当前自定义组件会用到的远程组件,需要和 neoExternals 配合使用
|
|
51
51
|
},
|
|
52
52
|
*/
|
|
53
53
|
preview: {
|