🧩 Admin 组件
Admin 提供了一套开箱即用的通用组件,位于 src/components/。这些组件大多是对 Element Plus 的二次封装,统一了触发方式(trigger slot)、确认流程(async confirm)、国际化和项目样式约定。
运行时包页面可通过 window.__SUNADMIN_ADMIN_RUNTIME__ 访问部分共享组件,详见 Admin 总览 - 运行包共享机制。
目录
💬 弹层与面板
Popup
src/components/popup/index.vue
对话框组件,基于 el-dialog 封装。通过 #trigger 插槽定义触发元素,点击即打开弹窗,无需外部管理 visible 状态。设置 async 后确认不会自动关闭,适合表单提交场景。
<popup title="编辑用户" async width="600px" @confirm="handleSave">
<template #trigger>
<el-button type="primary">编辑</el-button>
</template>
<el-form :model="formData">
<!-- 表单内容 -->
</el-form>
</popup>| Prop | 类型 | 默认值 | 说明 |
|---|---|---|---|
title | String | '' | 标题 |
content | String | '' | 纯文本内容(slot 优先) |
width | String | '400px' | 宽度 |
async | Boolean | false | 确认后不自动关闭 |
clickModalClose | Boolean | false | 点击遮罩关闭 |
center | Boolean | false | 居中布局 |
isFooter | Boolean | true | 显示底部按钮 |
fullscreen | Boolean | false | 全屏模式 |
confirmButtonText | String|Boolean | '确定' | 确认按钮文字,false 隐藏 |
cancelButtonText | String|Boolean | '取消' | 取消按钮文字,false 隐藏 |
loading | Boolean | false | 确认按钮加载状态 |
disabled | Boolean | false | 禁用触发 |
customClass | String | '' | 自定义 CSS 类 |
插槽:trigger、header、default、footer
事件:confirm、cancel、close、open
暴露方法:open()、close()
Drawer
src/components/drawer/index.vue
侧滑面板,基于 el-drawer 封装。与 Popup 共享 trigger slot 和 async confirm 模式,适合详情编辑、表单填写等需要更大空间的场景。
<drawer title="订单详情" size="800" @confirm="handleSave">
<template #trigger>
<el-button>查看详情</el-button>
</template>
<!-- 详情内容 -->
</drawer>| Prop | 类型 | 默认值 | 说明 |
|---|---|---|---|
direction | String | 'rtl' | 打开方向 |
title | String | '' | 标题 |
content | String | '' | 纯文本内容 |
size | String | '700' | 宽度/高度 |
async | Boolean | false | 确认后不自动关闭 |
clickModalClose | Boolean | false | 点击遮罩关闭 |
isFooter | Boolean | true | 显示底部按钮 |
confirmButtonText | String|Boolean | '确定' | 确认按钮文字 |
cancelButtonText | String|Boolean | '取消' | 取消按钮文字 |
loading | Boolean | false | 确认按钮加载状态 |
disabled | Boolean | false | 禁用触发 |
customClass | String | '' | 自定义 CSS 类 |
插槽:trigger、default、footer
事件:confirm、cancel、close、open
暴露方法:open()、close()
FooterBar
src/components/footer-bar/index.vue
固定在页面底部的操作栏,常用于编辑页面的保存/取消按钮。默认使用 position: absolute,设置 fixed 切换为 position: fixed。
<admin-surface-card title="编辑资料">
<el-form>...</el-form>
<footer-bar>
<el-button @click="cancel">取消</el-button>
<el-button type="primary" @click="save">保存</el-button>
</footer-bar>
</admin-surface-card>| Prop | 类型 | 默认值 | 说明 |
|---|---|---|---|
fixed | Boolean | false | 使用 fixed 定位 |
插槽:default
📸 媒体与上传
MediaPicker
src/components/media/picker.vue
媒体选择器,表单中选择图片/视频/文件的标准方式。选中的文件以缩略图展示,支持拖拽排序(vuedraggable),点击可预览。内部打开 Media 媒体库弹窗进行选择。
<!-- 单图选择 -->
<media-picker v-model="formData.cover" type="image" />
<!-- 多图选择,最多 9 张 -->
<media-picker v-model="formData.images" type="image" :limit="9" />
<!-- 视频选择 -->
<media-picker v-model="formData.video" type="video" />| Prop | 类型 | 默认值 | 说明 |
|---|---|---|---|
modelValue | String|Array | [] | 绑定值,limit=1 时为字符串,否则为数组 |
type | String | 'image' | 媒体类型:image、video、file |
size | String | '100px' | 缩略图尺寸 |
limit | Number | 1 | 最大选择数量,-1 不限 |
disabled | Boolean | false | 禁用 |
hiddenUpload | Boolean | false | 隐藏上传入口 |
module | String | '' | 按模块筛选 |
tag | String | '' | 按标签筛选 |
事件:update:modelValue、change
暴露方法:showPopup(index)、handleClose()
Media
src/components/media/index.vue
完整媒体库浏览器,包含分类树、搜索、网格/列表切换、批量删除、批量移动、重命名和分页。通常由 MediaPicker 内部调用,也可在媒体管理页面单独使用(mode="page")。
| Prop | 类型 | 默认值 | 说明 |
|---|---|---|---|
type | String | 'image' | 媒体类型 |
mode | String | 'picker' | picker(嵌入弹窗)或 page(独立页面) |
limit | Number | 1 | 选择数量限制 |
pageSize | Number | 15 | 每页数量 |
事件:change
MediaPreview
src/components/media/preview.vue
媒体预览弹层,图片使用 el-image-viewer,视频使用 VideoPlayer。通过 v-model 控制显隐。
<media-preview v-model="showPreview" :url="previewUrl" :type="previewType" />| Prop | 类型 | 默认值 | 说明 |
|---|---|---|---|
modelValue | Boolean | false | 显示/隐藏 |
url | String | '' | 媒体 URL |
type | String | 'image' | image 或 video |
MediaFileItem
src/components/media/file.vue
单个媒体文件缩略图渲染器。图片显示 el-image,视频显示 <video>,文件显示带扩展名图标卡片。通常由 MediaPicker 内部使用。
| Prop | 类型 | 默认值 | 说明 |
|---|---|---|---|
url | String | — | 文件 URL |
fileSize | String | '100px' | 显示尺寸 |
type | String | 'image' | 文件类型 |
name | String | '' | 文件名 |
插槽:default(覆盖层内容,如选中勾)
Upload
src/components/upload/index.vue
文件上传组件,基于 el-upload 封装。自动携带 Authorization 请求头,图片上传前自动压缩,支持进度弹窗。上传端点为 {baseUrl}/{urlPrefix}/system/upload/file。
<upload type="image" @change="onUploaded">
<el-button type="primary">上传图片</el-button>
</upload>| Prop | 类型 | 默认值 | 说明 |
|---|---|---|---|
type | String | 'image' | 上传类型:image、video、file |
engine | String | '' | 存储引擎标识 |
multiple | Boolean | true | 多文件选择 |
limit | Number | 10 | 最大文件数 |
data | Object | {} | 附带的额外表单数据 |
showProgress | Boolean | false | 显示上传进度弹窗 |
事件:change(文件对象)、success(响应)、error(文件)
Editor
src/components/editor/index.vue
基于 TipTap 的富文本编辑器,提供完整工具栏:标题、加粗/斜体/下划线/删除线/高亮、字号、行高、文字颜色、对齐、列表、任务列表、引用、代码块、链接、图片/视频插入(通过 MediaPicker)、表格、源码编辑、Markdown 导入、全屏,以及可选的 AI 集成(润色/摘要/翻译/续写/自定义)。
<editor v-model="formData.content" mode="default" height="500px" :enable-ai="true" />| Prop | 类型 | 默认值 | 说明 |
|---|---|---|---|
modelValue | String | '' | HTML 内容(v-model) |
mode | String | 'default' | default(完整工具栏)或 simple(精简工具栏) |
height | String|Number | '100%' | 编辑器高度 |
width | String|Number | 'auto' | 编辑器宽度 |
enableAi | Boolean | true | 显示 AI 下拉菜单 |
allowMarkdownImport | Boolean | true | 显示 Markdown 导入按钮 |
事件:update:modelValue
VideoPlayer
src/components/video-player/index.vue
视频播放器,封装 vue3-video-play。暴露 play() 和 pause() 方法供外部控制。
<video-player :src="videoUrl" width="100%" :poster="coverUrl" />| Prop | 类型 | 默认值 | 说明 |
|---|---|---|---|
src | String | — | 视频地址(必填) |
width | String | — | 播放器宽度 |
height | String | — | 播放器高度 |
poster | String | — | 封面图 URL |
暴露方法:play()、pause()
ImageView
src/components/image-view/index.vue
增强版 el-image,额外提供 width、height、radius 快捷属性(自动转换带单位),加载失败时显示占位图标。
<image-view :src="url" width="200px" height="150px" radius="8px" fit="cover" />| Prop | 类型 | 默认值 | 说明 |
|---|---|---|---|
width | String|Number | 'auto' | 宽度 |
height | String|Number | 'auto' | 高度 |
radius | String|Number | 0 | 圆角 |
其余属性透传至 el-image。
🎛️ 表单控件
DatePicker
src/components/date-picker/index.vue
日期选择器,封装 el-date-picker。日期范围模式下分别绑定 startTime 和 endTime,无需手动处理数组格式。
<!-- 单日期 -->
<date-picker v-model="formData.date" />
<!-- 日期范围 -->
<date-picker v-model:type="'daterange'" v-model:startTime="query.start" v-model:endTime="query.end" />| Prop | 类型 | 默认值 | 说明 |
|---|---|---|---|
modelValue | String | '' | 日期值(单日期模式) |
startTime | String | '' | 开始日期(范围模式) |
endTime | String | '' | 结束日期(范围模式) |
type | String | 'date' | date 或 daterange |
format | String | 'YYYY-MM-DD' | 日期格式 |
clearable | Boolean | true | 可清除 |
ColorPicker
src/components/color-picker/index.vue
颜色选择器,带预设色板、十六进制输入框和重置按钮。
<color-picker v-model="formData.color" default-color="#409EFF" />| Prop | 类型 | 默认值 | 说明 |
|---|---|---|---|
modelValue | String | — | 颜色值(v-model) |
defaultColor | String | — | 重置目标颜色 |
IconPicker
src/components/icon/picker.vue
图标选择弹窗,三个标签页分别展示 Element Plus 图标、Bootstrap Icons 和本地 SVG 图标,支持搜索。触发器显示当前图标和清除按钮。
<icon-picker v-model="formData.icon" />| Prop | 类型 | 默认值 | 说明 |
|---|---|---|---|
modelValue | String | '' | 图标名称(v-model) |
disabled | Boolean | false | 禁用 |
事件:update:modelValue、change
LinkPicker
src/components/link/picker.vue
链接路径选择器,弹窗内分标签页提供系统页面、文章页面和自定义 URL 三种选择方式。触发器为只读输入框,显示已选路径。
<link-picker v-model="formData.link" />| Prop | 类型 | 默认值 | 说明 |
|---|---|---|---|
modelValue | String | — | 链接路径(v-model) |
disabled | Boolean | false | 禁用 |
事件:update:modelValue
DataPicker
src/components/data-picker/index.vue
注册式数据选择弹窗。模块通过 registerDataPicker() 注册数据源配置(搜索字段、表格列、API、结果映射),使用时传入 type 即可弹出对应选择器。适用于商品、优惠券等模块提供的数据选择。
<data-picker type="product" v-model="showPicker" @change="onProductSelected" />| Prop | 类型 | 默认值 | 说明 |
|---|---|---|---|
type | String | — | 注册键名(必填) |
modelValue | Boolean | false | 控制弹窗开关 |
事件:update:modelValue、change(映射后的行数据)
注册 API(data-picker/registry.ts):
import { registerDataPicker } from '@/components/data-picker/registry'
registerDataPicker('product', {
title: '选择商品',
api: productList,
searchFields: [...],
tableColumns: [...],
resultFields: { id: 'id', name: 'name', price: 'price' }
})UserPicker
src/components/user-picker/index.vue
用户选择弹窗,支持关键字搜索(用户 ID / 昵称 / 手机号)、时间范围筛选和分页用户列表。
<user-picker v-model="showPicker" @change="onUserSelected" />| Prop | 类型 | 默认值 | 说明 |
|---|---|---|---|
modelValue | Boolean | false | 控制弹窗开关 |
事件:update:modelValue、change(选中的用户行对象)
PopoverInput
src/components/popover-input/index.vue
行内编辑气泡。点击触发元素后弹出小型输入框(支持文本、下拉、日期三种类型),确认后 emit 新值。适合表格内的快速编辑。
<popover-input :value="row.sort" type="text" @confirm="updateSort(row, $event)">
<el-button size="small">{{ row.sort }}</el-button>
</popover-input>| Prop | 类型 | 默认值 | 说明 |
|---|---|---|---|
value | String|Number | — | 当前值 |
type | String | 'text' | text、select、date |
width | Number|String | '300px' | 气泡宽度 |
placeholder | String | — | 输入框占位文本 |
disabled | Boolean | false | 禁用 |
options | Array | [] | 下拉选项(select 类型) |
size | String | 'default' | 尺寸 |
limit | Number | 200 | 最大字符数 |
插槽:default(触发元素)
事件:confirm(输入值)
ReadonlyCopyField
src/components/copy/readonly-copy-field.vue
只读值展示,带复制按钮。空值时显示"保存后生成"占位文本。自动包裹为 el-form-item。
<readonly-copy-field label="API 密钥" v-model="apiKey" tip="请妥善保管" />| Prop | 类型 | 默认值 | 说明 |
|---|---|---|---|
label | String | '' | 表单项标签 |
modelValue | String | '' | 显示值 |
tip | String | '' | 帮助文本 |
📊 数据展示
Pagination
src/components/pagination/index.vue
分页组件,封装 el-pagination,绑定 { page, size, count } 形式的 pager 对象。切换每页条数时自动重置到第 1 页。
<pagination v-model="pager" @change="loadData" />| Prop | 类型 | 默认值 | 说明 |
|---|---|---|---|
modelValue | Object | {} | pager 对象,含 page、size、count |
pageSizes | Number[] | [15, 20, 30, 40] | 每页条数选项 |
layout | String | 'total, prev, pager, next' | 布局 |
事件:update:modelValue、change
OverflowTooltip
src/components/overflow-tooltip/index.vue
文本溢出时才显示 Tooltip。通过 mouseenter 时比较 scrollWidth 和 offsetWidth 动态决定是否启用 Tooltip,避免短文本也弹出提示。
<overflow-tooltip :content="row.description" />| Prop | 类型 | 默认值 | 说明 |
|---|---|---|---|
content | String | — | 文本内容 |
teleported | Boolean | false | 挂载到 body |
placement | String | 'top' | 弹出位置 |
overfloType | String | 'ellipsis' | 溢出样式:ellipsis、unset、clip |
其余属性透传至 el-tooltip content。
DictValue
src/components/dict-value/index.vue
字典值渲染器。根据 options 数组将值映射为标签文字,支持逗号分隔的多值。适合表格列中展示字典/枚举的中文含义。
<dict-value :options="statusOptions" :value="row.status" />| Prop | 类型 | 默认值 | 说明 |
|---|---|---|---|
options | Array | [] | 选项数组 |
value | Any | — | 选中值,支持字符串或数组 |
config | Object | { label: 'name', value: 'value' } | 字段名映射 |
Icon
src/components/icon/index.vue
统一图标组件,根据 name 前缀自动选择渲染方式:
el-icon-*:Element Plus 图标bi bi-*:Bootstrap Icons- 其他:本地 SVG 图标(svg-icon sprite)
<icon name="el-icon-Search" size="18px" />
<icon name="bi bi-house" />
<icon name="icon-custom" />| Prop | 类型 | 默认值 | 说明 |
|---|---|---|---|
name | String | — | 图标名称(必填) |
size | String|Number | '14px' | 尺寸 |
color | String | 'inherit' | 颜色 |
🏗️ 布局与容器
AdminListShell
src/components/admin/list-shell.vue
列表页根容器,flex 纵向排列,12px 间距。用于统一堆叠搜索栏、表格和分页区域。
<admin-list-shell>
<!-- 搜索区域 -->
<!-- 表格 -->
<!-- 分页 -->
</admin-list-shell>无 Props。插槽:default
AdminSurfaceCard
src/components/admin/surface-card.vue
通用内容卡片,带可选标题栏(标题 + 描述 + extra 插槽)和圆角阴影样式。
<admin-surface-card title="基本信息" description="填写用户基本资料">
<template #extra>
<el-button size="small">操作</el-button>
</template>
<!-- 内容 -->
</admin-surface-card>| Prop | 类型 | 默认值 | 说明 |
|---|---|---|---|
title | String | '' | 标题 |
description | String | '' | 描述 |
compact | Boolean | false | 减少内容区顶部间距 |
插槽:extra(标题栏右侧)、default
PageHeroShell
src/components/page-shell/hero-shell.vue
Hero 风格页面头部,带渐变背景、标题、描述、状态徽章和提示警告。用于详情/设置等需要醒目头部的页面。
<page-hero-shell title="订单详情" eyebrow="ORD-2024" status-text="已完成" status-type="success">
<template #meta>
<el-button>操作</el-button>
</template>
<!-- 下方内容 -->
</page-hero-shell>| Prop | 类型 | 默认值 | 说明 |
|---|---|---|---|
eyebrow | String | '' | 标题上方小标签 |
title | String | '' | 主标题 |
description | String | '' | 描述 |
tip | String | '' | 警告提示文本 |
statusText | String | '' | 状态徽章文字 |
statusType | String | 'info' | 状态类型:info、success、warning |
插槽:meta(右上角区域)、default
PageSectionCard
src/components/page-shell/section-card.vue
分节内容卡片,带标题头(标题 + 可选徽章 + 描述)和内容区,头部分隔线。用于在 PageHeroShell 或 AdminSurfaceCard 内分组展示内容。
<page-section-card title="收货信息" badge="必填">
<!-- 表单内容 -->
</page-section-card>| Prop | 类型 | 默认值 | 说明 |
|---|---|---|---|
title | String | '' | 标题 |
description | String | '' | 描述 |
badge | String | '' | 标题旁徽章文字 |
插槽:extra(标题栏右侧)、default
DelWrap
src/components/del-wrap/index.vue
删除/拖拽覆盖层。包裹图片或项目元素,hover 时显示关闭按钮和可选拖拽手柄。常用于媒体缩略图和可排序列表项。
<del-wrap show-drag @close="removeItem(index)">
<image-view :src="item.url" width="100px" height="100px" />
</del-wrap>| Prop | 类型 | 默认值 | 说明 |
|---|---|---|---|
showClose | Boolean | true | 显示关闭按钮 |
showDrag | Boolean | false | 显示拖拽手柄 |
事件:close
🔗 其他
AppLink
src/components/app-link/index.vue
智能链接组件。内部路径渲染为 <router-link>,外部 URL 渲染为 <a target="_blank">。
<app-link to="/system/user">用户管理</app-link>
<app-link to="https://example.com">外部链接</app-link>| Prop | 类型 | 默认值 | 说明 |
|---|---|---|---|
to | String|Object | — | 路由路径或外部 URL(必填) |
replace | Boolean | — | 使用 replace 模式 |
插槽:default
Captcha
src/components/captcha/index.vue
验证码组件,支持滑块和点击两种验证类型。通过模板 ref 调用 show() 触发。
<captcha ref="captchaRef" captcha-type="slide" @success="onVerify" />| Prop | 类型 | 默认值 | 说明 |
|---|---|---|---|
captchaType | String | — | 验证类型:slide、points(必填) |
explain | String | — | 说明文字 |
imgSize | Object | { width: '400px', height: '200px' } | 验证图尺寸 |
事件:success(验证结果)、close
暴露方法:show()
LanguageSwitch
src/components/language/index.vue
顶栏语言切换下拉框。仅在后端多语言功能启用且配置了多种语言时显示。选择后自动切换语言并提示成功。
无 Props,自包含(从 Store 读取语言列表)。
