neo-cmp-cli 1.2.26 → 1.3.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 +60 -42
- package/package.json +1 -1
- package/src/template/antd-custom-cmp-template/package.json +1 -1
- package/src/template/echarts-custom-cmp-template/package.json +1 -1
- package/src/template/neo-custom-cmp-template/package.json +1 -1
- package/src/template/neo-custom-cmp-template/src/components/object-form/index.tsx +40 -49
- package/src/template/neo-custom-cmp-template/src/components/object-form/model.ts +0 -1
- package/src/template/neo-custom-cmp-template/src/components/object-form/style.scss +0 -1
- package/src/template/react-custom-cmp-template/package.json +1 -1
- package/src/template/react-ts-custom-cmp-template/package.json +1 -1
- package/src/template/vue2-custom-cmp-template/package.json +1 -1
package/README.md
CHANGED
|
@@ -20,18 +20,18 @@ neo-cmp-cli 是 Neo 自定义组件开发工具,基于 [AKFun](https://github.
|
|
|
20
20
|
|
|
21
21
|
## 快速开始
|
|
22
22
|
|
|
23
|
-
###
|
|
24
|
-
1)
|
|
23
|
+
### 方法一:全局安装自定义组件开发工具
|
|
24
|
+
##### 1) 全局安装
|
|
25
25
|
```bash
|
|
26
26
|
yarn global add neo-cmp-cli
|
|
27
27
|
# 或
|
|
28
28
|
npm i -g neo-cmp-cli
|
|
29
29
|
```
|
|
30
|
-
2)
|
|
30
|
+
##### 2) 创建自定义组件(默认 React+TS,可用 -t 指定模板,-n 指定自定义组件名称)
|
|
31
31
|
```bash
|
|
32
32
|
neo init -t=react-ts
|
|
33
33
|
```
|
|
34
|
-
3)
|
|
34
|
+
##### 3) 进入自定义组件项目根目录,安装依赖并运行
|
|
35
35
|
```bash
|
|
36
36
|
# 预览自定义组件内容
|
|
37
37
|
neo preview
|
|
@@ -39,14 +39,13 @@ neo preview
|
|
|
39
39
|
# 外链调试(在平台线上预览与调试)
|
|
40
40
|
neo linkDebug
|
|
41
41
|
|
|
42
|
-
# 构建库产物(默认输出到 dist)
|
|
43
|
-
neo build2lib
|
|
44
|
-
|
|
45
42
|
# 构建并发布到 OSS(确保 package.json 的 name 唯一、version 不重复)
|
|
46
43
|
neo publish2oss
|
|
47
44
|
```
|
|
48
45
|
|
|
49
|
-
###
|
|
46
|
+
### 方法二:在现有业务项目中使用自定义组件开发工具
|
|
47
|
+
此方式可用于将现有业务组件发布成平台可用自定义组件。
|
|
48
|
+
|
|
50
49
|
1) 安装到当前项目
|
|
51
50
|
```bash
|
|
52
51
|
yarn add neo-cmp-cli --dev
|
|
@@ -70,7 +69,7 @@ npm run linkDebug
|
|
|
70
69
|
npm run publish2oss
|
|
71
70
|
```
|
|
72
71
|
|
|
73
|
-
##
|
|
72
|
+
## 常用命令说明
|
|
74
73
|
- **neo init**: 交互式创建自定义组件(支持 -t、--name)。
|
|
75
74
|
- **neo preview**: 本地预览自定义组件内容,默认支持热更新与接口代理。
|
|
76
75
|
- **neo linkDebug**: 外链调试模式,在平台端页面设计器中调试自定义组件。
|
|
@@ -79,21 +78,63 @@ npm run publish2oss
|
|
|
79
78
|
## 开发须知
|
|
80
79
|
#### 1、默认自动识别自定义组件
|
|
81
80
|
- **自动生成入口配置**: 当 `entry` 未配置时,自动从 `src/components` 目录下扫描并识别自定义组件,`src/components` 下的子目录名称作为自定义组件的 cmpType,并以其目录下的 `index.ts/.tsx/.js/.jsx` 文件作为组件内容文件,model.[tj]s 作为模型内容文件;
|
|
82
|
-
- **自动注册自定义组件**: 当 `entry`
|
|
81
|
+
- **自动注册自定义组件**: 当 `entry` 未配置时,自动生成自定义组件注册文件和模型注册文件,并注入到构建脚本中,无需用户手动编写注册文件([neo-register](https://www.npmjs.com/package/neo-register))。
|
|
83
82
|
|
|
84
|
-
#### 2
|
|
85
|
-
通过 neo init
|
|
83
|
+
#### 2、设置自定义组件属性配置项
|
|
84
|
+
通过 neo init 初始化的自定义组件,默认自带组件模型文件,所有和页面设计器关联的信息均在此文件中定义(详细见 model 文件中的注释说明)。
|
|
85
|
+
其中 propsSchema 用于添加自定义组件的属性配置面板,当前可用的配置项类型请见 [neo-register 使用文档](https://www.npmjs.com/package/neo-register)。
|
|
86
86
|
|
|
87
87
|
#### 3、在自定义组件使用平台实体数据源
|
|
88
88
|
可使用 OpenAPI SDK 对接平台实体数据源,详细使用方法见 [neo-open-api](https://www.npmjs.com/package/neo-open-api)。
|
|
89
89
|
|
|
90
|
-
#### 4
|
|
91
|
-
|
|
90
|
+
#### 4、默认复用平台第三方依赖
|
|
91
|
+
自定义组件构建过程中默认会剔除掉平台已有依赖模块(比如 antd、echarts、axios、lodash 等),确保自定义组件构建后的资源体积较小。
|
|
92
|
+
|
|
93
|
+
##### 自定义组件可直接使用的第三方依赖包(NeoCRM 平台预置):
|
|
94
|
+
- react: '^16.13.1',
|
|
95
|
+
- react-dom: '^16.13.1',
|
|
96
|
+
- mobx: '^6.3.0',
|
|
97
|
+
- mobx-react: '^7.0.0',
|
|
98
|
+
- mobx-state-tree' '^5.4.0',
|
|
99
|
+
- echarts: '5.4.2',
|
|
100
|
+
- antd: '4.9.4',
|
|
101
|
+
- antd-mobile: '2.3.4',
|
|
102
|
+
- @ant-design/icons: '^4.8.0',
|
|
103
|
+
- video-react: '0.14.1',
|
|
104
|
+
- axios: '^0.27.2',
|
|
105
|
+
- classnames: '^2.3.2',
|
|
106
|
+
- qs: '^6.11.0',
|
|
107
|
+
- lodash: '^4.17.21',
|
|
108
|
+
- neo-ui-component-web: '^1.0.0',
|
|
109
|
+
- neo-ui-common' '^1.0.0',
|
|
110
|
+
- neo-open-api: '^1.0.11',
|
|
111
|
+
- amis: '^1.1.5'
|
|
112
|
+
|
|
113
|
+
备注:自定义组件中请使用依赖包支持的版本,如版本不匹配运行时可能出现异常。
|
|
114
|
+
|
|
115
|
+
#### 5、本地调试自定义组件
|
|
116
|
+
|
|
117
|
+
##### 1. 启动 外链调试模式
|
|
118
|
+
```
|
|
119
|
+
neo linkDebug
|
|
120
|
+
```
|
|
121
|
+
启动成功后,当前命令控制台会输出一个可使用的 外链脚本地址(通常为 http://localhost:1024/index.js)。
|
|
122
|
+
|
|
123
|
+
##### 2. 登录 Neo 平台,打开页面设计器,并开启 debug 模式
|
|
124
|
+
在页面设计器 URL 后添加 debug=true 参数并重新访问,即可开启 debug 模式
|
|
125
|
+
|
|
126
|
+
##### 3. 页面设计器开启 debug 模式后,左侧会展示 外部链接 管理面板
|
|
127
|
+
将第 1 步生成的「外链脚本地址」添加进来,即可在此页面设计器 / 组件物料面板中看到对应自定义组件。
|
|
128
|
+
|
|
129
|
+
#### 6、发布自定义组件
|
|
130
|
+
执行 `neo publish2oss` 即可构建对应自定义组件,并自动将构建后资源上传到对象存储(OSS)中。
|
|
131
|
+
|
|
132
|
+
##### 发布前请确保
|
|
92
133
|
- **package.json 的 name 唯一**
|
|
93
134
|
- **version 不重复**
|
|
94
135
|
- 已按需配置对象存储参数(支持自定义)
|
|
95
136
|
|
|
96
|
-
#####
|
|
137
|
+
##### 支持发布指定自定义组件
|
|
97
138
|
执行 `neo publish2oss --cmpType=xxCmp`
|
|
98
139
|
|
|
99
140
|
##### 支持自定义对象存储配置
|
|
@@ -116,31 +157,6 @@ module.exports = {
|
|
|
116
157
|
}
|
|
117
158
|
```
|
|
118
159
|
|
|
119
|
-
#### 5、默认复用平台第三方依赖
|
|
120
|
-
自定义组件构建过程中默认会剔除掉平台已有依赖模块(比如 antd、echarts、axios、lodash 等),确保自定义组件构建后的资源体积较小。
|
|
121
|
-
|
|
122
|
-
##### 自定义组件可直接使用的第三方依赖包(NeoCRM 平台预置):
|
|
123
|
-
- react: '^16.13.1',
|
|
124
|
-
- react-dom: '^16.13.1',
|
|
125
|
-
- mobx: '^6.3.0',
|
|
126
|
-
- mobx-react: '^7.0.0',
|
|
127
|
-
- mobx-state-tree' '^5.4.0',
|
|
128
|
-
- echarts: '5.4.2',
|
|
129
|
-
- antd: '4.9.4',
|
|
130
|
-
- antd-mobile: '2.3.4',
|
|
131
|
-
- @ant-design/icons: '^4.8.0',
|
|
132
|
-
- video-react: '0.14.1',
|
|
133
|
-
- axios: '^0.27.2',
|
|
134
|
-
- classnames: '^2.3.2',
|
|
135
|
-
- qs: '^6.11.0',
|
|
136
|
-
- lodash: '^4.17.21',
|
|
137
|
-
- neo-ui-component-web: '^1.0.0',
|
|
138
|
-
- neo-ui-common' '^1.0.0',
|
|
139
|
-
- neo-open-api: '^1.0.11',
|
|
140
|
-
- amis: '^1.1.5'
|
|
141
|
-
|
|
142
|
-
备注:自定义组件中请使用依赖包支持的版本,如版本不匹配运行时可能出现异常。
|
|
143
|
-
|
|
144
160
|
## 项目工程配置说明(neo.config.js)
|
|
145
161
|
neo-cmp-cli 默认提供完整配置;
|
|
146
162
|
如需自定义,使用 `neo config init` 生成 `neo.config.js` 并按需修改。
|
|
@@ -160,6 +176,9 @@ module.exports = {
|
|
|
160
176
|
```
|
|
161
177
|
|
|
162
178
|
### 2) 构建入口(优先级:linkDebug/build2lib/publish2oss.entry > webpack.entry)
|
|
179
|
+
【提示】当未配置 entry 时,cli 默认从 `src/components` 目录下扫描并识别自定义组件,并自动生成对应的 entry 构建入口配置。
|
|
180
|
+
|
|
181
|
+
如需自定义构建入口配置,请按如下结构调整项目工程配置文件(neo.config.js):
|
|
163
182
|
```javascript
|
|
164
183
|
module.exports = {
|
|
165
184
|
webpack: {
|
|
@@ -170,8 +189,7 @@ module.exports = {
|
|
|
170
189
|
publish2oss: { entry: {} },
|
|
171
190
|
}
|
|
172
191
|
```
|
|
173
|
-
|
|
174
|
-
备注2: 详细配置方法请查看 Webpack 官网 ([关于entry的配置方法](https://www.webpackjs.com/configuration/entry-context/#entry))。
|
|
192
|
+
备注: 详细配置方法请查看 Webpack 官网 ([关于entry的配置方法](https://www.webpackjs.com/configuration/entry-context/#entry))。
|
|
175
193
|
|
|
176
194
|
### 3) 解析配置(extensions/alias)
|
|
177
195
|
```javascript
|
package/package.json
CHANGED
|
@@ -145,10 +145,7 @@ export default class ObjectForm extends React.PureComponent<
|
|
|
145
145
|
const { xObjectApiKey: prevXObjectApiKey, fields: prevFields } =
|
|
146
146
|
prevProps.xObjectDataApi || {};
|
|
147
147
|
|
|
148
|
-
if (
|
|
149
|
-
xObjectApiKey !== prevXObjectApiKey ||
|
|
150
|
-
!isEqual(fields, prevFields)
|
|
151
|
-
) {
|
|
148
|
+
if (xObjectApiKey !== prevXObjectApiKey || !isEqual(fields, prevFields)) {
|
|
152
149
|
if (xObjectApiKey) {
|
|
153
150
|
await this.loadFieldList();
|
|
154
151
|
await this.getEntityTypeList(xObjectApiKey);
|
|
@@ -192,7 +189,7 @@ export default class ObjectForm extends React.PureComponent<
|
|
|
192
189
|
try {
|
|
193
190
|
// 方式一:直接从 props.xObjectDataApi 中获取字段描述
|
|
194
191
|
if (xObjectDataApi && xObjectDataApi.fieldDescList) {
|
|
195
|
-
this.setState({
|
|
192
|
+
this.setState({
|
|
196
193
|
fieldList: xObjectDataApi.fieldDescList,
|
|
197
194
|
loading: false,
|
|
198
195
|
});
|
|
@@ -206,13 +203,13 @@ export default class ObjectForm extends React.PureComponent<
|
|
|
206
203
|
if (resultData && resultData.status) {
|
|
207
204
|
const result = resultData.data || {};
|
|
208
205
|
const fieldList = result.fields || [];
|
|
209
|
-
this.setState({
|
|
210
|
-
fieldList,
|
|
206
|
+
this.setState({
|
|
207
|
+
fieldList,
|
|
211
208
|
title: result.label,
|
|
212
209
|
loading: false,
|
|
213
210
|
});
|
|
214
211
|
} else {
|
|
215
|
-
this.setState({
|
|
212
|
+
this.setState({
|
|
216
213
|
error: '获取字段列表失败',
|
|
217
214
|
loading: false,
|
|
218
215
|
});
|
|
@@ -221,7 +218,7 @@ export default class ObjectForm extends React.PureComponent<
|
|
|
221
218
|
} catch (error) {
|
|
222
219
|
console.error('获取字段列表失败:', error);
|
|
223
220
|
message.error('获取字段列表失败');
|
|
224
|
-
this.setState({
|
|
221
|
+
this.setState({
|
|
225
222
|
error: '获取字段列表失败',
|
|
226
223
|
loading: false,
|
|
227
224
|
});
|
|
@@ -269,11 +266,11 @@ export default class ObjectForm extends React.PureComponent<
|
|
|
269
266
|
|
|
270
267
|
if (response && (response.code === 200 || response.code === '200')) {
|
|
271
268
|
message.success('创建成功');
|
|
272
|
-
this.setState({
|
|
269
|
+
this.setState({
|
|
273
270
|
submitting: false,
|
|
274
271
|
submitSuccess: true,
|
|
275
272
|
});
|
|
276
|
-
|
|
273
|
+
|
|
277
274
|
// 重置表单
|
|
278
275
|
this.state.form?.resetFields();
|
|
279
276
|
|
|
@@ -344,13 +341,16 @@ export default class ObjectForm extends React.PureComponent<
|
|
|
344
341
|
);
|
|
345
342
|
}
|
|
346
343
|
|
|
347
|
-
const formItemLayout =
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
344
|
+
const formItemLayout =
|
|
345
|
+
columnCount === 2
|
|
346
|
+
? {
|
|
347
|
+
labelCol: { span: 8 },
|
|
348
|
+
wrapperCol: { span: 16 },
|
|
349
|
+
}
|
|
350
|
+
: {
|
|
351
|
+
labelCol: { span: 4 },
|
|
352
|
+
wrapperCol: { span: 20 },
|
|
353
|
+
};
|
|
354
354
|
|
|
355
355
|
return (
|
|
356
356
|
<Form
|
|
@@ -373,10 +373,7 @@ export default class ObjectForm extends React.PureComponent<
|
|
|
373
373
|
case 'entitytype':
|
|
374
374
|
// 业务类型选择器
|
|
375
375
|
inputComponent = (
|
|
376
|
-
<Select
|
|
377
|
-
placeholder="请选择业务类型"
|
|
378
|
-
allowClear
|
|
379
|
-
>
|
|
376
|
+
<Select placeholder="请选择业务类型" allowClear>
|
|
380
377
|
{entityTypeList.map((item) => (
|
|
381
378
|
<Option
|
|
382
379
|
key={item.apiKey}
|
|
@@ -392,10 +389,7 @@ export default class ObjectForm extends React.PureComponent<
|
|
|
392
389
|
case 'picklist':
|
|
393
390
|
// 单选下拉框
|
|
394
391
|
inputComponent = (
|
|
395
|
-
<Select
|
|
396
|
-
placeholder={`请选择${field.label}`}
|
|
397
|
-
allowClear
|
|
398
|
-
>
|
|
392
|
+
<Select placeholder={`请选择${field.label}`} allowClear>
|
|
399
393
|
{selectitem.map((item) => (
|
|
400
394
|
<Option key={item.apiKey} value={item.id}>
|
|
401
395
|
{item.label}
|
|
@@ -407,8 +401,8 @@ export default class ObjectForm extends React.PureComponent<
|
|
|
407
401
|
case 'textarea':
|
|
408
402
|
// 多行文本输入框
|
|
409
403
|
inputComponent = (
|
|
410
|
-
<Input.TextArea
|
|
411
|
-
placeholder={`请输入${field.label}`}
|
|
404
|
+
<Input.TextArea
|
|
405
|
+
placeholder={`请输入${field.label}`}
|
|
412
406
|
rows={3}
|
|
413
407
|
showCount
|
|
414
408
|
maxLength={500}
|
|
@@ -418,8 +412,8 @@ export default class ObjectForm extends React.PureComponent<
|
|
|
418
412
|
case 'multipicklist':
|
|
419
413
|
// 多选下拉框
|
|
420
414
|
inputComponent = (
|
|
421
|
-
<Select
|
|
422
|
-
placeholder={`请选择${field.label}`}
|
|
415
|
+
<Select
|
|
416
|
+
placeholder={`请选择${field.label}`}
|
|
423
417
|
mode="multiple"
|
|
424
418
|
allowClear
|
|
425
419
|
>
|
|
@@ -467,7 +461,7 @@ export default class ObjectForm extends React.PureComponent<
|
|
|
467
461
|
case 'float':
|
|
468
462
|
// 数字输入框
|
|
469
463
|
inputComponent = (
|
|
470
|
-
<InputNumber
|
|
464
|
+
<InputNumber
|
|
471
465
|
placeholder={`请输入${field.label}`}
|
|
472
466
|
style={{ width: '100%' }}
|
|
473
467
|
/>
|
|
@@ -476,37 +470,25 @@ export default class ObjectForm extends React.PureComponent<
|
|
|
476
470
|
case 'email':
|
|
477
471
|
// 邮箱输入框
|
|
478
472
|
inputComponent = (
|
|
479
|
-
<Input
|
|
480
|
-
placeholder={`请输入${field.label}`}
|
|
481
|
-
type="email"
|
|
482
|
-
/>
|
|
473
|
+
<Input placeholder={`请输入${field.label}`} type="email" />
|
|
483
474
|
);
|
|
484
475
|
break;
|
|
485
476
|
case 'url':
|
|
486
477
|
// URL 输入框
|
|
487
478
|
inputComponent = (
|
|
488
|
-
<Input
|
|
489
|
-
placeholder={`请输入${field.label}`}
|
|
490
|
-
type="url"
|
|
491
|
-
/>
|
|
479
|
+
<Input placeholder={`请输入${field.label}`} type="url" />
|
|
492
480
|
);
|
|
493
481
|
break;
|
|
494
482
|
case 'phone':
|
|
495
483
|
// 电话号码输入框
|
|
496
484
|
inputComponent = (
|
|
497
|
-
<Input
|
|
498
|
-
placeholder={`请输入${field.label}`}
|
|
499
|
-
type="tel"
|
|
500
|
-
/>
|
|
485
|
+
<Input placeholder={`请输入${field.label}`} type="tel" />
|
|
501
486
|
);
|
|
502
487
|
break;
|
|
503
488
|
default:
|
|
504
489
|
// 默认文本输入框
|
|
505
490
|
inputComponent = (
|
|
506
|
-
<Input
|
|
507
|
-
placeholder={`请输入${field.label}`}
|
|
508
|
-
maxLength={200}
|
|
509
|
-
/>
|
|
491
|
+
<Input placeholder={`请输入${field.label}`} maxLength={200} />
|
|
510
492
|
);
|
|
511
493
|
}
|
|
512
494
|
|
|
@@ -521,7 +503,17 @@ export default class ObjectForm extends React.PureComponent<
|
|
|
521
503
|
rules={[
|
|
522
504
|
{
|
|
523
505
|
required: field.required,
|
|
524
|
-
message: `请${
|
|
506
|
+
message: `请${
|
|
507
|
+
field.type === 'picklist' ||
|
|
508
|
+
field.type === 'multipicklist' ||
|
|
509
|
+
field.type === 'entityType' ||
|
|
510
|
+
field.type === 'entitytype' ||
|
|
511
|
+
field.type === 'date' ||
|
|
512
|
+
field.type === 'datetime' ||
|
|
513
|
+
field.type === 'time'
|
|
514
|
+
? '选择'
|
|
515
|
+
: '输入'
|
|
516
|
+
}${field.label}`,
|
|
525
517
|
},
|
|
526
518
|
]}
|
|
527
519
|
>
|
|
@@ -618,4 +610,3 @@ export default class ObjectForm extends React.PureComponent<
|
|
|
618
610
|
);
|
|
619
611
|
}
|
|
620
612
|
}
|
|
621
|
-
|