@ucloud-fe/udesign-cli 0.1.4 → 0.2.0
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/package.json +1 -1
- package/skills/cpn-basic-box/SKILL.md +40 -2
- package/skills/cpn-basic-breadcrumb/SKILL.md +17 -2
- package/skills/cpn-basic-button/SKILL.md +64 -2
- package/skills/cpn-basic-card/SKILL.md +34 -2
- package/skills/cpn-basic-checkbox/SKILL.md +20 -2
- package/skills/cpn-basic-combine/SKILL.md +27 -2
- package/skills/cpn-basic-date-picker/SKILL.md +21 -2
- package/skills/cpn-basic-editable-table/SKILL.md +6 -2
- package/skills/cpn-basic-icon/SKILL.md +10 -2
- package/skills/cpn-basic-input/SKILL.md +39 -2
- package/skills/cpn-basic-loading/SKILL.md +41 -2
- package/skills/cpn-basic-message/SKILL.md +48 -2
- package/skills/cpn-basic-modal/SKILL.md +73 -2
- package/skills/cpn-basic-notice/SKILL.md +45 -2
- package/skills/cpn-basic-number-input/SKILL.md +42 -2
- package/skills/cpn-basic-popover/SKILL.md +30 -2
- package/skills/cpn-basic-radio/SKILL.md +40 -2
- package/skills/cpn-basic-select/SKILL.md +46 -2
- package/skills/cpn-basic-slider/SKILL.md +45 -2
- package/skills/cpn-basic-switch/SKILL.md +37 -2
- package/skills/cpn-basic-table/SKILL.md +48 -2
- package/skills/cpn-basic-tabs/SKILL.md +46 -2
- package/skills/cpn-basic-tag/SKILL.md +37 -2
- package/skills/cpn-basic-textarea/SKILL.md +40 -2
- package/skills/cpn-basic-tooltip/SKILL.md +39 -2
- package/skills/cpn-basic-tree/SKILL.md +40 -2
|
@@ -219,13 +219,56 @@ class Demo extends React.Component {
|
|
|
219
219
|
<!-- MANUAL_START: best-practices -->
|
|
220
220
|
## 最佳实践
|
|
221
221
|
|
|
222
|
-
|
|
222
|
+
1. **根据语义选择 styleType**:成功用 success、警告用 warning、错误用 error
|
|
223
|
+
2. **重要提示设置 closable={false}**:不可忽略的提示禁止关闭
|
|
224
|
+
3. **Modal 中常配合 Notice**:在弹窗中使用 Notice 提供额外提示信息
|
|
225
|
+
4. **区分 Notice 和 Message**:Notice 是嵌入式静态提示,Message 是全局弹出式提示
|
|
226
|
+
|
|
227
|
+
### 常见场景
|
|
228
|
+
|
|
229
|
+
#### 页面顶部提示
|
|
230
|
+
|
|
231
|
+
```jsx
|
|
232
|
+
<Notice styleType="warning" closable={false}>
|
|
233
|
+
当前地域资源配额即将用完,请及时清理或申请扩容。
|
|
234
|
+
</Notice>
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
#### Modal 中的提示
|
|
238
|
+
|
|
239
|
+
```jsx
|
|
240
|
+
<Modal visible={visible} title="删除资源" onClose={handleClose}>
|
|
241
|
+
<Notice styleType="error" closable={false}>
|
|
242
|
+
删除操作不可撤销,请谨慎操作。
|
|
243
|
+
</Notice>
|
|
244
|
+
<Modal.Content>
|
|
245
|
+
确定要删除该资源吗?
|
|
246
|
+
</Modal.Content>
|
|
247
|
+
</Modal>
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
#### 带操作的提示
|
|
251
|
+
|
|
252
|
+
```jsx
|
|
253
|
+
<Notice
|
|
254
|
+
styleType="warning"
|
|
255
|
+
action={<Button size="sm" onClick={handleRenew}>立即续费</Button>}
|
|
256
|
+
>
|
|
257
|
+
您的资源将于 3 天后到期
|
|
258
|
+
</Notice>
|
|
259
|
+
```
|
|
223
260
|
<!-- MANUAL_END: best-practices -->
|
|
224
261
|
|
|
225
262
|
<!-- MANUAL_START: faq -->
|
|
226
263
|
## 常见问题
|
|
227
264
|
|
|
228
|
-
|
|
265
|
+
### Q: Notice 和 Message 的区别?
|
|
266
|
+
|
|
267
|
+
A: Notice 是嵌入在页面中的静态提示组件,不会自动消失;Message 是全局弹出的消息提示,会自动消失。
|
|
268
|
+
|
|
269
|
+
### Q: 如何隐藏前置图标?
|
|
270
|
+
|
|
271
|
+
A: 将 `icon` 设为 `null` 或 `false`:`<Notice icon={null}>内容</Notice>`。
|
|
229
272
|
<!-- MANUAL_END: faq -->
|
|
230
273
|
|
|
231
274
|
<!-- MANUAL_START: critical -->
|
|
@@ -549,13 +549,53 @@ class Demo extends React.Component {
|
|
|
549
549
|
<!-- MANUAL_START: best-practices -->
|
|
550
550
|
## 最佳实践
|
|
551
551
|
|
|
552
|
-
|
|
552
|
+
1. **设置合理的 min/max**:限制输入范围防止非法值
|
|
553
|
+
2. **使用 onNumberChange 而非 onChange**:`onNumberChange` 只在有效值变化时触发,避免中间态
|
|
554
|
+
3. **formatter 和 parser 配对使用**:格式化显示时需要同时提供 parser 解析输入
|
|
555
|
+
4. **使用 suffix 添加单位**:比 formatter 更简单的方式添加单位后缀
|
|
556
|
+
|
|
557
|
+
### 常见场景
|
|
558
|
+
|
|
559
|
+
#### 资源数量选择
|
|
560
|
+
|
|
561
|
+
```jsx
|
|
562
|
+
<Form.Item label="实例数量">
|
|
563
|
+
<NumberInput
|
|
564
|
+
value={instanceCount}
|
|
565
|
+
onChange={setInstanceCount}
|
|
566
|
+
min={1}
|
|
567
|
+
max={100}
|
|
568
|
+
step={1}
|
|
569
|
+
/>
|
|
570
|
+
</Form.Item>
|
|
571
|
+
```
|
|
572
|
+
|
|
573
|
+
#### 带单位的数值输入
|
|
574
|
+
|
|
575
|
+
```jsx
|
|
576
|
+
<Form.Item label="磁盘大小">
|
|
577
|
+
<NumberInput
|
|
578
|
+
value={diskSize}
|
|
579
|
+
onChange={setDiskSize}
|
|
580
|
+
min={10}
|
|
581
|
+
max={32000}
|
|
582
|
+
step={10}
|
|
583
|
+
suffix="GB"
|
|
584
|
+
/>
|
|
585
|
+
</Form.Item>
|
|
586
|
+
```
|
|
553
587
|
<!-- MANUAL_END: best-practices -->
|
|
554
588
|
|
|
555
589
|
<!-- MANUAL_START: faq -->
|
|
556
590
|
## 常见问题
|
|
557
591
|
|
|
558
|
-
|
|
592
|
+
### Q: onChange 和 onNumberChange 的区别?
|
|
593
|
+
|
|
594
|
+
A: `onChange` 在每次输入时都会触发(包括输入中间态),`onNumberChange` 只在有效数字确定时触发(按钮点击、回车、失焦)。
|
|
595
|
+
|
|
596
|
+
### Q: 如何自定义合法值的计算方式?
|
|
597
|
+
|
|
598
|
+
A: 使用 `computeValidNumber` 属性,传入一个函数接收当前数值和选项,返回合法的数值。
|
|
559
599
|
<!-- MANUAL_END: faq -->
|
|
560
600
|
|
|
561
601
|
<!-- MANUAL_START: critical -->
|
|
@@ -486,13 +486,41 @@ const Demo = () => (
|
|
|
486
486
|
<!-- MANUAL_START: best-practices -->
|
|
487
487
|
## 最佳实践
|
|
488
488
|
|
|
489
|
-
|
|
489
|
+
1. **children 必须是 React 元素**:Popover 需要获取子元素的 ref,文本节点不可用
|
|
490
|
+
2. **overflow 容器内使用 forwardPopupContainer**:避免弹出层被裁剪
|
|
491
|
+
3. **click 触发时注意关闭时机**:可能需要受控模式手动管理 visible
|
|
492
|
+
4. **默认容器为 body**:如需在特定容器内弹出,使用 getPopupContainer
|
|
493
|
+
|
|
494
|
+
### 常见场景
|
|
495
|
+
|
|
496
|
+
#### 自定义操作菜单
|
|
497
|
+
|
|
498
|
+
```jsx
|
|
499
|
+
<Popover
|
|
500
|
+
trigger={['click']}
|
|
501
|
+
placement="bottomLeft"
|
|
502
|
+
popup={
|
|
503
|
+
<div>
|
|
504
|
+
<div onClick={handleEdit}>编辑</div>
|
|
505
|
+
<div onClick={handleDelete}>删除</div>
|
|
506
|
+
</div>
|
|
507
|
+
}
|
|
508
|
+
>
|
|
509
|
+
<Button icon="more" />
|
|
510
|
+
</Popover>
|
|
511
|
+
```
|
|
490
512
|
<!-- MANUAL_END: best-practices -->
|
|
491
513
|
|
|
492
514
|
<!-- MANUAL_START: faq -->
|
|
493
515
|
## 常见问题
|
|
494
516
|
|
|
495
|
-
|
|
517
|
+
### Q: 弹出层被裁剪或位置偏移?
|
|
518
|
+
|
|
519
|
+
A: 通常是因为父容器有 `overflow: hidden` 或 `overflow: auto`。使用 `forwardPopupContainer` 自动查找安全容器,或使用 `getPopupContainer` 手动指定。
|
|
520
|
+
|
|
521
|
+
### Q: Popover 中使用表单元素无法聚焦?
|
|
522
|
+
|
|
523
|
+
A: 检查 trigger 是否包含 `focus`,可能导致 focus 事件冲突。建议使用 `click` 触发。
|
|
496
524
|
<!-- MANUAL_END: faq -->
|
|
497
525
|
|
|
498
526
|
<!-- MANUAL_START: critical -->
|
|
@@ -284,13 +284,51 @@ class Demo extends React.Component {
|
|
|
284
284
|
<!-- MANUAL_START: best-practices -->
|
|
285
285
|
## 最佳实践
|
|
286
286
|
|
|
287
|
-
|
|
287
|
+
1. **使用 Radio.Group 管理**:避免单独使用 Radio 管理状态
|
|
288
|
+
2. **使用 options 快速配置**:简单选项直接使用 options 数组
|
|
289
|
+
3. **根据场景选择 styleType**:表单切换用 button、地域选择用 card
|
|
290
|
+
4. **button 样式禁用注意 Tooltip**:需要用 fakeDisabled 处理
|
|
291
|
+
|
|
292
|
+
### 常见场景
|
|
293
|
+
|
|
294
|
+
#### 表单中的单选
|
|
295
|
+
|
|
296
|
+
```jsx
|
|
297
|
+
<Form.Item label="付费方式">
|
|
298
|
+
<Radio.Group
|
|
299
|
+
value={payType}
|
|
300
|
+
onChange={setPayType}
|
|
301
|
+
styleType="button"
|
|
302
|
+
options={[
|
|
303
|
+
{ label: '按月', value: 'monthly' },
|
|
304
|
+
{ label: '按年', value: 'yearly' },
|
|
305
|
+
{ label: '按需', value: 'demand' }
|
|
306
|
+
]}
|
|
307
|
+
/>
|
|
308
|
+
</Form.Item>
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
#### 卡片选择
|
|
312
|
+
|
|
313
|
+
```jsx
|
|
314
|
+
<Radio.Group value={region} onChange={setRegion} styleType="card">
|
|
315
|
+
<Radio value="cn-bj2" title="北京二">华北地域</Radio>
|
|
316
|
+
<Radio value="cn-sh2" title="上海二">华东地域</Radio>
|
|
317
|
+
<Radio value="cn-gd" title="广州">华南地域</Radio>
|
|
318
|
+
</Radio.Group>
|
|
319
|
+
```
|
|
288
320
|
<!-- MANUAL_END: best-practices -->
|
|
289
321
|
|
|
290
322
|
<!-- MANUAL_START: faq -->
|
|
291
323
|
## 常见问题
|
|
292
324
|
|
|
293
|
-
|
|
325
|
+
### Q: Radio.Group 的 onChange 返回什么?
|
|
326
|
+
|
|
327
|
+
A: 返回当前选中的 Radio 的 `value` 值。
|
|
328
|
+
|
|
329
|
+
### Q: styleType 为 card 时如何显示标题?
|
|
330
|
+
|
|
331
|
+
A: 使用 Radio 的 `title` 属性:`<Radio value="a" title="标题">描述内容</Radio>`。
|
|
294
332
|
<!-- MANUAL_END: faq -->
|
|
295
333
|
|
|
296
334
|
<!-- MANUAL_START: critical -->
|
|
@@ -1225,13 +1225,57 @@ class Demo extends React.Component {
|
|
|
1225
1225
|
<!-- MANUAL_START: best-practices -->
|
|
1226
1226
|
## 最佳实践
|
|
1227
1227
|
|
|
1228
|
-
|
|
1228
|
+
1. **优先使用 options 属性**:比 children 方式性能更好,且支持虚拟列表
|
|
1229
|
+
2. **大量选项启用 virtualList**:选项超过 100 条时建议启用
|
|
1230
|
+
3. **多选默认可清空**:多选模式下 clearable 自动启用
|
|
1231
|
+
4. **搜索时建议自定义 handleSearch**:默认搜索为模糊匹配,如需精确匹配可自定义
|
|
1232
|
+
|
|
1233
|
+
### 常见场景
|
|
1234
|
+
|
|
1235
|
+
#### 表单中的下拉选择
|
|
1236
|
+
|
|
1237
|
+
```jsx
|
|
1238
|
+
<Form.Item label="地域" required>
|
|
1239
|
+
<Select
|
|
1240
|
+
value={region}
|
|
1241
|
+
onChange={setRegion}
|
|
1242
|
+
placeholder="请选择地域"
|
|
1243
|
+
options={regionOptions}
|
|
1244
|
+
/>
|
|
1245
|
+
</Form.Item>
|
|
1246
|
+
```
|
|
1247
|
+
|
|
1248
|
+
#### 带搜索的多选
|
|
1249
|
+
|
|
1250
|
+
```jsx
|
|
1251
|
+
<Form.Item label="标签">
|
|
1252
|
+
<Select
|
|
1253
|
+
multiple
|
|
1254
|
+
search
|
|
1255
|
+
showSelectAll
|
|
1256
|
+
value={tags}
|
|
1257
|
+
onChange={setTags}
|
|
1258
|
+
options={tagOptions}
|
|
1259
|
+
placeholder="请选择标签"
|
|
1260
|
+
/>
|
|
1261
|
+
</Form.Item>
|
|
1262
|
+
```
|
|
1229
1263
|
<!-- MANUAL_END: best-practices -->
|
|
1230
1264
|
|
|
1231
1265
|
<!-- MANUAL_START: faq -->
|
|
1232
1266
|
## 常见问题
|
|
1233
1267
|
|
|
1234
|
-
|
|
1268
|
+
### Q: 单选清空后 onChange 回调的值是什么?
|
|
1269
|
+
|
|
1270
|
+
A: 清空时回调值为 `undefined`。
|
|
1271
|
+
|
|
1272
|
+
### Q: virtualList 为什么不生效?
|
|
1273
|
+
|
|
1274
|
+
A: 虚拟列表仅在使用 `options` 属性时生效,children 方式不支持。
|
|
1275
|
+
|
|
1276
|
+
### Q: 弹出层位置偏移?
|
|
1277
|
+
|
|
1278
|
+
A: 默认使用 `forwardPopupContainer` 自动查找安全容器。如仍有问题,使用 `popoverProps.getPopupContainer` 手动指定。
|
|
1235
1279
|
<!-- MANUAL_END: faq -->
|
|
1236
1280
|
|
|
1237
1281
|
<!-- MANUAL_START: critical -->
|
|
@@ -558,13 +558,56 @@ class Demo extends React.Component {
|
|
|
558
558
|
<!-- MANUAL_START: best-practices -->
|
|
559
559
|
## 最佳实践
|
|
560
560
|
|
|
561
|
-
|
|
561
|
+
1. **设置合理的 min/max/step**:确保 (max - min) 是 step 的整数倍
|
|
562
|
+
2. **使用 marks 标记关键值**:帮助用户理解值的含义
|
|
563
|
+
3. **使用 onLastChange 处理异步操作**:避免拖拽过程中频繁触发请求
|
|
564
|
+
4. **资源配置建议添加单位**:通过 numberInput.suffix 和 tipFormatter 展示单位
|
|
565
|
+
|
|
566
|
+
### 常见场景
|
|
567
|
+
|
|
568
|
+
#### 资源配置选择
|
|
569
|
+
|
|
570
|
+
```jsx
|
|
571
|
+
<Form.Item label="CPU 核数">
|
|
572
|
+
<Slider
|
|
573
|
+
value={cpuCount}
|
|
574
|
+
onChange={setCpuCount}
|
|
575
|
+
min={1}
|
|
576
|
+
max={64}
|
|
577
|
+
step={1}
|
|
578
|
+
marks={{ 1: '1', 8: '8', 16: '16', 32: '32', 64: '64' }}
|
|
579
|
+
numberInput={{ suffix: '核' }}
|
|
580
|
+
/>
|
|
581
|
+
</Form.Item>
|
|
582
|
+
```
|
|
583
|
+
|
|
584
|
+
#### 带宽选择
|
|
585
|
+
|
|
586
|
+
```jsx
|
|
587
|
+
<Form.Item label="带宽">
|
|
588
|
+
<Slider
|
|
589
|
+
value={bandwidth}
|
|
590
|
+
onChange={setBandwidth}
|
|
591
|
+
min={1}
|
|
592
|
+
max={200}
|
|
593
|
+
step={1}
|
|
594
|
+
numberInput={{ suffix: 'Mbps' }}
|
|
595
|
+
tipFormatter={value => `${value} Mbps`}
|
|
596
|
+
/>
|
|
597
|
+
</Form.Item>
|
|
598
|
+
```
|
|
562
599
|
<!-- MANUAL_END: best-practices -->
|
|
563
600
|
|
|
564
601
|
<!-- MANUAL_START: faq -->
|
|
565
602
|
## 常见问题
|
|
566
603
|
|
|
567
|
-
|
|
604
|
+
### Q: range 模式下 numberInput 为什么不显示?
|
|
605
|
+
|
|
606
|
+
A: numberInput 仅在 range 为 false 时生效。range 模式不支持 NumberInput。
|
|
607
|
+
|
|
608
|
+
### Q: step 设置后为什么报错?
|
|
609
|
+
|
|
610
|
+
A: 确保 (max - min) 是 step 的整数倍,且 step 大于 0。
|
|
568
611
|
<!-- MANUAL_END: faq -->
|
|
569
612
|
|
|
570
613
|
<!-- MANUAL_START: critical -->
|
|
@@ -289,13 +289,48 @@ class Demo extends React.Component {
|
|
|
289
289
|
<!-- MANUAL_START: best-practices -->
|
|
290
290
|
## 最佳实践
|
|
291
291
|
|
|
292
|
-
|
|
292
|
+
1. **明确语义**:使用 onText/offText 让用户清楚开关的含义
|
|
293
|
+
2. **即时生效的操作使用 Switch**:切换后立即生效的场景适合用 Switch
|
|
294
|
+
3. **表单提交使用 Checkbox**:需要表单提交才生效的场景更适合用 Checkbox
|
|
295
|
+
|
|
296
|
+
### 常见场景
|
|
297
|
+
|
|
298
|
+
#### 表单中的开关
|
|
299
|
+
|
|
300
|
+
```jsx
|
|
301
|
+
<Form.Item label="自动续费">
|
|
302
|
+
<Switch
|
|
303
|
+
checked={autoRenew}
|
|
304
|
+
onChange={setAutoRenew}
|
|
305
|
+
onText="是"
|
|
306
|
+
offText="否"
|
|
307
|
+
/>
|
|
308
|
+
</Form.Item>
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
#### 功能开关
|
|
312
|
+
|
|
313
|
+
```jsx
|
|
314
|
+
<Form.Item label="启用监控">
|
|
315
|
+
<Switch
|
|
316
|
+
checked={monitorEnabled}
|
|
317
|
+
onChange={enabled => {
|
|
318
|
+
setMonitorEnabled(enabled);
|
|
319
|
+
if (enabled) {
|
|
320
|
+
Message.success('监控已开启');
|
|
321
|
+
}
|
|
322
|
+
}}
|
|
323
|
+
/>
|
|
324
|
+
</Form.Item>
|
|
325
|
+
```
|
|
293
326
|
<!-- MANUAL_END: best-practices -->
|
|
294
327
|
|
|
295
328
|
<!-- MANUAL_START: faq -->
|
|
296
329
|
## 常见问题
|
|
297
330
|
|
|
298
|
-
|
|
331
|
+
### Q: Switch 和 Checkbox 的使用场景区别?
|
|
332
|
+
|
|
333
|
+
A: Switch 适用于切换后立即生效的场景(如开启/关闭功能),Checkbox 适用于需要表单提交后才生效的场景(如同意协议)。
|
|
299
334
|
<!-- MANUAL_END: faq -->
|
|
300
335
|
|
|
301
336
|
<!-- MANUAL_START: critical -->
|
|
@@ -2931,13 +2931,59 @@ class Demo extends React.Component {
|
|
|
2931
2931
|
<!-- MANUAL_START: best-practices -->
|
|
2932
2932
|
## 最佳实践
|
|
2933
2933
|
|
|
2934
|
-
|
|
2934
|
+
1. **务必设置 rowKey 或保证数据有 key**:避免使用 index 作为 key
|
|
2935
|
+
2. **大数据量使用服务端分页**:配合 `doNotHandleCondition` 和 `onConditionChange`
|
|
2936
|
+
3. **固定列时设置列宽**:使用 `fixed` 时需要给列设置 `width`
|
|
2937
|
+
4. **Loading 包裹 Table**:使用 Loading 组件展示加载状态
|
|
2938
|
+
|
|
2939
|
+
### 常见场景
|
|
2940
|
+
|
|
2941
|
+
#### 资源列表页
|
|
2942
|
+
|
|
2943
|
+
```jsx
|
|
2944
|
+
const [loading, setLoading] = useState(true);
|
|
2945
|
+
const [dataSource, setDataSource] = useState([]);
|
|
2946
|
+
const [selectedRowKeys, setSelectedRowKeys] = useState([]);
|
|
2947
|
+
const [page, setPage] = useState(1);
|
|
2948
|
+
|
|
2949
|
+
<Loading loading={loading}>
|
|
2950
|
+
<Table
|
|
2951
|
+
rowKey="resourceId"
|
|
2952
|
+
columns={columns}
|
|
2953
|
+
dataSource={dataSource}
|
|
2954
|
+
rowSelection={{
|
|
2955
|
+
selectedRowKeys,
|
|
2956
|
+
onChange: setSelectedRowKeys
|
|
2957
|
+
}}
|
|
2958
|
+
pagination={{
|
|
2959
|
+
current: page,
|
|
2960
|
+
pageSize: 10,
|
|
2961
|
+
total,
|
|
2962
|
+
onChange: setPage
|
|
2963
|
+
}}
|
|
2964
|
+
contextMenu={record => [
|
|
2965
|
+
{ label: '编辑', onClick: () => handleEdit(record) },
|
|
2966
|
+
{ label: '删除', onClick: () => handleDelete(record) }
|
|
2967
|
+
]}
|
|
2968
|
+
/>
|
|
2969
|
+
</Loading>
|
|
2970
|
+
```
|
|
2935
2971
|
<!-- MANUAL_END: best-practices -->
|
|
2936
2972
|
|
|
2937
2973
|
<!-- MANUAL_START: faq -->
|
|
2938
2974
|
## 常见问题
|
|
2939
2975
|
|
|
2940
|
-
|
|
2976
|
+
### Q: 表格数据异常、行错乱?
|
|
2977
|
+
|
|
2978
|
+
A: 检查 key 是否唯一。务必使用 `rowKey` 指定唯一标识字段,不要依赖 index。
|
|
2979
|
+
|
|
2980
|
+
### Q: 如何实现后端分页?
|
|
2981
|
+
|
|
2982
|
+
A: 设置 `doNotHandleCondition`,在 `onConditionChange` 和 `pagination.onChange` 中请求后端数据。
|
|
2983
|
+
|
|
2984
|
+
### Q: 固定列后横向无法滚动?
|
|
2985
|
+
|
|
2986
|
+
A: 检查是否设置了 `scroll.x`,且 `scroll.x` 的值需要大于表格容器宽度。
|
|
2941
2987
|
<!-- MANUAL_END: faq -->
|
|
2942
2988
|
|
|
2943
2989
|
<!-- MANUAL_START: critical -->
|
|
@@ -612,13 +612,57 @@ const Demo = () => {
|
|
|
612
612
|
<!-- MANUAL_START: best-practices -->
|
|
613
613
|
## 最佳实践
|
|
614
614
|
|
|
615
|
-
|
|
615
|
+
1. **Pane 必须有唯一 key**:这是 Tabs 正常工作的前提
|
|
616
|
+
2. **表单 Tab 使用受控模式**:方便校验时切换到有错误的 tab
|
|
617
|
+
3. **按需销毁内容**:大量内容的 Tab 使用 `destroyInactiveTabPane` 减少内存占用
|
|
618
|
+
4. **首次不需要渲染的使用懒加载**:默认非活动 tab 不会渲染,切换到才渲染
|
|
619
|
+
|
|
620
|
+
### 常见场景
|
|
621
|
+
|
|
622
|
+
#### 资源详情页
|
|
623
|
+
|
|
624
|
+
```jsx
|
|
625
|
+
<Tabs defaultActiveKey="overview">
|
|
626
|
+
<Tabs.Pane key="overview" tab="概览">
|
|
627
|
+
<OverviewPanel />
|
|
628
|
+
</Tabs.Pane>
|
|
629
|
+
<Tabs.Pane key="monitor" tab="监控">
|
|
630
|
+
<MonitorPanel />
|
|
631
|
+
</Tabs.Pane>
|
|
632
|
+
<Tabs.Pane key="log" tab="日志">
|
|
633
|
+
<LogPanel />
|
|
634
|
+
</Tabs.Pane>
|
|
635
|
+
</Tabs>
|
|
636
|
+
```
|
|
637
|
+
|
|
638
|
+
#### 配置切换
|
|
639
|
+
|
|
640
|
+
```jsx
|
|
641
|
+
<Tabs
|
|
642
|
+
activeKey={configTab}
|
|
643
|
+
onChange={setConfigTab}
|
|
644
|
+
styleType="ink"
|
|
645
|
+
>
|
|
646
|
+
<Tabs.Pane key="basic" tab="基础配置">
|
|
647
|
+
<BasicConfigForm />
|
|
648
|
+
</Tabs.Pane>
|
|
649
|
+
<Tabs.Pane key="advanced" tab="高级配置">
|
|
650
|
+
<AdvancedConfigForm />
|
|
651
|
+
</Tabs.Pane>
|
|
652
|
+
</Tabs>
|
|
653
|
+
```
|
|
616
654
|
<!-- MANUAL_END: best-practices -->
|
|
617
655
|
|
|
618
656
|
<!-- MANUAL_START: faq -->
|
|
619
657
|
## 常见问题
|
|
620
658
|
|
|
621
|
-
|
|
659
|
+
### Q: key 被 React 修改导致切换失败?
|
|
660
|
+
|
|
661
|
+
A: 在某些情况下 React 会修改 key,可以使用 `tabKey` 属性替代。
|
|
662
|
+
|
|
663
|
+
### Q: Tab 数量多时如何处理?
|
|
664
|
+
|
|
665
|
+
A: 组件内置了滚动功能,当 tab 数量超出容器宽度时会自动显示滚动按钮。
|
|
622
666
|
<!-- MANUAL_END: faq -->
|
|
623
667
|
|
|
624
668
|
<!-- MANUAL_START: critical -->
|
|
@@ -412,13 +412,48 @@ class Demo extends React.Component {
|
|
|
412
412
|
<!-- MANUAL_START: best-practices -->
|
|
413
413
|
## 最佳实践
|
|
414
414
|
|
|
415
|
-
|
|
415
|
+
1. **用颜色表达语义**:绿色表示成功/运行,红色表示错误/异常,黄色表示警告
|
|
416
|
+
2. **使用 icon 增强标识**:配合 `circle-fill` 图标标识状态
|
|
417
|
+
3. **标签列表使用 closable**:可删除的标签场景
|
|
418
|
+
4. **使用 customStyle 扩展颜色**:内置颜色不满足时自定义
|
|
419
|
+
|
|
420
|
+
### 常见场景
|
|
421
|
+
|
|
422
|
+
#### 资源状态标签
|
|
423
|
+
|
|
424
|
+
```jsx
|
|
425
|
+
const statusMap = {
|
|
426
|
+
running: { styleType: 'green', icon: 'circle-fill', text: '运行中' },
|
|
427
|
+
stopped: { styleType: 'gray', icon: 'circle-fill', text: '已停止' },
|
|
428
|
+
error: { styleType: 'red', icon: 'circle-fill', text: '异常' }
|
|
429
|
+
};
|
|
430
|
+
|
|
431
|
+
const { styleType, icon, text } = statusMap[status];
|
|
432
|
+
<Tag styleType={styleType} icon={icon}>{text}</Tag>
|
|
433
|
+
```
|
|
434
|
+
|
|
435
|
+
#### 标签列表
|
|
436
|
+
|
|
437
|
+
```jsx
|
|
438
|
+
{tags.map(tag => (
|
|
439
|
+
<Tag
|
|
440
|
+
key={tag.id}
|
|
441
|
+
closable
|
|
442
|
+
onClose={() => handleRemoveTag(tag.id)}
|
|
443
|
+
styleType="blue"
|
|
444
|
+
>
|
|
445
|
+
{tag.name}
|
|
446
|
+
</Tag>
|
|
447
|
+
))}
|
|
448
|
+
```
|
|
416
449
|
<!-- MANUAL_END: best-practices -->
|
|
417
450
|
|
|
418
451
|
<!-- MANUAL_START: faq -->
|
|
419
452
|
## 常见问题
|
|
420
453
|
|
|
421
|
-
|
|
454
|
+
### Q: 有哪些可用的 styleType?
|
|
455
|
+
|
|
456
|
+
A: 常用的有 `gray`、`green`、`yellow`、`red`、`blue`、`orange`、`purple`、`cyan` 等,以及对应的 `-crisped` 后缀变体。可通过 `Tag.StyleType` 获取完整列表。
|
|
422
457
|
<!-- MANUAL_END: faq -->
|
|
423
458
|
|
|
424
459
|
<!-- MANUAL_START: critical -->
|
|
@@ -124,13 +124,51 @@ class Demo extends React.Component {
|
|
|
124
124
|
<!-- MANUAL_START: best-practices -->
|
|
125
125
|
## 最佳实践
|
|
126
126
|
|
|
127
|
-
|
|
127
|
+
1. **使用 rows 控制初始高度**:通过 `rows` 设置合理的初始显示行数
|
|
128
|
+
2. **设置 maxLength 限制长度**:避免用户输入过长内容
|
|
129
|
+
3. **onChange 返回原生 event**:取值用 `e.target.value`,与 Input 一致
|
|
130
|
+
4. **短文本用 Input**:单行文本输入使用 Input,多行才用 Textarea
|
|
131
|
+
|
|
132
|
+
### 常见场景
|
|
133
|
+
|
|
134
|
+
#### 表单中的描述输入
|
|
135
|
+
|
|
136
|
+
```jsx
|
|
137
|
+
<Form.Item label="描述">
|
|
138
|
+
<Textarea
|
|
139
|
+
value={description}
|
|
140
|
+
onChange={e => setDescription(e.target.value)}
|
|
141
|
+
placeholder="请输入描述信息"
|
|
142
|
+
rows={4}
|
|
143
|
+
/>
|
|
144
|
+
</Form.Item>
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
#### 备注输入
|
|
148
|
+
|
|
149
|
+
```jsx
|
|
150
|
+
<Form.Item label="备注">
|
|
151
|
+
<Textarea
|
|
152
|
+
value={remark}
|
|
153
|
+
onChange={e => setRemark(e.target.value)}
|
|
154
|
+
placeholder="请输入备注(选填)"
|
|
155
|
+
rows={3}
|
|
156
|
+
maxLength={500}
|
|
157
|
+
/>
|
|
158
|
+
</Form.Item>
|
|
159
|
+
```
|
|
128
160
|
<!-- MANUAL_END: best-practices -->
|
|
129
161
|
|
|
130
162
|
<!-- MANUAL_START: faq -->
|
|
131
163
|
## 常见问题
|
|
132
164
|
|
|
133
|
-
|
|
165
|
+
### Q: 如何固定高度不允许拖拽?
|
|
166
|
+
|
|
167
|
+
A: 设置 `style={{ resize: 'none' }}`。
|
|
168
|
+
|
|
169
|
+
### Q: onChange 的参数是什么?
|
|
170
|
+
|
|
171
|
+
A: 与 Input 一致,接收原生 `ChangeEvent`,通过 `e.target.value` 获取值。
|
|
134
172
|
<!-- MANUAL_END: faq -->
|
|
135
173
|
|
|
136
174
|
<!-- MANUAL_START: critical -->
|
|
@@ -235,13 +235,50 @@ const Demo = () => (
|
|
|
235
235
|
<!-- MANUAL_START: best-practices -->
|
|
236
236
|
## 最佳实践
|
|
237
237
|
|
|
238
|
-
|
|
238
|
+
1. **简短提示用 Tooltip**:复杂内容用 Popover
|
|
239
|
+
2. **暗色主题用于操作提示**:按钮等操作元素的提示建议用 dark 主题
|
|
240
|
+
3. **禁用按钮配合 fakeDisabled**:确保 Tooltip 在禁用按钮上也能正常工作
|
|
241
|
+
4. **popup 为 null 时不渲染**:可以通过传入 null 条件性隐藏 Tooltip
|
|
242
|
+
|
|
243
|
+
### 常见场景
|
|
244
|
+
|
|
245
|
+
#### 按钮操作说明
|
|
246
|
+
|
|
247
|
+
```jsx
|
|
248
|
+
<Tooltip popup="上传文件到服务器">
|
|
249
|
+
<Button icon="upload" shape="circle" />
|
|
250
|
+
</Tooltip>
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
#### 禁用按钮提示(配合 fakeDisabled)
|
|
254
|
+
|
|
255
|
+
```jsx
|
|
256
|
+
<Tooltip popup="该操作暂不可用">
|
|
257
|
+
<Button disabled fakeDisabled>操作</Button>
|
|
258
|
+
</Tooltip>
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
#### 文本截断提示
|
|
262
|
+
|
|
263
|
+
```jsx
|
|
264
|
+
<Tooltip popup={fullText}>
|
|
265
|
+
<span style={{ overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap', maxWidth: 200 }}>
|
|
266
|
+
{fullText}
|
|
267
|
+
</span>
|
|
268
|
+
</Tooltip>
|
|
269
|
+
```
|
|
239
270
|
<!-- MANUAL_END: best-practices -->
|
|
240
271
|
|
|
241
272
|
<!-- MANUAL_START: faq -->
|
|
242
273
|
## 常见问题
|
|
243
274
|
|
|
244
|
-
|
|
275
|
+
### Q: 禁用的按钮无法显示 Tooltip?
|
|
276
|
+
|
|
277
|
+
A: 原生 `disabled` 会屏蔽所有事件。解决方案是同时添加 `disabled` 和 `fakeDisabled`。
|
|
278
|
+
|
|
279
|
+
### Q: Tooltip 位置偏移?
|
|
280
|
+
|
|
281
|
+
A: 参考 Popover 的容器问题,使用 `forwardPopupContainer` 或 `getPopupContainer` 处理。
|
|
245
282
|
<!-- MANUAL_END: faq -->
|
|
246
283
|
|
|
247
284
|
<!-- MANUAL_START: critical -->
|