306 lines
9.2 KiB
Markdown
306 lines
9.2 KiB
Markdown
# InfoPanel 组件
|
||
|
||
## 组件说明
|
||
|
||
信息展示面板组件,用于以网格布局展示数据的字段信息,支持自定义字段渲染和操作按钮。常用于详情页面或抽屉中展示结构化数据。
|
||
|
||
## 组件位置
|
||
|
||
```
|
||
src/components/InfoPanel/InfoPanel.jsx
|
||
src/components/InfoPanel/InfoPanel.css
|
||
```
|
||
|
||
## 参数说明
|
||
|
||
| 参数名 | 类型 | 必填 | 默认值 | 说明 |
|
||
|--------|------|------|--------|------|
|
||
| data | Object | 是 | - | 数据源对象 |
|
||
| fields | Array<FieldConfig> | 否 | [] | 字段配置数组 |
|
||
| actions | Array<ActionConfig> | 否 | [] | 操作按钮配置数组 |
|
||
| gutter | Array<number> | 否 | [24, 16] | Grid 网格间距 [水平, 垂直] |
|
||
|
||
### FieldConfig 配置项
|
||
|
||
| 属性名 | 类型 | 必填 | 说明 |
|
||
|--------|------|------|------|
|
||
| key | string | 是 | 数据字段名 |
|
||
| label | string | 是 | 字段显示标签 |
|
||
| span | number | 否 | 网格占位份数(24栅格系统),默认 6 |
|
||
| render | function(value, data) | 否 | 自定义渲染函数 |
|
||
|
||
### ActionConfig 配置项
|
||
|
||
| 属性名 | 类型 | 必填 | 说明 |
|
||
|--------|------|------|------|
|
||
| key | string | 是 | 按钮唯一标识 |
|
||
| label | string | 是 | 按钮文本 |
|
||
| icon | ReactNode | 否 | 按钮图标 |
|
||
| type | string | 否 | 按钮类型(primary/default/dashed/text/link) |
|
||
| danger | boolean | 否 | 是否为危险按钮 |
|
||
| disabled | boolean | 否 | 是否禁用 |
|
||
| onClick | function | 否 | 点击回调函数 |
|
||
|
||
## 使用示例
|
||
|
||
### 基础用法
|
||
|
||
```jsx
|
||
import InfoPanel from '../components/InfoPanel/InfoPanel'
|
||
|
||
function UserDetail() {
|
||
const userData = {
|
||
userName: 'admin',
|
||
name: '系统管理员',
|
||
group: '管理员组',
|
||
userType: '管理员',
|
||
status: 'enabled',
|
||
grantedTerminals: 8,
|
||
grantedImages: 21,
|
||
}
|
||
|
||
const userFields = [
|
||
{ key: 'userName', label: '用户名', span: 6 },
|
||
{ key: 'name', label: '姓名', span: 6 },
|
||
{ key: 'group', label: '用户分组', span: 6 },
|
||
{ key: 'userType', label: '用户类型', span: 6 },
|
||
{ key: 'grantedTerminals', label: '授权终端', span: 6 },
|
||
{ key: 'grantedImages', label: '授权镜像', span: 6 },
|
||
]
|
||
|
||
return <InfoPanel data={userData} fields={userFields} />
|
||
}
|
||
```
|
||
|
||
### 自定义字段渲染
|
||
|
||
```jsx
|
||
import { Tag } from 'antd'
|
||
|
||
const userFields = [
|
||
{ key: 'userName', label: '用户名', span: 6 },
|
||
{ key: 'name', label: '姓名', span: 6 },
|
||
{
|
||
key: 'status',
|
||
label: '状态',
|
||
span: 6,
|
||
render: (value) => (
|
||
<Tag color={value === 'enabled' ? 'green' : 'default'}>
|
||
{value === 'enabled' ? '启用' : '停用'}
|
||
</Tag>
|
||
),
|
||
},
|
||
{
|
||
key: 'description',
|
||
label: '描述',
|
||
span: 18,
|
||
render: (value) => value || '--', // 空值显示默认占位符
|
||
},
|
||
]
|
||
|
||
<InfoPanel data={userData} fields={userFields} />
|
||
```
|
||
|
||
### 带操作按钮
|
||
|
||
```jsx
|
||
import { LockOutlined } from '@ant-design/icons'
|
||
|
||
<InfoPanel
|
||
data={userData}
|
||
fields={userFields}
|
||
actions={[
|
||
{
|
||
key: 'move',
|
||
label: '转移分组',
|
||
type: 'primary',
|
||
onClick: () => console.log('转移分组'),
|
||
},
|
||
{
|
||
key: 'blacklist',
|
||
label: '加入黑名单',
|
||
onClick: () => console.log('加入黑名单'),
|
||
},
|
||
{
|
||
key: 'reset',
|
||
label: '重置密码',
|
||
onClick: () => console.log('重置密码'),
|
||
},
|
||
{
|
||
key: 'disable',
|
||
label: '停用',
|
||
icon: <LockOutlined />,
|
||
onClick: () => console.log('停用'),
|
||
},
|
||
]}
|
||
/>
|
||
```
|
||
|
||
### 配合 DetailDrawer 使用
|
||
|
||
```jsx
|
||
import DetailDrawer from '../components/DetailDrawer/DetailDrawer'
|
||
import InfoPanel from '../components/InfoPanel/InfoPanel'
|
||
import { Tag } from 'antd'
|
||
|
||
function UserListPage() {
|
||
const [showDetailDrawer, setShowDetailDrawer] = useState(false)
|
||
const [selectedUser, setSelectedUser] = useState(null)
|
||
|
||
const userFields = [
|
||
{ key: 'userName', label: '用户名', span: 6 },
|
||
{ key: 'group', label: '用户分组', span: 6 },
|
||
{ key: 'name', label: '姓名', span: 6 },
|
||
{ key: 'grantedImages', label: '授权镜像', span: 6 },
|
||
{ key: 'userType', label: '用户类型', span: 6 },
|
||
{ key: 'grantedTerminals', label: '授权终端', span: 6 },
|
||
{
|
||
key: 'status',
|
||
label: '启停用',
|
||
span: 6,
|
||
render: (value) => (
|
||
<Tag color={value === 'enabled' ? 'green' : 'default'}>
|
||
{value === 'enabled' ? '启用' : '停用'}
|
||
</Tag>
|
||
),
|
||
},
|
||
{ key: 'description', label: '描述', span: 18, render: () => '--' },
|
||
]
|
||
|
||
return (
|
||
<DetailDrawer
|
||
visible={showDetailDrawer}
|
||
onClose={() => setShowDetailDrawer(false)}
|
||
title={{
|
||
text: selectedUser?.userName || '',
|
||
}}
|
||
>
|
||
<InfoPanel
|
||
data={selectedUser}
|
||
fields={userFields}
|
||
actions={[
|
||
{ key: 'move', label: '转移分组', type: 'primary', onClick: () => console.log('转移分组') },
|
||
{ key: 'blacklist', label: '加入黑名单', onClick: () => console.log('加入黑名单') },
|
||
{ key: 'reset', label: '重置密码', onClick: () => console.log('重置密码') },
|
||
{ key: 'disable', label: '停用', onClick: () => console.log('停用') },
|
||
]}
|
||
/>
|
||
</DetailDrawer>
|
||
)
|
||
}
|
||
```
|
||
|
||
### 不同 span 值的布局
|
||
|
||
```jsx
|
||
// 24栅格系统,一行总共24份
|
||
const fields = [
|
||
{ key: 'field1', label: '字段1', span: 6 }, // 占1/4宽度
|
||
{ key: 'field2', label: '字段2', span: 6 }, // 占1/4宽度
|
||
{ key: 'field3', label: '字段3', span: 6 }, // 占1/4宽度
|
||
{ key: 'field4', label: '字段4', span: 6 }, // 占1/4宽度,满一行
|
||
{ key: 'field5', label: '字段5', span: 8 }, // 占1/3宽度
|
||
{ key: 'field6', label: '字段6', span: 8 }, // 占1/3宽度
|
||
{ key: 'field7', label: '字段7', span: 8 }, // 占1/3宽度,满一行
|
||
{ key: 'field8', label: '字段8', span: 12 }, // 占1/2宽度
|
||
{ key: 'field9', label: '字段9', span: 12 }, // 占1/2宽度,满一行
|
||
{ key: 'description', label: '描述', span: 24 }, // 占满整行
|
||
]
|
||
|
||
<InfoPanel data={data} fields={fields} />
|
||
```
|
||
|
||
### 访问完整数据对象
|
||
|
||
```jsx
|
||
const fields = [
|
||
{ key: 'userName', label: '用户名', span: 6 },
|
||
{
|
||
key: 'status',
|
||
label: '状态信息',
|
||
span: 18,
|
||
// render 函数的第二个参数是完整的数据对象
|
||
render: (value, data) => (
|
||
<div>
|
||
<Tag color={value === 'enabled' ? 'green' : 'default'}>
|
||
{value === 'enabled' ? '启用' : '停用'}
|
||
</Tag>
|
||
<span style={{ marginLeft: 8 }}>
|
||
授权终端:{data.grantedTerminals} 台
|
||
</span>
|
||
</div>
|
||
),
|
||
},
|
||
]
|
||
|
||
<InfoPanel data={userData} fields={fields} />
|
||
```
|
||
|
||
### 自定义网格间距
|
||
|
||
```jsx
|
||
// 默认间距 [24, 16]
|
||
<InfoPanel
|
||
data={userData}
|
||
fields={userFields}
|
||
gutter={[32, 24]} // 更大的间距
|
||
/>
|
||
|
||
// 紧凑布局
|
||
<InfoPanel
|
||
data={userData}
|
||
fields={userFields}
|
||
gutter={[16, 12]} // 更小的间距
|
||
/>
|
||
```
|
||
|
||
## 布局说明
|
||
|
||
组件使用 Ant Design 的 24 栅格系统:
|
||
|
||
```
|
||
┌─────────────────────────────────────────────────┐
|
||
│ span=6 span=6 span=6 span=6 │ 一行4列
|
||
├─────────────────────────────────────────────────┤
|
||
│ span=8 span=8 span=8 │ 一行3列
|
||
├─────────────────────────────────────────────────┤
|
||
│ span=12 span=12 │ 一行2列
|
||
├─────────────────────────────────────────────────┤
|
||
│ span=24 │ 占满一行
|
||
└─────────────────────────────────────────────────┘
|
||
```
|
||
|
||
常用 span 值:
|
||
- `span=6` - 一行 4 列
|
||
- `span=8` - 一行 3 列
|
||
- `span=12` - 一行 2 列
|
||
- `span=24` - 占满整行(适合描述、备注等长文本字段)
|
||
|
||
## 样式定制
|
||
|
||
组件提供以下 CSS 类名供自定义样式:
|
||
|
||
- `.info-panel` - 组件根容器
|
||
- `.info-panel-item` - 单个字段容器
|
||
- `.info-panel-label` - 字段标签
|
||
- `.info-panel-value` - 字段值
|
||
- `.info-panel-actions` - 操作按钮区域
|
||
|
||
## 使用场景
|
||
|
||
1. **详情页信息展示** - 在详情抽屉或页面中展示对象的属性信息
|
||
2. **用户信息展示** - 展示用户的基本信息和状态
|
||
3. **设备信息展示** - 展示设备的配置和参数
|
||
4. **订单信息展示** - 展示订单的详细信息
|
||
5. **任何结构化数据展示** - 以标签-值形式展示的数据
|
||
|
||
## 注意事项
|
||
|
||
1. `data` 为 `null` 或 `undefined` 时组件不渲染任何内容
|
||
2. 字段 `span` 值总和建议为 24 的倍数以保持布局整齐
|
||
3. 长文本字段(如描述、备注)建议使用 `span=24` 或 `span=18`
|
||
4. `render` 函数可以返回任何 React 节点,包括组件、文本、HTML 等
|
||
5. 操作按钮会显示在所有字段下方,建议不超过 6 个按钮
|
||
6. 使用 `render` 函数时,第一个参数是字段值,第二个参数是完整数据对象
|
||
7. 网格间距 `gutter` 的第一个值是水平间距,第二个值是垂直间距
|