2025-11-05 06:17:47 +00:00
|
|
|
|
# DetailDrawer 组件
|
|
|
|
|
|
|
|
|
|
|
|
## 组件说明
|
|
|
|
|
|
|
|
|
|
|
|
详情抽屉组件,用于从页面右侧滑出显示详细信息。支持自定义标题、操作按钮、标签页等功能,内容区域可滚动,顶部标题栏固定。
|
|
|
|
|
|
|
|
|
|
|
|
## 组件位置
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
src/components/DetailDrawer/DetailDrawer.jsx
|
|
|
|
|
|
src/components/DetailDrawer/DetailDrawer.css
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
## 参数说明
|
|
|
|
|
|
|
|
|
|
|
|
| 参数名 | 类型 | 必填 | 默认值 | 说明 |
|
|
|
|
|
|
|--------|------|------|--------|------|
|
|
|
|
|
|
| visible | boolean | 是 | - | 是否显示抽屉 |
|
|
|
|
|
|
| onClose | function | 是 | - | 关闭抽屉回调 |
|
|
|
|
|
|
| title | TitleConfig | 否 | - | 标题配置对象 |
|
|
|
|
|
|
| headerActions | Array<ActionConfig> | 否 | [] | 顶部操作按钮数组 |
|
|
|
|
|
|
| width | number | 否 | 1080 | 抽屉宽度(像素) |
|
|
|
|
|
|
| children | ReactNode | 否 | - | 主要内容区域 |
|
|
|
|
|
|
| tabs | Array<TabConfig> | 否 | - | 标签页配置数组 |
|
|
|
|
|
|
|
|
|
|
|
|
### 1. 小型抽屉 (Small) - 480px
|
|
|
|
|
|
**适用场景:**
|
|
|
|
|
|
- 简单的信息展示
|
|
|
|
|
|
- 少量字段的表单(1-3个字段)
|
|
|
|
|
|
- 快速操作面板
|
|
|
|
|
|
- 通知详情
|
|
|
|
|
|
|
|
|
|
|
|
**示例:**
|
|
|
|
|
|
```jsx
|
|
|
|
|
|
<Drawer width={480} ... />
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 2. 中型抽屉 (Medium) - 720px
|
|
|
|
|
|
**适用场景:**
|
|
|
|
|
|
- 详细信息展示(如主机详情)
|
|
|
|
|
|
- 中等复杂度的表单(4-10个字段)
|
|
|
|
|
|
- 数据编辑面板
|
|
|
|
|
|
- 配置设置
|
|
|
|
|
|
|
|
|
|
|
|
**示例:**
|
|
|
|
|
|
```jsx
|
|
|
|
|
|
<Drawer width={720} ... />
|
|
|
|
|
|
```
|
|
|
|
|
|
**当前主机列表页面使用此宽度模式**
|
|
|
|
|
|
|
|
|
|
|
|
### 3. 大型抽屉 (Large) - 1080px
|
|
|
|
|
|
**适用场景:**
|
|
|
|
|
|
- 复杂的多步骤表单
|
|
|
|
|
|
- 需要并排展示多列信息
|
|
|
|
|
|
- 包含图表或复杂可视化内容
|
|
|
|
|
|
- 嵌套子表格或列表
|
|
|
|
|
|
|
|
|
|
|
|
**示例:**
|
|
|
|
|
|
```jsx
|
|
|
|
|
|
<Drawer width={1080} ... />
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### TitleConfig 配置项
|
|
|
|
|
|
|
|
|
|
|
|
| 属性名 | 类型 | 必填 | 说明 |
|
|
|
|
|
|
|--------|------|------|------|
|
|
|
|
|
|
| text | string | 是 | 标题文本 |
|
|
|
|
|
|
| badge | ReactNode | 否 | 状态徽标(如 Tag、Badge 组件) |
|
|
|
|
|
|
| icon | ReactNode | 否 | 标题图标 |
|
|
|
|
|
|
|
|
|
|
|
|
### ActionConfig 配置项
|
|
|
|
|
|
|
|
|
|
|
|
| 属性名 | 类型 | 必填 | 说明 |
|
|
|
|
|
|
|--------|------|------|------|
|
|
|
|
|
|
| key | string | 是 | 按钮唯一标识 |
|
|
|
|
|
|
| label | string | 是 | 按钮文本 |
|
|
|
|
|
|
| icon | ReactNode | 否 | 按钮图标 |
|
|
|
|
|
|
| type | string | 否 | 按钮类型(primary/default/dashed/text/link) |
|
|
|
|
|
|
| danger | boolean | 否 | 是否为危险按钮 |
|
|
|
|
|
|
| disabled | boolean | 否 | 是否禁用 |
|
|
|
|
|
|
| onClick | function | 否 | 点击回调函数 |
|
|
|
|
|
|
|
|
|
|
|
|
### TabConfig 配置项
|
|
|
|
|
|
|
|
|
|
|
|
| 属性名 | 类型 | 必填 | 说明 |
|
|
|
|
|
|
|--------|------|------|------|
|
|
|
|
|
|
| key | string | 是 | 标签页唯一标识 |
|
|
|
|
|
|
| label | ReactNode | 是 | 标签页标题(支持图标+文字) |
|
|
|
|
|
|
| content | ReactNode | 是 | 标签页内容 |
|
|
|
|
|
|
|
|
|
|
|
|
## 使用示例
|
|
|
|
|
|
|
|
|
|
|
|
### 基础用法
|
|
|
|
|
|
|
|
|
|
|
|
```jsx
|
|
|
|
|
|
import { useState } from 'react'
|
|
|
|
|
|
import DetailDrawer from '../components/DetailDrawer/DetailDrawer'
|
|
|
|
|
|
|
|
|
|
|
|
function MyPage() {
|
|
|
|
|
|
const [showDrawer, setShowDrawer] = useState(false)
|
|
|
|
|
|
const [selectedItem, setSelectedItem] = useState(null)
|
|
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
|
<>
|
|
|
|
|
|
<Button onClick={() => setShowDrawer(true)}>查看详情</Button>
|
|
|
|
|
|
|
|
|
|
|
|
<DetailDrawer
|
|
|
|
|
|
visible={showDrawer}
|
|
|
|
|
|
onClose={() => setShowDrawer(false)}
|
|
|
|
|
|
title={{
|
|
|
|
|
|
text: selectedItem?.name || '详情',
|
|
|
|
|
|
}}
|
|
|
|
|
|
>
|
|
|
|
|
|
<div style={{ padding: 24 }}>
|
|
|
|
|
|
<p>详情内容</p>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</DetailDrawer>
|
|
|
|
|
|
</>
|
|
|
|
|
|
)
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 带状态徽标
|
|
|
|
|
|
|
|
|
|
|
|
```jsx
|
|
|
|
|
|
import { Tag, Badge } from 'antd'
|
|
|
|
|
|
|
|
|
|
|
|
<DetailDrawer
|
|
|
|
|
|
visible={showDetailDrawer}
|
|
|
|
|
|
onClose={() => setShowDetailDrawer(false)}
|
|
|
|
|
|
title={{
|
|
|
|
|
|
text: selectedUser?.userName || '',
|
|
|
|
|
|
badge: (
|
|
|
|
|
|
<Tag color={selectedUser?.status === 'enabled' ? 'green' : 'default'}>
|
|
|
|
|
|
{selectedUser?.status === 'enabled' ? '启用' : '停用'}
|
|
|
|
|
|
</Tag>
|
|
|
|
|
|
),
|
|
|
|
|
|
}}
|
|
|
|
|
|
>
|
|
|
|
|
|
{/* 内容 */}
|
|
|
|
|
|
</DetailDrawer>
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 带操作按钮
|
|
|
|
|
|
|
|
|
|
|
|
```jsx
|
|
|
|
|
|
import { EditOutlined, DeleteOutlined } from '@ant-design/icons'
|
|
|
|
|
|
|
|
|
|
|
|
<DetailDrawer
|
|
|
|
|
|
visible={showDetailDrawer}
|
|
|
|
|
|
onClose={() => setShowDetailDrawer(false)}
|
|
|
|
|
|
title={{
|
|
|
|
|
|
text: selectedUser?.userName || '',
|
|
|
|
|
|
}}
|
|
|
|
|
|
headerActions={[
|
|
|
|
|
|
{
|
|
|
|
|
|
key: 'edit',
|
|
|
|
|
|
label: '编辑',
|
|
|
|
|
|
icon: <EditOutlined />,
|
|
|
|
|
|
onClick: () => {
|
|
|
|
|
|
setEditMode('edit')
|
|
|
|
|
|
setShowEditDrawer(true)
|
|
|
|
|
|
setShowDetailDrawer(false)
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
key: 'delete',
|
|
|
|
|
|
label: '删除',
|
|
|
|
|
|
icon: <DeleteOutlined />,
|
|
|
|
|
|
danger: true,
|
|
|
|
|
|
onClick: () => {
|
|
|
|
|
|
setShowDetailDrawer(false)
|
|
|
|
|
|
handleDelete(selectedUser)
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
]}
|
|
|
|
|
|
>
|
|
|
|
|
|
{/* 内容 */}
|
|
|
|
|
|
</DetailDrawer>
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 使用 InfoPanel 显示信息
|
|
|
|
|
|
|
|
|
|
|
|
```jsx
|
|
|
|
|
|
import DetailDrawer from '../components/DetailDrawer/DetailDrawer'
|
|
|
|
|
|
import InfoPanel from '../components/InfoPanel/InfoPanel'
|
|
|
|
|
|
|
|
|
|
|
|
const userFields = [
|
|
|
|
|
|
{ key: 'userName', label: '用户名', span: 6 },
|
|
|
|
|
|
{ key: 'group', label: '用户分组', span: 6 },
|
|
|
|
|
|
{ key: 'name', label: '姓名', span: 6 },
|
|
|
|
|
|
{ key: 'userType', label: '用户类型', span: 6 },
|
|
|
|
|
|
{
|
|
|
|
|
|
key: 'status',
|
|
|
|
|
|
label: '状态',
|
|
|
|
|
|
span: 6,
|
|
|
|
|
|
render: (value) => (
|
|
|
|
|
|
<Tag color={value === 'enabled' ? 'green' : 'default'}>
|
|
|
|
|
|
{value === 'enabled' ? '启用' : '停用'}
|
|
|
|
|
|
</Tag>
|
|
|
|
|
|
),
|
|
|
|
|
|
},
|
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
|
|
<DetailDrawer
|
|
|
|
|
|
visible={showDetailDrawer}
|
|
|
|
|
|
onClose={() => setShowDetailDrawer(false)}
|
|
|
|
|
|
title={{
|
|
|
|
|
|
text: selectedUser?.userName || '',
|
|
|
|
|
|
}}
|
|
|
|
|
|
>
|
|
|
|
|
|
<InfoPanel
|
|
|
|
|
|
data={selectedUser}
|
|
|
|
|
|
fields={userFields}
|
|
|
|
|
|
actions={[
|
|
|
|
|
|
{ key: 'reset', label: '重置密码', onClick: () => console.log('重置密码') },
|
|
|
|
|
|
{ key: 'disable', label: '停用', onClick: () => console.log('停用') },
|
|
|
|
|
|
]}
|
|
|
|
|
|
/>
|
|
|
|
|
|
</DetailDrawer>
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 带标签页
|
|
|
|
|
|
|
|
|
|
|
|
```jsx
|
|
|
|
|
|
import { DatabaseOutlined, UserOutlined } from '@ant-design/icons'
|
|
|
|
|
|
|
|
|
|
|
|
<DetailDrawer
|
|
|
|
|
|
visible={showDetailDrawer}
|
|
|
|
|
|
onClose={() => setShowDetailDrawer(false)}
|
|
|
|
|
|
title={{
|
|
|
|
|
|
text: selectedHost?.name || '',
|
|
|
|
|
|
badge: (
|
|
|
|
|
|
<Badge
|
|
|
|
|
|
status={selectedHost?.status === 'online' ? 'success' : 'default'}
|
|
|
|
|
|
text={selectedHost?.status === 'online' ? '在线' : '离线'}
|
|
|
|
|
|
/>
|
|
|
|
|
|
),
|
|
|
|
|
|
}}
|
|
|
|
|
|
headerActions={[
|
|
|
|
|
|
{
|
|
|
|
|
|
key: 'edit',
|
|
|
|
|
|
label: '编辑',
|
|
|
|
|
|
icon: <EditOutlined />,
|
|
|
|
|
|
onClick: handleEdit,
|
|
|
|
|
|
},
|
|
|
|
|
|
]}
|
|
|
|
|
|
width={1080}
|
|
|
|
|
|
tabs={[
|
|
|
|
|
|
{
|
|
|
|
|
|
key: 'images',
|
|
|
|
|
|
label: (
|
|
|
|
|
|
<span>
|
|
|
|
|
|
<DatabaseOutlined style={{ marginRight: 8 }} />
|
|
|
|
|
|
终端镜像
|
|
|
|
|
|
</span>
|
|
|
|
|
|
),
|
|
|
|
|
|
content: (
|
|
|
|
|
|
<div className="card-list">
|
|
|
|
|
|
{/* 镜像列表内容 */}
|
|
|
|
|
|
</div>
|
|
|
|
|
|
),
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
key: 'users',
|
|
|
|
|
|
label: (
|
|
|
|
|
|
<span>
|
|
|
|
|
|
<UserOutlined style={{ marginRight: 8 }} />
|
|
|
|
|
|
终端用户
|
|
|
|
|
|
</span>
|
|
|
|
|
|
),
|
|
|
|
|
|
content: (
|
|
|
|
|
|
<div className="card-list">
|
|
|
|
|
|
{/* 用户列表内容 */}
|
|
|
|
|
|
</div>
|
|
|
|
|
|
),
|
|
|
|
|
|
},
|
|
|
|
|
|
]}
|
|
|
|
|
|
>
|
|
|
|
|
|
<InfoPanel data={selectedHost} fields={hostFields} />
|
|
|
|
|
|
</DetailDrawer>
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 完整示例
|
|
|
|
|
|
|
|
|
|
|
|
```jsx
|
|
|
|
|
|
import { useState } from 'react'
|
|
|
|
|
|
import DetailDrawer from '../components/DetailDrawer/DetailDrawer'
|
|
|
|
|
|
import InfoPanel from '../components/InfoPanel/InfoPanel'
|
|
|
|
|
|
import { Tag, Badge, Card } from 'antd'
|
|
|
|
|
|
import { EditOutlined, DeleteOutlined, DatabaseOutlined, UserOutlined } from '@ant-design/icons'
|
|
|
|
|
|
|
|
|
|
|
|
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>
|
|
|
|
|
|
),
|
|
|
|
|
|
},
|
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
|
|
const detailTabs = [
|
|
|
|
|
|
{
|
|
|
|
|
|
key: 'terminals',
|
|
|
|
|
|
label: (
|
|
|
|
|
|
<span>
|
|
|
|
|
|
<DesktopOutlined style={{ marginRight: 8 }} />
|
|
|
|
|
|
授权终端
|
|
|
|
|
|
</span>
|
|
|
|
|
|
),
|
|
|
|
|
|
content: (
|
|
|
|
|
|
<div className="card-list">
|
|
|
|
|
|
{selectedUser?.terminals?.map((terminal) => (
|
|
|
|
|
|
<Card key={terminal.id}>
|
|
|
|
|
|
<h4>{terminal.name}</h4>
|
|
|
|
|
|
<p>IP: {terminal.ip}</p>
|
|
|
|
|
|
</Card>
|
|
|
|
|
|
))}
|
|
|
|
|
|
</div>
|
|
|
|
|
|
),
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
key: 'images',
|
|
|
|
|
|
label: (
|
|
|
|
|
|
<span>
|
|
|
|
|
|
<DatabaseOutlined style={{ marginRight: 8 }} />
|
|
|
|
|
|
授权镜像
|
|
|
|
|
|
</span>
|
|
|
|
|
|
),
|
|
|
|
|
|
content: (
|
|
|
|
|
|
<div className="card-list">
|
|
|
|
|
|
{selectedUser?.images?.map((image) => (
|
|
|
|
|
|
<Card key={image.id}>
|
|
|
|
|
|
<h4>{image.name}</h4>
|
|
|
|
|
|
<p>系统: {image.os}</p>
|
|
|
|
|
|
</Card>
|
|
|
|
|
|
))}
|
|
|
|
|
|
</div>
|
|
|
|
|
|
),
|
|
|
|
|
|
},
|
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
|
<>
|
|
|
|
|
|
{/* 列表页面 */}
|
|
|
|
|
|
<ListTable
|
|
|
|
|
|
columns={columns}
|
|
|
|
|
|
dataSource={users}
|
|
|
|
|
|
onRowClick={(record) => {
|
|
|
|
|
|
setSelectedUser(record)
|
|
|
|
|
|
setShowDetailDrawer(true)
|
|
|
|
|
|
}}
|
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
|
|
|
|
{/* 详情抽屉 */}
|
|
|
|
|
|
<DetailDrawer
|
|
|
|
|
|
visible={showDetailDrawer}
|
|
|
|
|
|
onClose={() => setShowDetailDrawer(false)}
|
|
|
|
|
|
title={{
|
|
|
|
|
|
text: selectedUser?.userName || '',
|
|
|
|
|
|
badge: (
|
|
|
|
|
|
<Tag color={selectedUser?.status === 'enabled' ? 'green' : 'default'}>
|
|
|
|
|
|
{selectedUser?.status === 'enabled' ? '启用' : '停用'}
|
|
|
|
|
|
</Tag>
|
|
|
|
|
|
),
|
|
|
|
|
|
}}
|
|
|
|
|
|
headerActions={[
|
|
|
|
|
|
{
|
|
|
|
|
|
key: 'edit',
|
|
|
|
|
|
label: '编辑',
|
|
|
|
|
|
icon: <EditOutlined />,
|
|
|
|
|
|
onClick: () => {
|
|
|
|
|
|
setShowDetailDrawer(false)
|
|
|
|
|
|
handleEdit(selectedUser)
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
key: 'delete',
|
|
|
|
|
|
label: '删除',
|
|
|
|
|
|
icon: <DeleteOutlined />,
|
|
|
|
|
|
danger: true,
|
|
|
|
|
|
onClick: () => {
|
|
|
|
|
|
setShowDetailDrawer(false)
|
|
|
|
|
|
handleDelete(selectedUser)
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
]}
|
|
|
|
|
|
width={1080}
|
|
|
|
|
|
tabs={detailTabs}
|
|
|
|
|
|
>
|
|
|
|
|
|
<InfoPanel
|
|
|
|
|
|
data={selectedUser}
|
|
|
|
|
|
fields={userFields}
|
|
|
|
|
|
actions={[
|
|
|
|
|
|
{ key: 'move', label: '转移分组', type: 'primary', onClick: () => console.log('转移分组') },
|
|
|
|
|
|
{ key: 'reset', label: '重置密码', onClick: () => console.log('重置密码') },
|
|
|
|
|
|
{ key: 'disable', label: '停用', onClick: () => console.log('停用') },
|
|
|
|
|
|
]}
|
|
|
|
|
|
/>
|
|
|
|
|
|
</DetailDrawer>
|
|
|
|
|
|
</>
|
|
|
|
|
|
)
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
## 布局结构
|
|
|
|
|
|
|
2025-11-13 10:11:08 +00:00
|
|
|
|
### 整体布局
|
|
|
|
|
|
|
2025-11-05 06:17:47 +00:00
|
|
|
|
抽屉采用固定头部、可滚动内容的布局:
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
┌─────────────────────────────────────┐
|
|
|
|
|
|
│ 标题栏(固定,不滚动) │
|
|
|
|
|
|
│ [关闭] [标题] [徽标] [操作按钮] │
|
|
|
|
|
|
├─────────────────────────────────────┤
|
|
|
|
|
|
│ │
|
2025-11-13 10:11:08 +00:00
|
|
|
|
│ 内容区域(可滚动,padding: 24px) │
|
2025-11-05 06:17:47 +00:00
|
|
|
|
│ - children 主要内容 │
|
|
|
|
|
|
│ - tabs 标签页(可选) │
|
|
|
|
|
|
│ │
|
|
|
|
|
|
└─────────────────────────────────────┘
|
|
|
|
|
|
```
|
|
|
|
|
|
|
2025-11-13 10:11:08 +00:00
|
|
|
|
### DOM 结构层级
|
|
|
|
|
|
|
|
|
|
|
|
```html
|
|
|
|
|
|
<Drawer styles={{ body: { padding: 0 } }}>
|
|
|
|
|
|
<div class="detail-drawer-content">
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 固定头部区域 -->
|
|
|
|
|
|
<div class="detail-drawer-header">
|
|
|
|
|
|
<div class="detail-drawer-header-left">
|
|
|
|
|
|
<Button class="detail-drawer-close-button" />
|
|
|
|
|
|
<div class="detail-drawer-header-info">
|
|
|
|
|
|
<span class="detail-drawer-title-icon">{icon}</span>
|
|
|
|
|
|
<h2 class="detail-drawer-title">{title}</h2>
|
|
|
|
|
|
<span class="detail-drawer-badge">{badge}</span>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="detail-drawer-header-right">
|
|
|
|
|
|
{headerActions}
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 可滚动内容区域 - 统一的 24px padding -->
|
|
|
|
|
|
<div class="detail-drawer-scrollable-content" style="padding: 24px">
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 主要内容 (children) -->
|
|
|
|
|
|
{children}
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 标签页区域(可选) -->
|
|
|
|
|
|
<div class="detail-drawer-tabs">
|
|
|
|
|
|
<Tabs>
|
|
|
|
|
|
<TabPane>
|
|
|
|
|
|
<div class="detail-drawer-tab-content">
|
|
|
|
|
|
{tab.content}
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</TabPane>
|
|
|
|
|
|
</Tabs>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</Drawer>
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### Padding 说明
|
|
|
|
|
|
|
|
|
|
|
|
**重要:为避免内容贴边,组件已经统一管理 padding**
|
|
|
|
|
|
|
|
|
|
|
|
- ✅ **Drawer body**: `padding: 0`(由组件设置)
|
|
|
|
|
|
- ✅ **detail-drawer-scrollable-content**: `padding: 24px`(统一的外边距)
|
|
|
|
|
|
- ❌ **children 内容**: 不需要额外添加 padding
|
|
|
|
|
|
- ❌ **tab content**: 不需要额外添加 padding
|
|
|
|
|
|
|
|
|
|
|
|
**正确用法:**
|
|
|
|
|
|
```jsx
|
|
|
|
|
|
<DetailDrawer visible={true} onClose={onClose}>
|
|
|
|
|
|
<InfoPanel data={data} fields={fields} /> {/* ✅ 不需要额外 padding */}
|
|
|
|
|
|
</DetailDrawer>
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
**错误用法:**
|
|
|
|
|
|
```jsx
|
|
|
|
|
|
<DetailDrawer visible={true} onClose={onClose}>
|
|
|
|
|
|
<div style={{ padding: 24 }}> {/* ❌ 不要添加额外的 padding */}
|
|
|
|
|
|
<InfoPanel data={data} fields={fields} />
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</DetailDrawer>
|
|
|
|
|
|
```
|
|
|
|
|
|
|
2025-11-05 06:17:47 +00:00
|
|
|
|
## 样式定制
|
|
|
|
|
|
|
|
|
|
|
|
组件提供以下 CSS 类名供自定义样式:
|
|
|
|
|
|
|
|
|
|
|
|
- `.detail-drawer-content` - 抽屉内容容器
|
|
|
|
|
|
- `.detail-drawer-header` - 顶部标题栏
|
|
|
|
|
|
- `.detail-drawer-header-left` - 标题栏左侧区域
|
|
|
|
|
|
- `.detail-drawer-header-right` - 标题栏右侧区域
|
|
|
|
|
|
- `.detail-drawer-close-button` - 关闭按钮
|
|
|
|
|
|
- `.detail-drawer-header-info` - 标题信息容器
|
|
|
|
|
|
- `.detail-drawer-title-icon` - 标题图标
|
|
|
|
|
|
- `.detail-drawer-title` - 标题文本
|
|
|
|
|
|
- `.detail-drawer-badge` - 徽标容器
|
|
|
|
|
|
- `.detail-drawer-scrollable-content` - 可滚动内容区域
|
|
|
|
|
|
- `.detail-drawer-tabs` - 标签页容器
|
|
|
|
|
|
- `.detail-drawer-tab-content` - 标签页内容
|
|
|
|
|
|
|
|
|
|
|
|
## 使用场景
|
|
|
|
|
|
|
|
|
|
|
|
1. **查看详细信息** - 点击列表行显示详细信息
|
|
|
|
|
|
2. **多标签页详情** - 在详情中展示不同类型的关联数据
|
|
|
|
|
|
3. **带快捷操作的详情** - 在详情顶部提供编辑、删除等操作
|
|
|
|
|
|
4. **复杂数据展示** - 配合 InfoPanel、Card 等组件展示复杂信息
|
|
|
|
|
|
|
|
|
|
|
|
## 注意事项
|
|
|
|
|
|
|
2025-11-13 10:11:08 +00:00
|
|
|
|
1. **宽度选择**:抽屉宽度默认 1080px,可根据内容调整,建议取值范围:720-1200px
|
|
|
|
|
|
2. **固定头部**:标题栏固定在顶部,不随内容滚动,确保操作按钮始终可见
|
|
|
|
|
|
3. **内容 padding**:`detail-drawer-scrollable-content` 已经统一设置了 24px padding,children 内容不需要额外添加 padding
|
|
|
|
|
|
4. **操作按钮**:操作按钮数量不宜过多,建议不超过 3 个
|
|
|
|
|
|
5. **标签页**:使用 `tabs` 时,第一个标签页默认激活
|
|
|
|
|
|
6. **状态清理**:关闭抽屉时建议清空选中状态,避免下次打开时显示旧数据
|
|
|
|
|
|
7. **InfoPanel 集成**:配合 InfoPanel 使用时,InfoPanel 会自动处理内部样式,不需要额外的容器包裹
|