DukeDuke
主页
项目文档
技术文档
  • 单机版
  • 微服务
  • 代办项目
  • 优鲜项目
项目管理
关于我们
主页
项目文档
技术文档
  • 单机版
  • 微服务
  • 代办项目
  • 优鲜项目
项目管理
关于我们
  • 单体脚手架

    • 项目简介
    • 运行环境
    • 项目结构
    • 前端开发手册
    • 前端组件详解
    • 后端开发手册
    • 后端模块详解
    • 部署运维手册

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 说明

使用示例

  • 基础用法
  • 高级用法
  • 常见场景

注意事项

  • 使用限制
  • 性能考虑
  • 兼容性说明
最近更新:: 2025/8/14 09:20
Contributors: Duke
Prev
前端开发手册
Next
后端开发手册