Duke Admin 前端组件详解
目录
组件概述
Duke Admin 前端采用组件化开发模式,所有组件都基于 Vue 3 + TypeScript 开发,使用 Composition API。组件分为公共组件、布局组件和业务组件三大类。
组件分类
- 公共组件: 可在多个页面复用的通用组件
- 布局组件: 页面布局相关的组件
- 业务组件: 特定业务功能的组件
公共组件
1. DictTag 字典标签组件
用于显示字典值的标签组件,支持多种显示样式。
组件位置
src/components/DictTag/
功能特性
- 支持多种显示样式(标签、文本、徽章)
- 支持自定义颜色
- 支持多语言
- 支持缓存字典数据
使用示例
<template>
<div>
<!-- 标签样式 -->
<DictTag :options="dict.type" :value="scope.row.status" />
<!-- 文本样式 -->
<DictTag :options="dict.type" :value="scope.row.status" type="text" />
<!-- 徽章样式 -->
<DictTag :options="dict.type" :value="scope.row.status" type="badge" />
</div>
</template>
<script setup lang="ts">
import { useDict } from "@/hooks/useDict";
const { dict } = useDict("sys_normal_disable");
</script>
Props 说明
interface DictTagProps {
options: DictOption[]; // 字典选项
value: string | number; // 当前值
type?: "tag" | "text" | "badge"; // 显示类型
color?: string; // 自定义颜色
size?: "small" | "medium" | "large"; // 尺寸
}
2. SvgIcon SVG 图标组件
用于显示 SVG 图标的组件,支持动态加载和缓存。
组件位置
src/components/SvgIcon/
功能特性
- 支持动态加载 SVG 文件
- 支持图标缓存
- 支持自定义颜色和尺寸
- 支持点击事件
使用示例
<template>
<div>
<!-- 基础用法 -->
<SvgIcon icon-class="user" />
<!-- 自定义样式 -->
<SvgIcon
icon-class="edit"
class-name="custom-icon"
color="#409EFF"
:size="20"
/>
<!-- 点击事件 -->
<SvgIcon
icon-class="delete"
@click="handleDelete"
style="cursor: pointer"
/>
</div>
</template>
Props 说明
interface SvgIconProps {
iconClass: string; // 图标类名
className?: string; // 自定义类名
color?: string; // 图标颜色
size?: number; // 图标尺寸
}
3. Pagination 分页组件
分页组件,支持多种分页模式和自定义配置。
组件位置
src/components/Pagination/
功能特性
- 支持多种分页模式
- 支持自定义每页条数
- 支持快速跳转
- 支持总数显示
使用示例
<template>
<div>
<Pagination
v-model:page="queryParams.pageNum"
v-model:limit="queryParams.pageSize"
:total="total"
:page-sizes="[10, 20, 50, 100]"
layout="total, sizes, prev, pager, next, jumper"
@pagination="getList"
/>
</div>
</template>
<script setup lang="ts">
import { ref } from "vue";
const queryParams = ref({
pageNum: 1,
pageSize: 10,
});
const total = ref(0);
const getList = () => {
// 获取列表数据
};
</script>
Props 说明
interface PaginationProps {
page: number; // 当前页码
limit: number; // 每页条数
total: number; // 总条数
pageSizes?: number[]; // 每页条数选项
layout?: string; // 布局配置
background?: boolean; // 是否显示背景色
small?: boolean; // 是否使用小尺寸
}
4. Editor 富文本编辑器
基于 Quill 的富文本编辑器组件。
组件位置
src/components/Editor/
功能特性
- 支持富文本编辑
- 支持图片上传
- 支持工具栏配置
- 支持内容验证
使用示例
<template>
<div>
<Editor
v-model="content"
:height="300"
:toolbar="toolbar"
@change="handleChange"
/>
</div>
</template>
<script setup lang="ts">
import { ref } from "vue";
const content = ref("");
const toolbar = [["bold", "italic", "underline"], ["image", "link"], ["clean"]];
const handleChange = (html: string) => {
console.log("内容变化:", html);
};
</script>
Props 说明
interface EditorProps {
modelValue: string; // 绑定值
height?: number; // 编辑器高度
toolbar?: any[]; // 工具栏配置
placeholder?: string; // 占位符
readonly?: boolean; // 是否只读
}
5. SSEStatus SSE 状态组件
用于显示 Server-Sent Events 连接状态的组件。
组件位置
src/components/SSEStatus.vue
功能特性
- 显示 SSE 连接状态
- 支持手动重连
- 显示连接时间
- 支持状态切换
使用示例
<template>
<div>
<SSEStatus
:connected="sseConnected"
:last-message="lastMessage"
@reconnect="handleReconnect"
/>
</div>
</template>
<script setup lang="ts">
import { ref } from "vue";
const sseConnected = ref(false);
const lastMessage = ref("");
const handleReconnect = () => {
// 重新连接 SSE
};
</script>
布局组件
1. Layout 主布局组件
应用的主布局组件,包含侧边栏、顶部导航和主内容区域。
组件位置
src/layout/
主要子组件
- Sidebar: 侧边栏组件
- Navbar: 顶部导航组件
- AppMain: 主内容区域组件
- TagsView: 标签页组件
功能特性
- 响应式布局
- 侧边栏折叠/展开
- 面包屑导航
- 标签页导航
- 用户信息显示
使用示例
<template>
<Layout>
<template #sidebar>
<Sidebar />
</template>
<template #navbar>
<Navbar />
</template>
<template #main>
<AppMain />
</template>
</Layout>
</template>
2. Sidebar 侧边栏组件
侧边栏导航组件,支持多级菜单和权限控制。
功能特性
- 多级菜单支持
- 权限控制
- 菜单折叠/展开
- 路由高亮
- 自定义图标
菜单配置
interface MenuItem {
path: string; // 路由路径
name: string; // 菜单名称
icon?: string; // 图标
children?: MenuItem[]; // 子菜单
hidden?: boolean; // 是否隐藏
meta?: {
title: string; // 标题
icon: string; // 图标
roles?: string[]; // 角色权限
};
}
3. Navbar 顶部导航组件
顶部导航栏组件,包含用户信息、通知、设置等功能。
功能特性
- 用户信息显示
- 通知消息
- 全屏切换
- 主题切换
- 用户设置
主要功能
- 用户头像: 显示当前用户头像
- 通知中心: 显示系统通知
- 全屏按钮: 切换全屏模式
- 设置按钮: 打开用户设置
- 退出登录: 安全退出系统
4. TagsView 标签页组件
标签页导航组件,支持多标签页管理。
功能特性
- 多标签页支持
- 标签页关闭
- 右键菜单
- 标签页刷新
- 标签页固定
右键菜单功能
- 刷新当前页
- 关闭当前页
- 关闭其他页
- 关闭所有页
- 固定标签页
业务组件
1. 用户管理组件
用户管理相关的业务组件。
组件列表
- UserList: 用户列表组件
- UserForm: 用户表单组件
- UserDetail: 用户详情组件
- UserImport: 用户导入组件
UserList 组件
<template>
<div class="user-list">
<!-- 搜索表单 -->
<el-form :model="queryParams" ref="queryForm" :inline="true">
<el-form-item label="用户名" prop="userName">
<el-input
v-model="queryParams.userName"
placeholder="请输入用户名"
clearable
@keyup.enter="handleQuery"
/>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="handleQuery">搜索</el-button>
<el-button @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
<!-- 操作按钮 -->
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button type="primary" @click="handleAdd">新增</el-button>
</el-col>
<el-col :span="1.5">
<el-button type="danger" @click="handleDelete">删除</el-button>
</el-col>
</el-row>
<!-- 数据表格 -->
<el-table
v-loading="loading"
:data="userList"
@selection-change="handleSelectionChange"
>
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="用户名" prop="userName" />
<el-table-column label="昵称" prop="nickName" />
<el-table-column label="状态" align="center">
<template #default="scope">
<DictTag
:options="dict.sys_normal_disable"
:value="scope.row.status"
/>
</template>
</el-table-column>
<el-table-column
label="操作"
align="center"
class-name="small-padding fixed-width"
>
<template #default="scope">
<el-button type="text" @click="handleUpdate(scope.row)"
>修改</el-button
>
<el-button type="text" @click="handleDelete(scope.row)"
>删除</el-button
>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<Pagination
v-model:page="queryParams.pageNum"
v-model:limit="queryParams.pageSize"
:total="total"
@pagination="getList"
/>
</div>
</template>
2. 角色管理组件
角色管理相关的业务组件。
组件列表
- RoleList: 角色列表组件
- RoleForm: 角色表单组件
- RolePermission: 角色权限分配组件
RolePermission 组件
<template>
<div class="role-permission">
<el-tree
ref="treeRef"
:data="menuOptions"
show-checkbox
node-key="id"
empty-text="加载中,请稍候"
:props="defaultProps"
/>
<div class="dialog-footer">
<el-button @click="cancel">取 消</el-button>
<el-button type="primary" @click="confirm">确 定</el-button>
</div>
</div>
</template>
<script setup lang="ts">
import { ref, onMounted } from "vue";
import { getMenuTree } from "@/api/menu";
const treeRef = ref();
const menuOptions = ref([]);
const defaultProps = {
children: "children",
label: "label",
};
onMounted(async () => {
const data = await getMenuTree();
menuOptions.value = data;
});
const confirm = () => {
const checkedKeys = treeRef.value.getCheckedKeys();
const halfCheckedKeys = treeRef.value.getHalfCheckedKeys();
// 保存权限配置
};
</script>
3. 系统监控组件
系统监控相关的业务组件。
组件列表
- OnlineUser: 在线用户监控
- SystemInfo: 系统信息监控
- CacheMonitor: 缓存监控
- JobMonitor: 定时任务监控
OnlineUser 组件
<template>
<div class="online-user">
<el-table :data="onlineUserList" v-loading="loading">
<el-table-column label="会话编号" prop="tokenId" />
<el-table-column label="登录名称" prop="userName" />
<el-table-column label="主机" prop="ipaddr" />
<el-table-column label="登录时间" prop="loginTime" />
<el-table-column label="操作" align="center">
<template #default="scope">
<el-button type="text" @click="handleForceLogout(scope.row)">
强退
</el-button>
</template>
</el-table-column>
</el-table>
</div>
</template>
<script setup lang="ts">
import { ref, onMounted } from "vue";
import { getOnlineUserList, forceLogout } from "@/api/monitor";
const loading = ref(false);
const onlineUserList = ref([]);
const getList = async () => {
loading.value = true;
try {
const data = await getOnlineUserList();
onlineUserList.value = data;
} finally {
loading.value = false;
}
};
const handleForceLogout = async (row: any) => {
await forceLogout(row.tokenId);
getList();
};
onMounted(() => {
getList();
});
</script>
组件开发规范
1. 组件命名规范
文件命名
- 组件文件使用 PascalCase
- 页面组件使用 kebab-case
- 工具组件使用 camelCase
组件命名
- 组件名使用 PascalCase
- 避免与 HTML 元素冲突
- 使用有意义的名称
2. 组件结构规范
标准组件结构
<template>
<!-- 模板内容 -->
</template>
<script setup lang="ts">
// 导入
import { ref, onMounted } from "vue";
import type { ComponentProps } from "./types";
// Props 定义
interface Props {
title: string;
data: any[];
}
const props = withDefaults(defineProps<Props>(), {
title: "",
data: () => [],
});
// Emits 定义
const emit = defineEmits<{
change: [value: string];
submit: [data: any];
}>();
// 响应式数据
const loading = ref(false);
// 计算属性
const computedValue = computed(() => {
return props.data.length;
});
// 方法
const handleSubmit = () => {
emit("submit", props.data);
};
// 生命周期
onMounted(() => {
// 初始化逻辑
});
</script>
<style scoped>
/* 样式 */
</style>
3. Props 和 Emits 规范
Props 定义
interface ComponentProps {
// 必填属性
title: string;
// 可选属性
data?: any[];
// 带默认值的属性
size?: "small" | "medium" | "large";
disabled?: boolean;
}
const props = withDefaults(defineProps<ComponentProps>(), {
data: () => [],
size: "medium",
disabled: false,
});
Emits 定义
const emit = defineEmits<{
// 简单事件
change: [value: string];
// 复杂事件
submit: [data: any, isValid: boolean];
// 无参数事件
close: [];
}>();
4. 样式规范
CSS 类命名
- 使用 BEM 命名规范
- 组件根元素使用组件名作为类名
- 子元素使用
__连接 - 修饰符使用
--连接
样式示例
<style scoped>
.user-list {
padding: 20px;
}
.user-list__header {
margin-bottom: 20px;
}
.user-list__table {
margin-top: 20px;
}
.user-list__pagination {
margin-top: 20px;
text-align: right;
}
.user-list--loading {
opacity: 0.6;
}
</style>
5. 组件文档规范
每个组件都应该包含以下文档:
组件说明
- 组件功能描述
- 使用场景
- 依赖关系
API 文档
- Props 说明
- Events 说明
- Slots 说明
使用示例
- 基础用法
- 高级用法
- 常见场景
注意事项
- 使用限制
- 性能考虑
- 兼容性说明
