Files
djangoadmin-wiki/DjangoAdmin_Django_AntdVue/zh/volume4/frontend/components.md
T
2026-09-13 17:33:13 +08:00

847 lines
25 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 公共组件库
<!-- Copyright (c) 2021-2026 小蚂蚁云团队 版权所有 -->
:::tip 说明
项目提供丰富的公共组件,位于 `ui/src/components/` 目录,基于 Ant Design Vue 二次封装,覆盖表格、表单、弹窗、上传、富文本编辑等常见场景。组件通过 `src/plugins/` 中的 `setupCustomComponents` 全局注册,任何页面直接使用,无需单独 import。
:::
## 组件总览
| 组件 | 路径 | 说明 |
|------|------|------|
| BasicTable | `components/Table/` | 表格(列定义、分页、操作列、全屏、密度、斑马纹) |
| TableAction | `components/Table/` | 操作列按钮组(权限控制、下拉折叠) |
| BasicForm | `components/Form/` | 表单(schemas 配置化、动态渲染、折叠展开) |
| BasicModal | `components/Modal/` | 弹窗(拖拽、全屏、自定义按钮) |
| BasicUpload | `components/Upload/` | 文件/图片上传(卡片/列表、限制数量、预览) |
| Editor | `components/Editor/` | 富文本编辑器(基于 wangeditor) |
| CropperImage | `components/Cropper/` | 图片裁剪(圆形/矩形、实时预览) |
| QrCode | `components/Qrcode/` | 二维码生成(canvas/img、内嵌 logo) |
| ChinaArea | `components/ChinaArea/` | 省市区级联(懒加载、二/三级联动) |
| Icon | `components/icon/` | 图标(支持 Ant Design Icons + SVG 图标) |
| BasicSelect | `components/Select/` | 增强下拉(远程请求、本地缓存) |
| CountTo | `components/CountTo/` | 数字动画(前缀/后缀、千分位、缓动曲线) |
| Password | `components/Password/` | 密码强度(强度指示器、重复确认、复杂度校验) |
| PageWrapper | `components/Page/` | 页面容器(标题卡片、固定底部) |
| Authority | `components/Authority/` | 权限容器(按权限码控制子元素渲染) |
| LockScreen | `components/Lockscreen/` | 锁屏组件 |
| ImpExcel | `components/Excel/` | Excel 导入/导出 |
| AppProvider | `components/Application/` | 应用提供者(全局配置注入) |
| Websocket | `components/Websocket/` | WebSocket 连接 |
| importFile | `components/importFile/` | 通用文件导入 |
| numberInput | `components/numberInput/` | 数字输入框 |
| priceInput | `components/priceInput/` | 金额输入框 |
| Region | `components/Region/` | 区域选择 |
| TableSelect | `components/TableSelect/` | 表格选择器 |
| pagination | `components/pagination/` | 分页组件 |
---
## BasicTable 表格
表格组件是使用频率最高的组件,基于 Ant Design Vue 的 `a-table` 封装,详见 [BasicTable 表格](/zh/volume4/frontend/table) 章节。
### Props
| 属性 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| `columns` | `BasicColumn[]` | `[]`(必填) | 列定义 |
| `request` | `Function` | `null` | 数据请求函数,自动管理分页和 loading |
| `dataSource` | `Function \| Array` | `[]` | 数据源(与 request 二选一) |
| `actionColumn` | `BasicColumn` | `null` | 操作列配置 |
| `title` | `string` | `null` | 表格标题 |
| `titleTooltip` | `string` | `null` | 标题提示 |
| `pagination` | `Object \| Boolean` | `{}` | 分页配置,`false` 隐藏分页 |
| `rowKey` | `string \| Function` | `undefined` | 行数据的唯一标识 |
| `border` | `Boolean` | `false` | 是否显示边框 |
| `striped` | `Boolean` | `false` | 斑马纹 |
| `size` | `string` | `'default'` | 表格尺寸:`small` / `default` / `large` |
| `tableHeight` | `Number \| String` | `null` | 固定表格高度 |
| `maxHeight` | `Number` | - | 最大高度 |
| `canResize` | `Boolean` | `true` | 是否自适应窗口高度 |
| `resizeHeightOffset` | `Number` | `0` | 高度偏移量 |
| `showTableSetting` | `Boolean` | `true` | 是否显示工具栏 |
| `tableSetting` | `TableSetting` | 见下方 | 工具栏配置 |
| `isKeepRowKeys` | `Boolean` | `false` | 翻页时是否保留选中行 |
### tableSetting 工具栏配置
| 属性 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| `redo` | `Boolean` | `true` | 刷新按钮 |
| `size` | `Boolean` | `true` | 密度切换 |
| `setting` | `Boolean` | `true` | 列设置 |
| `fullscreen` | `Boolean` | `true` | 全屏切换 |
| `striped` | `Boolean` | `true` | 斑马纹开关 |
### BasicColumn 列定义
| 属性 | 类型 | 说明 |
|------|------|------|
| `title` | `string` | 列标题 |
| `dataIndex` | `string` | 字段名 |
| `width` | `number` | 列宽 |
| `align` | `string` | 对齐方式 |
| `type` | `string` | 类型:`index` / `selection` |
| `customRender` | `Function` | 自定义渲染函数 `({ text, record, index, column }) => VNode` |
| `isSlot` | `boolean` | 是否使用插槽 |
| `ellipsis` | `boolean` | 超出省略(tooltip) |
| `auth` | `string[]` | 权限编码,控制列是否显示 |
| `ifShow` | `boolean \| Function` | 业务控制是否显示 |
### Events
| 事件 | 参数 | 说明 |
|------|------|------|
| `fetch-success` | `(data, result)` | 数据请求成功 |
| `fetch-error` | `(error)` | 数据请求失败 |
| `selection-change` | `(rows)` | 多选变化 |
| `columns-change` | `(columns)` | 列设置变化 |
| `checked-row-change` | `(rowKeys)` | 选中行变化 |
### Slots
| 插槽 | 说明 |
|------|------|
| `tableTitle` | 表格标题左侧区域(常放添加按钮) |
| `toolbar` | 工具栏右侧区域 |
| `{prop}` | 列名对应插槽,自定义列渲染 |
### Expose 方法
| 方法 | 说明 |
|------|------|
| `reload(opt?)` | 刷新表格(保留分页) |
| `restReload(opt?)` | 重置到第一页并刷新 |
| `reloadTable(opt?)` | 内部刷新(清空选中行) |
| `getDataSource()` | 获取当前数据 |
| `setTableData(data)` | 设置表格数据 |
| `updateTableDataRecord(index, record)` | 更新指定行 |
| `deleteTableDataRecord(index)` | 删除指定行 |
| `getColumns()` | 获取列配置 |
| `setColumns(columns)` | 设置列配置 |
| `clearSelection()` | 清空多选 |
| `setCheckedRowKeys(keys)` | 设置选中行 |
| `redoHeight()` | 重新计算高度 |
### 基础用法
```vue
<template>
<BasicTable :columns="columns" :request="loadDataTable" ref="tableRef">
<template #tableTitle>
<a-space>
<a-button v-perm="['sys:level:add']" type="primary" @click="handleAdd">
<template #icon><PlusOutlined /></template>
新增
</a-button>
</a-space>
</template>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'action'">
<a-space>
<a-button type="primary" @click="handleEdit(record.id)" v-perm="['sys:level:update']">
<template #icon><EditOutlined /></template>
编辑
</a-button>
<a-button type="primary" danger @click="handleDelete(record.id)" v-perm="['sys:level:delete']">
<template #icon><DeleteOutlined /></template>
删除
</a-button>
</a-space>
</template>
</template>
</BasicTable>
</template>
<script setup lang="ts">
import { PlusOutlined, EditOutlined, DeleteOutlined } from '@ant-design/icons-vue';
const columns = [
{ title: '名称', dataIndex: 'name', width: 200 },
{ title: '状态', dataIndex: 'status', width: 100 },
{ title: '创建时间', dataIndex: 'createTime', width: 180 },
];
async function loadDataTable(params) {
const res = await getListApi(params);
return res;
}
</script>
```
---
## TableAction 操作列
操作列按钮组件,支持权限控制和下拉折叠。
### Props
| 属性 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| `actions` | `ActionItem[]` | (必填) | 操作按钮列表 |
| `dropDownActions` | `ActionItem[]` | `null` | 下拉折叠操作列表 |
| `dropDownProps` | `ActionItem` | `{ label: '更多' }` | 下拉按钮配置 |
| `select` | `Function` | `() => {}` | 下拉选择回调 |
### ActionItem 配置
| 属性 | 类型 | 说明 |
|------|------|------|
| `label` | `string` | 按钮文字 |
| `auth` | `string[]` | 权限编码 |
| `onClick` | `Function` | 点击回调 |
| `icon` | `Component` | 图标组件 |
| `type` | `string` | 按钮类型 |
| `disabled` | `boolean` | 是否禁用 |
| `ifShow` | `boolean \| Function` | 是否显示 |
| `isConfirm` | `boolean` | 是否需要确认 |
| `popConfirm` | `object` | 气泡确认框配置 |
---
## BasicForm 表单
表单组件通过 schemas 配置化定义表单字段,支持动态渲染、折叠展开,详见 [BasicForm 表单](/zh/volume4/frontend/form) 章节。
### Props
| 属性 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| `schemas` | `FormSchema[]` | `[]` | 表单字段配置 |
| `model` | `Object` | - | 表单数据对象 |
| `rules` | `FormRules` | - | 表单验证规则 |
| `inline` | `Boolean` | `false` | 行内表单 |
| `layout` | `string` | `'vertical'` | 布局方式 |
| `labelPosition` | `string` | `'right'` | 标签位置 |
| `labelWidth` | `Number \| String` | `80` | 标签宽度 |
| `size` | `string` | `'default'` | 表单尺寸 |
| `disabled` | `Boolean` | `false` | 禁用全部组件 |
| `isFull` | `Boolean` | `true` | 组件是否 100% 宽度 |
| `showActionButtonGroup` | `Boolean` | `true` | 显示操作按钮组 |
| `showSubmitButton` | `Boolean` | `true` | 显示查询按钮 |
| `showResetButton` | `Boolean` | `true` | 显示重置按钮 |
| `showAdvancedButton` | `Boolean` | `true` | 显示展开/收起按钮 |
| `submitButtonText` | `string` | `'查询'` | 查询按钮文字 |
| `resetButtonText` | `string` | `'重置'` | 重置按钮文字 |
| `collapsed` | `Boolean` | `true` | 是否默认折叠 |
| `collapsedRows` | `Number` | `1` | 折叠时显示行数 |
### FormSchema 字段配置
| 属性 | 类型 | 说明 |
|------|------|------|
| `name` | `string` | 字段名(必填) |
| `label` | `string` | 标签文字 |
| `component` | `ComponentType` | 渲染组件:`Input` / `Select` / `DatePicker` 等 |
| `componentProps` | `object` | 组件属性 |
| `defaultValue` | `any` | 默认值 |
| `rules` | `object \| object[]` | 字段校验规则 |
| `slot` | `string` | 自定义插槽名 |
| `hidden` | `boolean \| Function` | 是否隐藏 |
| `colProps` | `ColProps` | 栅格配置 |
| `labelMessage` | `string` | 标签提示信息 |
| `suffix` | `string` | 后缀文字 |
### Events
| 事件 | 说明 |
|------|------|
| `submit` | 点击查询按钮 |
| `reset` | 点击重置按钮 |
### Expose 方法
| 方法 | 说明 |
|------|------|
| `setFieldsValue(values)` | 设置字段值 |
| `getFieldsValue()` | 获取所有字段值 |
| `resetFields()` | 重置字段 |
| `validate()` | 校验表单 |
| `clearValidate(name?)` | 清除校验 |
| `setProps(formProps)` | 设置属性 |
| `setSchema(schemaProps)` | 动态修改 schema |
### 基础用法
```vue
<template>
<BasicForm @register="registerForm" @submit="handleSearch" @reset="handleReset" />
</template>
<script setup lang="ts">
const [registerForm] = useForm({
schemas: [
{
name: 'name',
label: '名称',
component: 'Input',
componentProps: { placeholder: '请输入名称' },
},
{
name: 'status',
label: '状态',
component: 'Select',
componentProps: {
options: [
{ label: '启用', value: 1 },
{ label: '禁用', value: 0 },
],
},
},
{
name: 'dateRange',
label: '日期范围',
component: 'DatePicker',
componentProps: { type: 'daterange' },
},
],
});
</script>
```
---
## BasicModal 弹窗
弹窗组件基于 `a-modal` 封装,支持拖拽、自定义按钮,详见 [Modal 弹窗](/zh/volume4/frontend/modal) 章节。
### Props
| 属性 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| `title` | `string` | `''` | 弹窗标题 |
| `width` | `Number` | `446` | 弹窗宽度 |
| `draggable` | `Boolean` | `true` | 是否可拖拽 |
| `hideFooter` | `Boolean` | `false` | 隐藏底部按钮 |
| `confirmButText` | `string` | `'确认'` | 确认按钮文字 |
| `cancelButText` | `string` | `'取消'` | 取消按钮文字 |
| `confirmButProps` | `Object` | - | 确认按钮属性 |
| `cancelButProps` | `Object` | - | 取消按钮属性 |
### Events
| 事件 | 说明 |
|------|------|
| `ok` | 点击确认 |
| `register` | 弹窗注册回调 |
### Expose 方法
| 方法 | 说明 |
|------|------|
| `setModalProps(props)` | 设置弹窗属性 |
| `openModal()` | 打开弹窗 |
| `closeModal()` | 关闭弹窗 |
### 基础用法
```vue
<template>
<BasicModal title="编辑用户" :width="600" @register="registerModal" @ok="handleSubmit">
<BasicForm @register="registerForm" />
</BasicModal>
</template>
<script setup lang="ts">
const [registerModal, { openModal, closeModal, setModalProps }] = useModal();
function handleEdit(record) {
setModalProps({ title: '编辑用户' });
openModal();
// 回填表单数据
nextTick(() => {
setFieldsValue(record);
});
}
</script>
```
---
## BasicUpload 上传
文件/图片上传组件,基于 Ant Design Vue 的 `a-upload` 封装,支持卡片/列表模式、数量限制、图片预览。
### Props
| 属性 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| `listType` | `string` | `'picture-card'` | 展示类型:`picture-card` / `text` / `picture` |
| `limit` | `Number` | `Infinity` | 最大上传数量 |
| `maxSize` | `Number` | `2` | 文件大小上限(MB) |
| `accept` | `string` | - | 接受的文件类型 |
| `list` | `Ifiles[]` | `[]` | 已上传文件列表 |
| `circle` | `Boolean` | `false` | 圆形裁剪 |
| `uploadTitle` | `string` | `'上传图片'` | 列表模式按钮文字 |
| `helpText` | `string` | `''` | 帮助提示文字 |
| `width` | `Number` | `104` | 卡片宽度(px) |
### Events
| 事件 | 参数 | 说明 |
|------|------|------|
| `uploadChange` | `(fileList)` | 上传/删除变化 |
| `delete` | `(fileList)` | 删除文件 |
### 基础用法
```vue
<!-- 单图上传 -->
<Upload v-model="formData.cover" :limit="1" accept="image/*" />
<!-- 多图上传 -->
<Upload :list="formData.images" :limit="5" @uploadChange="handleImageChange" />
<!-- 文件上传 -->
<Upload list-type="text" accept=".pdf,.doc,.docx" uploadTitle="上传附件" />
```
---
## Editor 富文本编辑器
基于 [wangeditor](https://www.wangeditor.cn/) 封装,支持图片/视频上传、工具栏配置。
### Props
| 属性 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| `getHtml` | `string` | - | 双向绑定(HTML 内容) |
| `getText` | `string` | - | 双向绑定(纯文本) |
| `height` | `string` | `'310'` | 编辑器高度 |
| `width` | `string` | `'auto'` | 编辑器宽度 |
| `mode` | `string` | `'default'` | 模式:`default` / `simple` |
| `disable` | `Boolean` | `false` | 是否禁用 |
| `placeholder` | `string` | `'请输入内容...'` | 占位文字 |
| `uploadFileUrl` | `string` | `'/file/upload'` | 图片上传接口 |
### 基础用法
```vue
<template>
<Editor v-model:getHtml="formData.content" height="400px" />
</template>
```
:::warning 注意
编辑器内部自动处理图片上传,上传接口由 `uploadFileUrl` 配置。后端图片迁移和 XSS 清洗由 Service 层的 `rich_text_fields` 声明自动处理。
:::
---
## CropperImage 图片裁剪
基于 [cropperjs](https://github.com/fengyuanchen/cropperjs) 封装,支持圆形/矩形裁剪、实时预览。
### Props
| 属性 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| `src` | `string` | (必填) | 图片地址 |
| `alt` | `string` | - | 图片描述 |
| `circled` | `Boolean` | `false` | 圆形裁剪 |
| `realTimePreview` | `Boolean` | `true` | 实时预览 |
| `height` | `string \| Number` | `'360px'` | 裁剪区域高度 |
| `imageStyle` | `CSSProperties` | `{}` | 图片样式 |
| `options` | `Object` | `{}` | cropperjs 配置 |
### Events
| 事件 | 参数 | 说明 |
|------|------|------|
| `cropend` | `{ imgBase64, imgInfo }` | 裁剪完成 |
| `ready` | `(cropper)` | 裁剪器就绪 |
| `cropendError` | - | 裁剪出错 |
### 基础用法
```vue
<template>
<CropperImage
:src="formData.avatar"
:circled="true"
height="300px"
@cropend="handleCropend"
/>
</template>
<script setup lang="ts">
function handleCropend({ imgBase64, imgInfo }) {
// imgBase64: base64 格式的裁剪结果
// imgInfo: 裁剪区域坐标和尺寸
formData.value.avatar = imgBase64;
}
</script>
```
---
## QrCode 二维码生成
基于 [qrcode](https://github.com/soldair/node-qrcode) 封装,支持 canvas/img 渲染、内嵌 logo。
### Props
| 属性 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| `value` | `string \| Array` | (必填) | 二维码内容 |
| `width` | `Number` | `200` | 宽度(px) |
| `tag` | `string` | `'canvas'` | 渲染方式:`canvas` / `img` |
| `logo` | `string \| Object` | `''` | 中间 logo |
| `options` | `Object` | `{}` | qrcode 配置项 |
### Events
| 事件 | 参数 | 说明 |
|------|------|------|
| `done` | `{ url, ctx }` | 生成完成 |
| `error` | `(error)` | 生成失败 |
### Expose 方法
| 方法 | 说明 |
|------|------|
| `download(fileName?)` | 下载二维码图片 |
### 基础用法
```vue
<template>
<QrCode value="https://www.example.com" :width="200" :logo="logoUrl" />
</template>
```
---
## ChinaArea 省市区级联
省市区三级联动选择器,基于后端城市接口懒加载。
### Props
| 属性 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| `modelValue` | `String \| Array` | - | 双向绑定(区划编码数组) |
| `type` | `Number` | `3` | 联动级别:`2`(省市) / `3`(省市区) |
| `disabled` | `Boolean` | `false` | 是否禁用 |
### Events
| 事件 | 参数 | 说明 |
|------|------|------|
| `update:modelValue` | `(codes)` | 值变化 |
| `change` | `(text)` | 选中文本(如"浙江省杭州市西湖区") |
### 基础用法
```vue
<template>
<ChinaArea v-model="formData.cityCode" :type="3" @change="handleCityChange" />
</template>
```
---
## BasicSelect 增强下拉
远程数据下拉选择器,支持请求函数和本地缓存。
### Props
| 属性 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| `request` | `Function` | (必填) | 获取选项数据的异步函数 |
| `options` | `Array` | `[]` | 静态选项(与 request 二选一) |
| `modelValue` | `String \| Number` | - | 双向绑定 |
| `cache` | `Boolean` | `false` | 是否缓存到 localStorage |
| `cacheKey` | `string` | `''` | 缓存 key(开启缓存时必填) |
| `width` | `Number` | `150` | 宽度(px) |
| `block` | `Boolean` | `false` | 100% 父容器宽度 |
### Expose 方法
| 方法 | 说明 |
|------|------|
| `fetch()` | 重新请求数据 |
| `getData()` | 获取当前选项数据 |
### 基础用法
```vue
<template>
<BasicSelect
v-model="formData.deptId"
:request="getDeptOptions"
:cache="true"
cacheKey="dept-options"
placeholder="请选择部门"
/>
</template>
<script setup lang="ts">
async function getDeptOptions() {
const res = await getDeptListApi();
return res.data.map(item => ({ label: item.name, value: item.id }));
}
</script>
```
---
## CountTo 数字动画
数字动态递增/递减动画,支持前缀/后缀、千分位、缓动曲线。
### Props
| 属性 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| `startVal` | `Number` | `0` | 起始值 |
| `endVal` | `Number` | `2021` | 结束值 |
| `duration` | `Number` | `1500` | 动画时长(ms) |
| `autoplay` | `Boolean` | `true` | 自动播放 |
| `decimals` | `Number` | `0` | 小数位数 |
| `prefix` | `string` | `''` | 前缀 |
| `suffix` | `string` | `''` | 后缀 |
| `separator` | `string` | `','` | 千分位分隔符 |
| `decimal` | `string` | `'.'` | 小数点符号 |
| `color` | `string` | - | 字体颜色 |
| `useEasing` | `Boolean` | `true` | 是否使用缓动 |
| `transition` | `string` | `'linear'` | 缓动曲线 |
### Events
| 事件 | 说明 |
|------|------|
| `onStarted` | 动画开始 |
| `onFinished` | 动画结束 |
### 基础用法
```vue
<template>
<CountTo :endVal="12345" :duration="2000" prefix="¥" separator="," />
</template>
```
---
## Password 密码强度
密码输入框,内置强度指示器、重复确认、复杂度校验。
### Props
| 属性 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| `value` | `string` | - | 密码值 |
| `repeat` | `Boolean` | `false` | 是否显示重复确认框 |
| `required` | `Boolean` | `true` | 是否必填 |
| `minLength` | `Number` | `6` | 最小长度 |
| `maxLength` | `Number` | `32` | 最大长度 |
| `complexity` | `Boolean` | `false` | 是否启用复杂度校验 |
| `complexityTip` | `string` | - | 复杂度不满足时的提示 |
| `width` | `Number` | `300` | 弹出框宽度 |
| `block` | `Boolean` | `false` | 100% 宽度 |
### 强度等级
| 等级 | 条件 | 说明 |
|------|------|------|
| 0 | 无 | 极弱 |
| 1 | 含小写或大写 | 弱 |
| 2 | 含小写 + 大写,或含数字 | 中 |
| 3 | 含小写 + 大写 + 数字 | 强 |
| 4 | 含小写 + 大写 + 数字 + 特殊字符 | 极强 |
### Expose 方法
| 方法 | 说明 |
|------|------|
| `isValidator()` | 是否通过校验 |
| `showValidator()` | 触发校验显示 |
### 基础用法
```vue
<template>
<Password v-model:value="formData.password" :repeat="true" :complexity="true" />
</template>
```
---
## PageWrapper 页面容器
页面容器组件,提供标题卡片和固定底部区域。
### Props
| 属性 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| `title` | `string` | `''` | 页面标题 |
| `content` | `string` | `''` | 标题下方描述文字 |
| `contentStyle` | `Object` | `{}` | 主体区域样式 |
| `contentClass` | `string` | `''` | 主体区域 class |
| `showFooter` | `Boolean` | `true` | 是否显示底部 |
### Slots
| 插槽 | 说明 |
|------|------|
| `headerContent` | 标题卡片内容区域 |
| `default` | 页面主体内容 |
| `leftFooter` | 底部左侧(常放操作按钮) |
| `rightFooter` | 底部右侧 |
### 基础用法
```vue
<template>
<PageWrapper title="用户管理" content="管理系统用户信息">
<BasicTable :columns="columns" :request="loadData" />
<template #leftFooter>
<a-button @click="handleCancel">取消</a-button>
</template>
<template #rightFooter>
<a-button type="primary" @click="handleSubmit">提交</a-button>
</template>
</PageWrapper>
</template>
```
---
## Authority 权限容器
按权限码控制子元素是否渲染,类似 `v-perm` 指令的组件形式。
### Props
| 属性 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| `value` | `string[]` | `[]` | 权限编码数组 |
### 基础用法
```vue
<template>
<Authority :value="['sys:user:add']">
<a-button type="primary">新增用户</a-button>
</Authority>
</template>
```
:::tip v-perm 指令
除了 `Authority` 组件,项目还提供 `v-perm` 指令,功能相同但更简洁:
```vue
<a-button v-perm="['sys:user:add']">新增用户</a-button>
```
:::
---
## Icon 图标
统一图标组件,支持 Ant Design Icons 和 SVG 图标。
### Props
| 属性 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| `name` | `string` | (必填) | 图标名称 |
| `size` | `string \| Number` | `'14px'` | 图标大小 |
| `color` | `string` | `'inherit'` | 图标颜色 |
### 基础用法
```vue
<template>
<!-- Ant Design Icons -->
<PlusOutlined style="font-size: 18px" />
<!-- SVG 图标 -->
<Icon name="svg-icon-user" />
</template>
```
---
## ImpExcel Excel 导入/导出
Excel 文件导入和导出组件。
### 导出函数
```typescript
import { jsonToSheetXlsx, aoaToSheetXlsx } from '@/components/Excel';
// JSON 数据导出
jsonToSheetXlsx({
data: [{ name: '张三', age: 25 }],
header: { name: '姓名', age: '年龄' },
filename: '用户列表.xlsx',
});
// 二维数组导出
aoaToSheetXlsx({
data: [['姓名', '年龄'], ['张三', 25]],
filename: '用户列表.xlsx',
});
```
### 导入组件
```vue
<template>
<ImpExcel @success="handleImportSuccess" />
</template>
<script setup lang="ts">
function handleImportSuccess(data) {
// data: 导入的表格数据
console.log(data);
}
</script>
```
---
## 全局注册
所有组件在 `src/plugins/setupCustomComponents.ts` 中通过 `setupCustomComponents` 全局注册:
```typescript
// main.ts
import { setupCustomComponents } from '/@/plugins';
setupCustomComponents(app); // 注册所有自定义组件
```
全局注册后,任何组件中直接使用,无需单独 import。
---
## 权限控制体系
项目提供三种权限控制方式,覆盖不同场景:
| 方式 | 语法 | 适用场景 |
|------|------|----------|
| `v-perm` 指令 | `v-perm="['sys:user:add']"` | 按钮级权限,最常用 |
| `Authority` 组件 | `<Authority :value="['sys:user:add']">` | 容器级权限,控制多个元素 |
| `auth` 列属性 | `{ auth: ['sys:user:delete'] }` | TableAction 操作列权限 |
:::warning 注意
`v-perm` 和 `Authority` 的权限码必须与后端 `@permission_required("sys:xxx:xxx")` 一致。用户 ID 1(admin)拥有所有权限。
:::
---
## 总结
公共组件库基于 Ant Design Vue 二次封装,核心三件套 BasicTable(表格)、BasicForm(表单)、BasicModal(弹窗)覆盖列表页标准场景。辅以 Upload、Editor、Cropper 等业务组件,以及 Authority、v-perm 权限体系。通过全局注册,任何页面直接使用,无需单独 import。优先使用公共组件,避免重复开发。