# ProDescriptions 详情组件

基于 Element UI 风格封装的详情展示组件，参考 [Vben Admin Description](https://doc.vvbin.cn/components/desc.html#usage)，用于展示结构化只读信息，支持：

- `schema` 驱动的详情项配置
- 响应式 `column`
- `useDescription` 编程式调用
- 折叠展开
- 自定义 `render` 与具名插槽
- `field` / `dataIndex` 双写法兼容 Vben 使用习惯

## 组件构成

- **ProDescriptions** - 主组件
- **useDescription** - Hook，返回 `register` 和 `descriptionAction`

## 基础用法

```vue
<template>
  <ProDescriptions
    title="基础示例"
    :column="3"
    :data="detailData"
    :schema="schema"
  />
</template>

<script setup lang="ts">
import { ProDescriptions } from 'element-component-pro'
import type { DescriptionSchema } from 'element-component-pro'

const detailData = {
  username: 'test',
  nickName: 'VB',
  age: 18,
  phone: '15695909xxx',
  email: '190848757@qq.com',
}

const schema: DescriptionSchema[] = [
  { label: '用户名', field: 'username', dataIndex: 'username' },
  {
    label: '昵称',
    dataIndex: 'nickName',
    render: (value, record) => `${record.username}-${value}`,
  },
  { label: '年龄', dataIndex: 'age' },
  { label: '联系电话', dataIndex: 'phone' },
  { label: '邮箱', dataIndex: 'email' },
]
</script>
```

## useDescription

```vue
<template>
  <ProDescriptions @register="register" />
</template>

<script setup lang="ts">
import { ProDescriptions, useDescription } from 'element-component-pro'

const [register, descriptionAction] = useDescription({
  title: 'useDescription',
  data: {
    name: '张三',
    role: '管理员',
  },
  schema: [
    { label: '姓名', dataIndex: 'name' },
    { label: '角色', dataIndex: 'role' },
  ],
})

const updateRole = () => {
  descriptionAction.setData({ role: '访客' })
}
</script>
```

## Props

| 属性 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| `title` | `string` | - | 标题 |
| `helpMessage` | `string \| string[]` | - | 标题右侧帮助文案 |
| `size` | `'medium' \| 'small'` | `'medium'` | 尺寸 |
| `bordered` | `boolean` | `true` | 是否显示边框 |
| `column` | `number \| { xxl, xl, lg, md, sm, xs }` | `{ xxl: 4, xl: 3, lg: 3, md: 3, sm: 2, xs: 1 }` | 每行列数 |
| `schema` | `DescriptionSchema[]` | `[]` | 描述项配置 |
| `data` | `Record<string, unknown>` | `{}` | 数据源 |
| `emptyText` | `string` | `'-'` | 空值展示文本 |
| `useCollapse` | `boolean` | `false` | 是否启用折叠 |
| `collapseOptions` | `object` | `{ canExpand: false, defaultExpand: true, visibleRows: 1 }` | 折叠配置 |

## DescriptionSchema

| 属性 | 类型 | 说明 |
|------|------|------|
| `label` | `string` | 标签 |
| `field` | `string` | 字段名，兼容 Vben 风格写法 |
| `dataIndex` | `string` | 字段名；未传时可回退使用 `field` |
| `span` | `number` | 所占列数 |
| `show` | `boolean \| (data) => boolean` | 是否显示 |
| `labelMinWidth` | `number` | label 最小宽度 |
| `contentMinWidth` | `number` | content 最小宽度 |
| `labelStyle` | `Record<string, string \| number>` | 标签样式 |
| `contentStyle` | `Record<string, string \| number>` | 内容样式 |
| `slot` | `string` | 自定义插槽名 |
| `render` | `(value, record) => VNode \| string \| number` | 自定义渲染 |
| `tooltip` | `boolean \| string \| object \| (params) => boolean \| string \| object` | 描述项 value tooltip，`true` 时默认展示当前值 |

## tooltip

`tooltip` 用于给详情项 value 增加悬浮提示，适合长文本、层级较深的数组值，或需要补充业务说明的只读字段。

支持以下几种写法：

| 写法 | 说明 |
|------|------|
| `true` | 启用 tooltip，并默认使用当前字段值作为内容 |
| `string` | 使用固定文案作为 tooltip 内容 |
| `object` | 透传给 `el-tooltip` 的 props；未传 `content` 时默认使用当前字段值 |
| `(params) => ...` | 动态返回上面任一类型，可根据 record 联动 |

`params` 包含以下字段：

- `value`：当前详情项值
- `record`：完整数据源
- `schema`：当前详情项配置

默认行为：

- 默认 `placement` 为 `top`
- 默认 `effect` 为 `dark`
- 当 tooltip 内容为空字符串、`null`、`undefined` 或空数组时，会自动禁用 tooltip
- 数组值未显式指定 `content` 时，会按逗号拼接展示
- 对象值未显式指定 `content` 时，会自动 `JSON.stringify` 后展示

```ts
const schema: DescriptionSchema[] = [
  {
    label: '联系地址',
    dataIndex: 'address',
    tooltip: true,
  },
  {
    label: '账号状态',
    dataIndex: 'status',
    tooltip: ({ record }) => record.status === 1 ? '当前为启用状态' : '当前为禁用状态',
  },
  {
    label: '备注',
    dataIndex: 'remark',
    tooltip: {
      placement: 'top-start',
      effect: 'light',
    },
  },
]
```

### tooltip 常见问题

#### 1. `tooltip: true` 默认展示什么？

默认展示当前字段真实值：

- 普通文本直接转成字符串
- 数组按逗号拼接
- 对象转成 JSON 字符串
- 空值时自动禁用 tooltip

#### 2. `render` 返回字符串时还会支持 tooltip 吗？

支持。如果 `render` 返回的是 `string` 或 `number`，会继续套用 `tooltip` 逻辑。

如果 `render` 返回的是自定义 VNode，则由你自己控制展示结构，此时不会额外包裹默认 tooltip。

#### 3. 适合在哪些字段上开启？

建议优先用于：

- 长地址、备注、说明类字段
- 多选标签或数组拼接结果
- 证件号、邮箱等可能需要完整查看但页面空间有限的字段
- 需要补充业务解释的状态字段

## collapseOptions

| 属性 | 类型 | 说明 |
|------|------|------|
| `canExpand` | `boolean` | 是否显示展开/收起按钮 |
| `defaultExpand` | `boolean` | 默认是否展开 |
| `expandButtonText` | `string` | 展开按钮文案 |
| `collapseButtonText` | `string` | 收起按钮文案 |
| `helpMessage` | `string \| string[]` | 折叠区域帮助提示 |
| `visibleRows` | `number` | 折叠时默认显示的行数 |

## descriptionAction 方法

| 方法 | 类型 | 说明 |
|------|------|------|
| `setProps` | `(props: Partial<DescriptionProps>) => Promise<void>` | 动态更新组件 Props |
| `setData` | `(data: Record<string, unknown>) => Promise<void>` | 合并更新数据 |
| `getData` | `() => Record<string, unknown>` | 获取当前数据 |

## Slots

| 名称 | 说明 |
|------|------|
| `[dataIndex]` | 以字段名命名的具名插槽，参数：`{ value, record, schema }` |
| `[schema.slot]` | 自定义 slot 名称，优先于 `dataIndex` |
