diff --git a/doc/前端开发文档.md b/doc/前端开发文档.md new file mode 100644 index 0000000..f06ab8d --- /dev/null +++ b/doc/前端开发文档.md @@ -0,0 +1,1464 @@ +# Lyzsys 前端开发文档 + +## 目录 + +- [项目概述](#项目概述) +- [技术栈](#技术栈) +- [项目结构](#项目结构) +- [开发指南](#开发指南) +- [核心功能](#核心功能) +- [组件库](#组件库) +- [样式指南](#样式指南) +- [部署指南](#部署指南) + +--- + +## 项目概述 + +Lyzsys 前端是基于 Vue 3 + TypeScript + Element Plus 构建的现代化管理系统,采用 Composition API 和模块化架构,支持多租户、权限管理、国际化等功能。 + +### 核心特性 + +- **Vue 3 Composition API**: 充分利用 Vue 3 的新特性 +- **TypeScript**: 完整的类型支持 +- **Vite 构建**: 极速的开发体验 +- **Element Plus**: 企业级 UI 组件库 +- **权限管理**: 基于 RBAC 的权限控制 +- **国际化**: 支持多语言切换 +- **主题定制**: 灵活的主题配置 + +--- + +## 技术栈 + +### 核心框架 + +| 技术 | 版本 | 说明 | +|------|------|------| +| Vue | 3.2+ | 渐进式 JavaScript 框架 | +| TypeScript | 4.x | JavaScript 的超集 | +| Vite | 4.x | 下一代前端构建工具 | +| Vue Router | 4.x | Vue.js 官方路由管理器 | +| Pinia | 2.x | Vue 官方状态管理库 | + +### UI 框架 + +| 技术 | 版本 | 说明 | +|------|------|------| +| Element Plus | 2.x | 基于 Vue 3 的组件库 | +| UnoCSS | - | 原子化 CSS 引擎 | +| Animate.css | - | CSS 动画库 | +| Iconify | - | 统一的图标框架 | + +### 工具库 + +| 技术 | 版本 | 说明 | +|------|------|------| +| Axios | - | HTTP 客户端 | +| Day.js | - | 轻量级日期处理库 | +| Lodash | - | JavaScript 实用工具库 | +| Crypto-js | - | JavaScript 加密库 | +| DOMPurify | - | XSS 过滤器 | +| WangEditor | - | 富文本编辑器 | +| ECharts | - | 数据可视化库 | + +### 开发工具 + +| 技术 | 版本 | 说明 | +|------|------|------| +| ESLint | - | 代码检查工具 | +| Prettier | - | 代码格式化工具 | +| Stylelint | - | CSS 代码检查工具 | +| Commitlint | - | Git 提交信息检查 | +| unplugin-auto-import | - | 自动导入 API | +| unplugin-vue-components | - | 自动导入组件 | + +--- + +## 项目结构 + +### 目录结构 + +``` +lyzsys-ui-admin/ +├── .github/ # GitHub Actions 配置 +├── .husky/ # Git Hooks 配置 +├── .vscode/ # VSCode 配置 +├── public/ # 静态资源 +├── src/ # 源代码 +│ ├── api/ # API 接口管理 +│ │ ├── ai/ # AI 相关接口 +│ │ ├── bpm/ # 工作流接口 +│ │ ├── crm/ # CRM 接口 +│ │ ├── erp/ # ERP 接口 +│ │ ├── system/ # 系统管理接口 +│ │ └── login/ # 登录接口 +│ ├── assets/ # 静态资源 +│ │ ├── images/ # 图片 +│ │ ├── styles/ # 样式文件 +│ │ └── svg/ # SVG 图标 +│ ├── components/ # 全局组件 +│ ├── config/ # 全局配置 +│ ├── directives/ # 自定义指令 +│ ├── hooks/ # 组合式函数 +│ ├── layout/ # 布局组件 +│ ├── locales/ # 国际化文件 +│ │ ├── en/ # 英文 +│ │ └── zh-CN/ # 简体中文 +│ ├── plugins/ # 插件配置 +│ ├── router/ # 路由配置 +│ ├── store/ # 状态管理 +│ │ ├── modules/ # 模块化 Store +│ │ └── index.ts # Store 入口 +│ ├── styles/ # 全局样式 +│ ├── types/ # TypeScript 类型定义 +│ ├── utils/ # 工具函数 +│ ├── views/ # 页面组件 +│ ├── App.vue # 应用根组件 +│ ├── main.ts # 应用入口 +│ └── permission.ts # 路由权限控制 +├── types/ # 全局类型定义 +├── .env.base # 基础环境变量 +├── .env.dev # 开发环境变量 +├── .env.pro # 生产环境变量 +├── .env.test # 测试环境变量 +├── .eslintrc.js # ESLint 配置 +├── .gitignore # Git 忽略文件 +├── .prettierrc.js # Prettier 配置 +├── index.html # HTML 模板 +├── package.json # 项目依赖 +├── tsconfig.json # TypeScript 配置 +└── vite.config.ts # Vite 配置 +``` + +### 核心文件说明 + +#### main.ts + +应用入口文件,负责初始化 Vue 应用: + +```typescript +import { createApp } from 'vue' +import App from './App.vue' +import router from './router' +import { setupStore } from './store' +import { setupRouter } from './router' +import { setupElPlus, setupIcons } from './plugins' + +async function bootstrap() { + const app = createApp(App) + + // 配置 Store + setupStore(app) + + // 配置 Router + await setupRouter(app) + + // 配置插件 + setupElPlus(app) + setupIcons(app) + + // 挂载应用 + app.mount('#app') +} + +bootstrap() +``` + +#### App.vue + +应用根组件: + +```vue + + + +``` + +#### permission.ts + +路由权限控制: + +```typescript +import router from './router' +import { useUserStore } from './store/modules/user' +import { usePermissionStore } from './store/modules/permission' + +router.beforeEach(async (to, from, next) => { + const userStore = useUserStore() + const permissionStore = usePermissionStore() + + // 检查是否登录 + if (userStore.getToken) { + // 已登录 + if (to.path === '/login') { + next({ path: '/' }) + } else { + // 检查是否已获取权限 + if (permissionStore.getIsAddRouters) { + next() + } else { + // 获取权限和路由 + await permissionStore.generateRoutes() + next({ ...to, replace: true }) + } + } + } else { + // 未登录 + if (to.path === '/login') { + next() + } else { + next(`/login?redirect=${to.path}`) + } + } +}) +``` + +--- + +## 开发指南 + +### 环境准备 + +#### 必需软件 + +| 软件 | 版本要求 | 下载地址 | +|------|----------|----------| +| Node.js | 16+ | https://nodejs.org/ | +| pnpm | 8+ | https://pnpm.io/ | +| VSCode | 最新版 | https://code.visualstudio.com/ | + +#### 推荐插件 + +- Vue - Official +- TypeScript Vue Plugin (Volar) +- ESLint +- Prettier - Code formatter +- Stylelint +- UnoCSS + +### 快速开始 + +#### 1. 克隆项目 + +```bash +git clone https://github.com/your-org/lyzsys.git +cd lyzsys/lyzsys-ui-admin +``` + +#### 2. 安装依赖 + +```bash +pnpm install +``` + +#### 3. 启动开发服务器 + +```bash +pnpm dev +``` + +#### 4. 访问应用 + +- 应用地址: http://localhost:5173 +- 用户名: admin +- 密码: admin123 + +### 开发规范 + +#### 命名规范 + +**文件命名**: +- 组件文件:大驼峰 `UserList.vue` +- 工具文件:小驼峰 `formatDate.ts` +- 样式文件:小驼峰 `userList.scss` + +**变量命名**: +```typescript +// 常量:全大写 +const MAX_SIZE = 100 + +// 变量:小驼峰 +const userName = 'admin' + +// 接口:大驼峰 +interface UserInfo { + id: number + name: string +} + +// 类型:大驼峰 +type UserRole = 'admin' | 'user' + +// 枚举:大驼峰 +enum UserStatus { + Active = 'active', + Inactive = 'inactive' +} +``` + +**组件命名**: +```vue + +``` + +#### 注释规范 + +**函数注释**: +```typescript +/** + * 获取用户列表 + * @param params 查询参数 + * @returns 用户列表 + */ +async function getUserList(params: UserPageReqVO) { + return await userApi.getUserPage(params) +} +``` + +**组件注释**: +```vue + + +``` + +#### 代码风格 + +**使用 Composition API**: +```vue + +``` + +**使用 TypeScript**: +```typescript +interface User { + id: number + name: string + email: string +} + +type UserRole = 'admin' | 'user' | 'guest' + +const user: User = { + id: 1, + name: 'Admin', + email: 'admin@example.com' +} + +const role: UserRole = 'admin' +``` + +### 组件开发 + +#### 创建组件 + +```vue + + + + + + +``` + +#### 组件通信 + +**Props**: +```vue + +``` + +**Emits**: +```vue + +``` + +**Slots**: +```vue + +``` + +### API 开发 + +#### API 定义 + +```typescript +// api/system/user/index.ts +import request from '@/utils/request' + +// 获取用户分页 +export function getUserPage(params: UserPageReqVO) { + return request.get({ url: '/system/user/page', params }) +} + +// 获取用户详情 +export function getUser(id: number) { + return request.get({ url: `/system/user/get?id=${id}` }) +} + +// 创建用户 +export function createUser(data: UserCreateReqVO) { + return request.post({ url: '/system/user/create', data }) +} + +// 更新用户 +export function updateUser(data: UserUpdateReqVO) { + return request.put({ url: '/system/user/update', data }) +} + +// 删除用户 +export function deleteUser(id: number) { + return request.delete({ url: `/system/user/delete?id=${id}` }) +} +``` + +#### API 调用 + +```vue + +``` + +### 路由开发 + +#### 路由配置 + +```typescript +// router/modules/system.ts +import type { AppRouteModule } from '@/router/types' + +const system: AppRouteModule = { + path: '/system', + name: 'System', + component: 'LAYOUT', + redirect: '/system/user', + meta: { + title: '系统管理', + icon: 'system', + orderNo: 1000 + }, + children: [ + { + path: 'user', + name: 'SystemUser', + component: () => import('@/views/system/user/index.vue'), + meta: { + title: '用户管理', + icon: 'user', + noCache: true + } + }, + { + path: 'role', + name: 'SystemRole', + component: () => import('@/views/system/role/index.vue'), + meta: { + title: '角色管理', + icon: 'role', + noCache: true + } + } + ] +} + +export default system +``` + +#### 路由跳转 + +```typescript +import { useRouter } from 'vue-router' + +const router = useRouter() + +// 路径跳转 +router.push('/system/user') + +// 命名路由跳转 +router.push({ name: 'SystemUser' }) + +// 带参数跳转 +router.push({ + path: '/system/user', + query: { id: 1 } +}) + +// 替换当前路由 +router.replace('/system/user') + +// 后退 +router.back() + +// 前进 +router.forward() +``` + +### 状态管理 + +#### Store 定义 + +```typescript +// store/modules/user.ts +import { defineStore } from 'pinia' +import { getUserInfo, login } from '@/api/system/user' + +interface UserState { + token: string + userInfo: UserInfo | null +} + +export const useUserStore = defineStore('user', { + state: (): UserState => ({ + token: '', + userInfo: null + }), + + getters: { + getToken: (state) => state.token, + getUserInfo: (state) => state.userInfo + }, + + actions: { + setToken(token: string) { + this.token = token + }, + + async login(params: LoginReqVO) { + const { data } = await login(params) + this.setToken(data.token) + }, + + async getUserInfoAction() { + const { data } = await getUserInfo() + this.userInfo = data + }, + + async logout() { + this.token = '' + this.userInfo = null + } + }, + + persist: { + key: 'user-store', + storage: localStorage + } +}) +``` + +#### Store 使用 + +```vue + +``` + +--- + +## 核心功能 + +### 权限管理 + +#### 权限指令 + +```vue + +``` + +#### 权限函数 + +```typescript +import { usePermission } from '@/hooks/web/usePermission' + +const { hasPermission, hasRole } = usePermission() + +// 检查权限 +if (hasPermission(['system:user:create'])) { + // 有权限 +} + +// 检查角色 +if (hasRole(['admin'])) { + // 是管理员 +} +``` + +### 国际化 + +#### 使用翻译 + +```vue + + + +``` + +#### 添加翻译 + +```typescript +// locales/zh-CN/common.ts +export default { + title: 'Lyzsys 管理系统', + welcome: '欢迎,{name}', + logout: '退出登录' +} +``` + +```typescript +// locales/en/common.ts +export default { + title: 'Lyzsys Admin', + welcome: 'Welcome, {name}', + logout: 'Logout' +} +``` + +### 主题定制 + +#### 修改主题色 + +```typescript +// styles/variables.scss +$primary-color: #409eff; +$success-color: #67c23a; +$warning-color: #e6a23c; +$danger-color: #f56c6c; +$error-color: #f56c6c; +``` + +#### 动态切换主题 + +```vue + +``` + +### 文件上传 + +#### 单文件上传 + +```vue + + + +``` + +#### 多文件上传 + +```vue + + + +``` + +### 表单验证 + +#### 表单定义 + +```vue + + + +``` + +### 表格操作 + +#### 基础表格 + +```vue + + + +``` + +#### 分页表格 + +```vue + + + +``` + +--- + +## 组件库 + +### Element Plus + +#### 按钮 + +```vue +默认按钮 +主要按钮 +成功按钮 +警告按钮 +危险按钮 +文字按钮 +``` + +#### 表单 + +```vue + + + +``` + +#### 选择器 + +```vue + + + + +``` + +#### 日期选择器 + +```vue + + + +``` + +#### 对话框 + +```vue + + 这是一段内容 + + +``` + +#### 消息提示 + +```typescript +import { ElMessage, ElMessageBox, ElNotification } from 'element-plus' + +// 消息提示 +ElMessage.success('操作成功') +ElMessage.warning('警告消息') +ElMessage.error('错误消息') +ElMessage.info('提示消息') + +// 确认框 +ElMessageBox.confirm('确定要删除吗?', '提示', { + confirmButtonText: '确定', + cancelButtonText: '取消', + type: 'warning' +}) + .then(() => { + ElMessage.success('删除成功') + }) + .catch(() => { + ElMessage.info('已取消删除') + }) + +// 通知 +ElNotification({ + title: '通知', + message: '这是一条通知消息', + type: 'success' +}) +``` + +### 自定义组件 + +#### 图表组件 (ECharts) + +```vue + + + +``` + +#### 富文本编辑器 (WangEditor) + +```vue + + + +``` + +--- + +## 样式指南 + +### CSS 预处理器 + +使用 SCSS 作为 CSS 预处理器: + +```scss +// 使用变量 +$primary-color: #409eff; +$border-radius: 4px; + +// 使用嵌套 +.button { + background: $primary-color; + border-radius: $border-radius; + + &:hover { + background: darken($primary-color, 10%); + } + + &.active { + background: lighten($primary-color, 10%); + } +} +``` + +### UnoCSS + +使用原子化 CSS: + +```vue + +``` + +### 响应式设计 + +```scss +// 使用媒体查询 +.container { + padding: 20px; + + @media (max-width: 768px) { + padding: 10px; + } + + @media (max-width: 480px) { + padding: 5px; + } +} +``` + +### 主题定制 + +```scss +// 自定义主题色 +:root { + --el-color-primary: #409eff; + --el-color-success: #67c23a; + --el-color-warning: #e6a23c; + --el-color-danger: #f56c6c; +} + +// 暗黑模式 +.dark { + --el-bg-color: #1a1a1a; + --el-text-color-primary: #ffffff; +} +``` + +--- + +## 部署指南 + +### 本地构建 + +```bash +# 开发环境构建 +pnpm build:dev + +# 生产环境构建 +pnpm build:prod + +# 测试环境构建 +pnpm build:test +``` + +### 环境变量配置 + +```bash +# .env.base +VITE_BASE_URL=/api + +# .env.dev +VITE_BASE_URL=http://localhost:48080 + +# .env.prod +VITE_BASE_URL=https://api.example.com +``` + +### Docker 部署 + +#### 1. 构建镜像 + +```bash +docker build -t lyzsys/lyzsys-ui-admin:latest . +``` + +#### 2. 运行容器 + +```bash +docker run -d \ + --name lyzsys-ui-admin \ + -p 80:80 \ + lyzsys/lyzsys-ui-admin:latest +``` + +### Nginx 配置 + +```nginx +server { + listen 80; + server_name example.com; + + root /usr/share/nginx/html; + index index.html; + + location / { + try_files $uri $uri/ /index.html; + } + + location /api { + proxy_pass http://backend:48080; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + } + + gzip on; + gzip_types text/plain text/css application/json application/javascript; +} +``` + +--- + +## 附录 + +### 常见问题 + +#### Q1: 如何添加新页面? + +1. 在 `views/` 目录下创建页面组件 +2. 在 `router/modules/` 中配置路由 +3. 添加国际化翻译(如需要) +4. 在后台系统中配置菜单权限 + +#### Q2: 如何调用后端 API? + +1. 在 `api/` 目录下创建 API 文件 +2. 定义 API 接口函数 +3. 在组件中导入并调用 +4. 处理响应数据 + +#### Q3: 如何实现权限控制? + +1. 使用 `v-hasPermi` 指令控制按钮显示 +2. 使用 `v-hasRole` 指令控制角色访问 +3. 在路由配置中设置权限 meta +4. 后端接口进行权限验证 + +#### Q4: 如何切换语言? + +1. 在 `locales/` 目录下添加语言文件 +2. 使用 `$t()` 函数进行翻译 +3. 在语言切换器中调用 `setLocale()` 方法 + +### 参考资源 + +- [Vue 3 官方文档](https://cn.vuejs.org/) +- [TypeScript 官方文档](https://www.typescriptlang.org/zh/) +- [Vite 官方文档](https://cn.vitejs.dev/) +- [Element Plus 官方文档](https://element-plus.org/zh-CN/) +- [Pinia 官方文档](https://pinia.vuejs.org/zh/) +- [UnoCSS 官方文档](https://unocss.dev/) + +--- + +**文档版本**: v1.0.0 +**最后更新**: 2025-01-19 +**维护团队**: Lyzsys 开发团队 diff --git a/doc/后端开发文档.md b/doc/后端开发文档.md new file mode 100644 index 0000000..8fe083c --- /dev/null +++ b/doc/后端开发文档.md @@ -0,0 +1,866 @@ +# Lyzsys 后端开发文档 + +## 目录 + +- [项目概述](#项目概述) +- [技术栈](#技术栈) +- [项目架构](#项目架构) +- [模块说明](#模块说明) +- [开发指南](#开发指南) +- [核心功能](#核心功能) +- [部署指南](#部署指南) + +--- + +## 项目概述 + +Lyzsys 是一个基于 Spring Boot 的企业级后台管理系统,采用模块化单体架构,支持多租户、工作流、权限管理、AI 集成等企业级功能。 + +### 核心特性 + +- **模块化架构**: 基于 Maven 多模块的清晰分层设计 +- **多租户支持**: 原生支持 SaaS 多租户场景 +- **权限管理**: 基于 RBAC 的动态权限和数据权限 +- **工作流引擎**: 集成 Flowable 实现业务流程管理 +- **AI 集成**: 支持多个 AI 服务提供商集成 +- **微服务就绪**: 模块化设计便于未来微服务化改造 + +--- + +## 技术栈 + +### 核心框架 + +| 技术 | 版本 | 说明 | +|------|------|------| +| Spring Boot | 2.7.18 | 应用开发框架 | +| Spring Security | 5.8.16 | 安全框架 | +| MyBatis Plus | 3.5.15 | ORM 增强框架 | +| Flowable | 6.8.0 | 工作流引擎 | +| Redisson | 3.52.0 | 分布式锁客户端 | + +### 数据存储 + +| 技术 | 版本 | 说明 | +|------|------|------| +| MySQL | 5.7+ | 主数据库 | +| Redis | 5.0+ | 缓存数据库 | +| 支持数据库 | - | MySQL、PostgreSQL、Oracle、SQL Server、H2 等 | + +### 工具库 + +| 技术 | 版本 | 说明 | +|------|------|------| +| Lombok | 1.18.34 | 简化 Java 代码 | +| MapStruct | 1.6.3 | 对象映射 | +| Jackson | 2.13.5 | JSON 处理 | +| Hibernate Validator | 6.2.5 | 参数校验 | +| Knife4j | 3.0.3 | API 文档 | + +--- + +## 项目架构 + +### 整体架构 + +Lyzsys 后端采用**模块化单体架构**,基于 **Controller-Service-DAL** 三层架构模式: + +``` +┌─────────────────────────────────────────────────────────────┐ +│ 前端应用 │ +│ (lyzsys-ui-admin / lyzsys-ui-admin-uniapp) │ +└─────────────────────────────────────────────────────────────┘ + │ + ▼ +┌─────────────────────────────────────────────────────────────┐ +│ lyzsys-server │ +│ (应用启动入口) │ +└─────────────────────────────────────────────────────────────┘ + │ + ┌─────────────────────┼─────────────────────┐ + │ │ │ + ▼ ▼ ▼ +┌──────────────┐ ┌──────────────────┐ ┌──────────────┐ +│ lyzsys-framework│ │ lyzsys-module-xxx│ │lyzsys-dependencies│ +│ (框架层) │ │ (业务模块) │ │ (依赖管理) │ +└──────────────┘ └──────────────────┘ └──────────────┘ +``` + +### 分层架构 + +每个业务模块都遵循标准的三层架构: + +``` +controller/ # 控制层 - 接收 HTTP 请求 + ├── admin/ # 管理后台 API + └── app/ # 用户 App API + │ + ▼ +service/ # 服务层 - 业务逻辑处理 + ├── IxxxService.java # 服务接口 + └── xxxServiceImpl.java # 服务实现 + │ + ▼ +dal/ # 数据访问层 + ├── dataobject/ # 数据对象 (DO) + ├── mysql/ # MyBatis Mapper + └── redis/ # Redis 操作 +``` + +### 架构设计原则 + +1. **依赖倒置**: Controller 依赖 Service 接口,而非实现 +2. **单一职责**: 每层只负责自己的职责 +3. **开闭原则**: 通过接口扩展,而非修改 +4. **非严格分层**: 允许跨层访问(如 Service 直接调用多个 Mapper) + +--- + +## 模块说明 + +### Maven 模块分类 + +项目共有四类 Maven Module: + +#### 1. lyzsys-dependencies + +**作用**: Maven 依赖版本管理 (BOM) + +**说明**: 定义项目中所有 Maven 依赖的版本号,解决依赖冲突问题。 + +**关键文件**: +- `pom.xml`: 依赖版本定义 + +#### 2. lyzsys-framework + +**作用**: Java 框架拓展 + +**说明**: 提供项目的基础框架能力,分为技术组件和业务组件。 + +**技术组件**: + +| 模块 | 作用 | +|------|------| +| lyzsys-common | 基础 pojo 类、枚举、工具类 | +| lyzsys-spring-boot-starter-web | Web 封装,全局异常、访问日志 | +| lyzsys-spring-boot-starter-security | 认证授权,基于 Spring Security | +| lyzsys-spring-boot-starter-mybatis | 数据库操作,基于 MyBatis Plus | +| lyzsys-spring-boot-starter-redis | 缓存操作,基于 Spring Data Redis + Redisson | +| lyzsys-spring-boot-starter-mq | 消息队列,基于 Redis 实现 | +| lyzsys-spring-boot-starter-job | 定时任务,基于 Quartz 实现 | +| lyzsys-spring-boot-starter-protection | 服务保障,幂等、分布式锁、限流、熔断 | +| lyzsys-spring-boot-starter-excel | Excel 导入导出,基于 EasyExcel | +| lyzsys-spring-boot-starter-monitor | 服务监控,链路追踪、日志服务 | +| lyzsys-spring-boot-starter-websocket | WebSocket 封装,支持 Token 认证 | + +**业务组件**: + +| 模块 | 作用 | +|------|------| +| lyzsys-spring-boot-starter-biz-tenant | SaaS 多租户 | +| lyzsys-spring-boot-starter-biz-data-permission | 数据权限 | +| lyzsys-spring-boot-starter-biz-ip | 地区 & IP 库 | + +#### 3. lyzsys-module-xxx + +**作用**: 业务功能模块 + +**核心模块**: + +| 模块 | 说明 | 是否必须 | +|------|------|----------| +| lyzsys-module-system | 系统功能模块 | √ | +| lyzsys-module-infra | 基础设施模块 | √ | +| lyzsys-module-ai | AI 大模型集成 | × | +| lyzsys-module-bpm | 业务流程管理 | × | +| lyzsys-module-crm | 客户关系管理 | × | +| lyzsys-module-erp | 企业资源规划 | × | +| lyzsys-module-iot | 物联网平台 | × | +| lyzsys-module-mall | 商城系统 | × | +| lyzsys-module-member | 会员中心 | × | +| lyzsys-module-mp | 微信公众号 | × | +| lyzsys-module-pay | 支付系统 | × | +| lyzsys-module-report | 报表系统 | × | + +#### 4. lyzsys-server + +**作用**: 管理后台 + 用户 App 的服务端 + +**说明**: 后端 Server 的主项目,通过引入需要的 lyzsys-module-xxx 业务模块,提供 RESTful API。 + +### 模块标准结构 + +每个业务模块采用统一的目录结构: + +``` +lyzsys-module-xxx/ +├── src/ +│ ├── main/ +│ │ ├── java/ +│ │ │ └── cn/iocoder/lyzsys/module/xxx/ +│ │ │ ├── api/ # 对外 API 接口 +│ │ │ │ ├── xxxApi.java +│ │ │ │ └── xxxApiImpl.java +│ │ │ ├── controller/ # 控制层 +│ │ │ │ ├── admin/ # 管理后台 Controller +│ │ │ │ │ ├── xxxController.java +│ │ │ │ │ └── vo/ # 视图对象 +│ │ │ │ │ ├── xxxReqVO.java +│ │ │ │ │ └── xxxRespVO.java +│ │ │ │ └── app/ # 用户 App Controller +│ │ │ ├── service/ # 服务层 +│ │ │ │ ├── xxxService.java +│ │ │ │ └── xxxServiceImpl.java +│ │ │ ├── dal/ # 数据访问层 +│ │ │ │ ├── dataobject/ # 数据对象 +│ │ │ │ │ └── xxxDO.java +│ │ │ │ ├── mysql/ # MyBatis Mapper +│ │ │ │ │ └── xxxMapper.java +│ │ │ │ └── redis/ # Redis 操作 +│ │ │ │ └── xxxRedisDAO.java +│ │ │ ├── convert/ # 对象转换器 +│ │ │ │ └── xxxConvert.java +│ │ │ ├── enums/ # 枚举类 +│ │ │ │ └── xxxEnum.java +│ │ │ └── framework/ # 模块框架配置 +│ │ └── resources/ +│ │ └── mapper/ # MyBatis XML +│ └── test/ +│ └── java/ +└── pom.xml +``` + +--- + +## 开发指南 + +### 环境准备 + +#### 必需软件 + +| 软件 | 版本要求 | 下载地址 | +|------|----------|----------| +| JDK | 8+ | https://www.oracle.com/java/technologies/downloads/ | +| MySQL | 5.7+ | https://dev.mysql.com/downloads/mysql/ | +| Redis | 5.0+ | https://redis.io/download | +| Maven | 3.6+ | https://maven.apache.org/download.cgi | +| IDE | IntelliJ IDEA 推荐 | https://www.jetbrains.com/idea/ | + +#### 配置数据库 + +1. 创建数据库: +```sql +CREATE DATABASE lyzsys CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; +``` + +2. 导入 SQL 脚本(位置:`sql/` 目录) + +3. 修改配置文件 `lyzsys-server/src/main/resources/application.yaml` + +### 快速开始 + +#### 1. 克隆项目 + +```bash +git clone https://github.com/your-org/lyzsys.git +cd lyzsys/lyzsys_backend +``` + +#### 2. 导入 IDE + +将项目导入 IntelliJ IDEA: + +``` +File → Open → 选择 lyzsys_backend 目录 +``` + +等待 Maven 依赖下载完成。 + +#### 3. 启动 Redis + +```bash +redis-server +``` + +#### 4. 运行主类 + +找到 `lyzsys-server/src/main/java/cn/iocoder/lyzsys/server/LyzsysServerApplication.java` + +右键 → Run 'LyzsysServerApplication' + +#### 5. 访问应用 + +- 应用地址: http://localhost:48080 +- API 文档: http://localhost:48080/doc.html +- 用户名: admin +- 密码: admin123 + +### 开发规范 + +#### 命名规范 + +**包命名**: 全小写,使用点分隔 +``` +cn.iocoder.lyzsys.module.system.controller.admin +``` + +**类命名**: 大驼峰 +``` +UserController, UserService, UserDO +``` + +**方法命名**: 小驼峰 +``` +getUserById(), createUser(), deleteUser() +``` + +**变量命名**: 小驼峰 +``` +userName, userAge, isAdmin +``` + +**常量命名**: 全大写,下划线分隔 +``` +MAX_SIZE, DEFAULT_PAGE_SIZE, ERROR_CODE +``` + +#### 注释规范 + +**类注释**: +```java +/** + * 用户 Controller + * + * @author 芋道源码 + */ +@RestController +@RequestMapping("/system/user") +public class UserController { +} +``` + +**方法注释**: +```java +/** + * 创建用户 + * + * @param createReqVO 创建信息 + * @return 用户 ID + */ +@PostMapping("/create") +public CommonResult createUser(@Valid @RequestBody UserCreateReqVO createReqVO) { + return success(userService.createUser(createReqVO)); +} +``` + +#### 代码规范 + +1. **使用 Lombok 简化代码**: +```java +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class UserDO extends TenantBaseDO { + private Long id; + private String username; +} +``` + +2. **使用 MapStruct 进行对象转换**: +```java +@Mapper +public interface UserConvert { + UserConvert INSTANCE = Mappers.getMapper(UserConvert.class); + + UserDO convert(UserCreateReqVO bean); + + UserRespVO convert(UserDO bean); +} +``` + +3. **异常处理**: +```java +// 使用全局异常处理器 +throw new ServiceException(USER_USERNAME_EXISTS); + +// 或使用工具方法 +throw exception(USER_USERNAME_EXISTS); +``` + +### 接口开发 + +#### Controller 层 + +```java +@Tag(name = "管理后台 - 用户") +@RestController +@RequestMapping("/system/user") +@RequiredArgsConstructor +public class UserController { + + private final UserService userService; + + @PostMapping("/create") + @Operation(summary = "创建用户") + @PreAuthorize("@ss.hasPermission('system:user:create')") + public CommonResult createUser(@Valid @RequestBody UserCreateReqVO createReqVO) { + return success(userService.createUser(createReqVO)); + } + + @GetMapping("/get") + @Operation(summary = "获取用户详情") + @Parameter(name = "id", description = "用户 ID", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('system:user:query')") + public CommonResult getUser(@RequestParam("id") Long id) { + return success(userService.getUser(id)); + } +} +``` + +#### Service 层 + +```java +public interface UserService { + Long createUser(UserCreateReqVO createReqVO); + UserRespVO getUser(Long id); + void deleteUser(Long id); +} + +@Service +@RequiredArgsConstructor +public class UserServiceImpl implements UserService { + + private final UserMapper userMapper; + + @Override + @Transactional(rollbackFor = Exception.class) + public Long createUser(UserCreateReqVO createReqVO) { + // 1. 参数校验 + validateUserExists(null, createReqVO.getUsername()); + + // 2. 插入用户 + UserDO user = UserConvert.INSTANCE.convert(createReqVO); + user.setPassword(encodePassword(createReqVO.getPassword())); + userMapper.insert(user); + + // 3. 返回 ID + return user.getId(); + } + + @Override + public UserRespVO getUser(Long id) { + UserDO user = userMapper.selectById(id); + return UserConvert.INSTANCE.convert(user); + } +} +``` + +#### Mapper 层 + +```java +@Mapper +public interface UserMapper extends BaseMapperX { + + default UserDO selectByUsername(String username) { + return selectOne("username", username); + } + + default List selectListByDeptIds(Collection deptIds) { + return selectList(new LambdaQueryWrapperX() + .in(UserDO::getDeptId, deptIds)); + } + + default PageResult selectPage(UserPageReqVO pageReqVO) { + return selectPage(pageReqVO, new LambdaQueryWrapperX() + .likeIfPresent(UserDO::getUsername, pageReqVO.getUsername()) + .likeIfPresent(UserDO::getMobile, pageReqVO.getMobile()) + .betweenIfPresent(UserDO::getCreateTime, pageReqVO.getCreateTime()) + .orderByDesc(UserDO::getId)); + } +} +``` + +--- + +## 核心功能 + +### 认证授权 + +#### 认证流程 + +1. **登录认证**: +``` +用户输入用户名密码 → 后端验证 → 生成 JWT Token → 返回 Token +``` + +2. **Token 验证**: +``` +请求携带 Token → 后端解析 Token → 验证有效性 → 允许访问 +``` + +3. **Token 刷新**: +``` +Token 即将过期 → 使用刷新令牌 → 获取新 Token +``` + +#### 权限模型 + +**RBAC (基于角色的访问控制)**: + +``` +用户 (User) + ↓ +角色 (Role) + ↓ +权限 (Permission) + ↓ +资源 (Resource) +``` + +**数据权限**: + +- 全部数据权限 +- 本部门数据权限 +- 本部门及以下数据权限 +- 仅本人数据权限 +- 自定义数据权限 + +### 多租户 + +#### 租户隔离 + +1. **数据库隔离**: 通过 `tenant_id` 字段隔离 +2. **自动过滤**: MyBatis Plus 拦截器自动添加租户条件 +3. **租户上下文**: `TenantContextHolder` 管理当前租户 + +#### 使用示例 + +```java +// 继承租户基类 +@TableName("system_user") +public class UserDO extends TenantBaseDO { + private Long id; + private String username; + // tenant_id 由 TenantBaseDO 提供 +} + +// 查询自动过滤租户 +List users = userMapper.selectList(); +// SQL: SELECT * FROM system_user WHERE tenant_id = ? +``` + +### 工作流 (Flowable) + +#### 流程定义 + +```java +@Service +public class ProcessDefinitionService { + + public String createProcessDefinition(ProcessDefinitionCreateReqVO createReqVO) { + // 1. 校验流程模型 + validateProcessModel(createReqVO.getModelId()); + + // 2. 部署流程定义 + Deployment deployment = repositoryService.createDeployment() + .name(createReqVO.getName()) + .addBytes(createReqVO.getBpmnBytes()) + .deploy(); + + // 3. 返回流程定义 ID + return deployment.getId(); + } +} +``` + +#### 流程实例 + +```java +@Service +public class ProcessInstanceService { + + public String startProcessInstance(ProcessInstanceStartReqVO startReqVO) { + // 1. 启动流程实例 + ProcessInstance instance = runtimeService.startProcessInstanceByKey( + startReqVO.getProcessDefinitionKey(), + startReqVO.getBusinessKey() + ); + + // 2. 完成第一个任务 + taskService.complete(instance.getId()); + + // 3. 返回实例 ID + return instance.getId(); + } +} +``` + +### 缓存管理 + +#### Redis 缓存 + +```java +// 使用 RedisTemplate +@Service +@RequiredArgsConstructor +public class UserServiceImpl { + + private final RedisTemplate redisTemplate; + + public UserDO getUser(Long id) { + String key = "user:" + id; + UserDO user = redisTemplate.opsForValue().get(key); + + if (user == null) { + user = userMapper.selectById(id); + redisTemplate.opsForValue().set(key, user, 1, TimeUnit.HOURS); + } + + return user; + } +} +``` + +#### 缓存注解 + +```java +@Cacheable(value = "user", key = "#id") +public UserDO getUser(Long id) { + return userMapper.selectById(id); +} + +@CachePut(value = "user", key = "#user.id") +public UserDO updateUser(UserDO user) { + userMapper.updateById(user); + return user; +} + +@CacheEvict(value = "user", key = "#id") +public void deleteUser(Long id) { + userMapper.deleteById(id); +} +``` + +### 消息队列 + +#### Redis 消息队列 + +```java +@Component +@RequiredArgsConstructor +public class SmsProducer { + + private final RedisTemplate redisTemplate; + + public void sendSmsSendMessage(Long userId, String mobile, String content) { + SmsSendMessage message = new SmsSendMessage() + .setUserId(userId) + .setMobile(mobile) + .setContent(content); + redisTemplate.convertAndSend("sms_send", message); + } +} + +@Component +@RequiredArgsConstructor +public class SmsSendConsumer { + + private final SmsService smsService; + + @RedisStreamListener(stream = "sms_send", consumerGroup = "sms_send_group") + public void consumeSmsSendMessage(SmsSendMessage message) { + smsService.sendSms(message.getMobile(), message.getContent()); + } +} +``` + +### 定时任务 + +#### Quartz 定时任务 + +```java +@Component +public class DemoJob extends QuartzJobBean { + + @Autowired + private UserService userService; + + @Override + protected void executeInternal(JobExecutionContext context) throws JobExecutionException { + // 定时清理过期用户 + userService.cleanExpiredUsers(); + } +} +``` + +### 文件管理 + +#### 文件上传 + +```java +@RestController +@RequestMapping("/infra/file") +public class FileController { + + @PostMapping("/upload") + public CommonResult uploadFile(@RequestParam("file") MultipartFile file) { + // 1. 上传文件 + String url = fileService.uploadFile(file); + + // 2. 返回 URL + return success(url); + } +} +``` + +#### 文件存储 + +支持多种存储方式: +- 本地存储 +- 阿里云 OSS +- 腾讯云 COS +- MinIO +- FTP / SFTP + +### Excel 操作 + +#### 导入 + +```java +@PostMapping("/import") +public CommonResult importUsers(@RequestParam("file") MultipartFile file) { + List list = ExcelUtils.read(file, UserImportExcelVO.class); + return success(userService.importUsers(list)); +} +``` + +#### 导出 + +```java +@GetMapping("/export") +public void exportUsers(HttpServletResponse response, UserPageReqVO pageReqVO) { + List list = userService.getUserList(pageReqVO); + ExcelUtils.write(response, "用户数据.xls", "用户列表", UserRespVO.class, + BeanConvertUtils.convertList(list, UserRespVO.class)); +} +``` + +--- + +## 部署指南 + +### 本地部署 + +#### 1. 打包项目 + +```bash +cd lyzsys_backend +mvn clean package -DskipTests +``` + +#### 2. 上传文件 + +将 `lyzsys-server/target/lyzsys-server.jar` 上传到服务器 + +#### 3. 启动应用 + +```bash +java -jar lyzsys-server.jar --spring.profiles.active=prod +``` + +### Docker 部署 + +#### 1. 构建镜像 + +```bash +docker build -t lyzsys/lyzsys-server:latest . +``` + +#### 2. 运行容器 + +```bash +docker run -d \ + --name lyzsys-server \ + -p 48080:48080 \ + -e SPRING_PROFILES_ACTIVE=prod \ + -e SPRING_DATASOURCE_URL=jdbc:mysql://mysql:3306/lyzsys \ + -e SPRING_DATASOURCE_USERNAME=root \ + -e SPRING_DATASOURCE_PASSWORD=password \ + -e SPRING_DATA_REDIS_HOST=redis \ + lyzsys/lyzsys-server:latest +``` + +### 配置说明 + +#### application.yaml + +```yaml +spring: + # 数据源配置 + datasource: + url: jdbc:mysql://127.0.0.1:3306/lyzsys?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true + username: root + password: password + driver-class-name: com.mysql.cj.jdbc.Driver + + # Redis 配置 + redis: + host: 127.0.0.1 + port: 6379 + database: 1 + password: + timeout: 0 + +# 项目配置 +lyzsys: + info: + base-package: cn.iocoder.lyzsys + web: + api-prefix: /admin-api + security: + mock-enable: true + upload: + base-url: http://127.0.0.1:48080 +``` + +--- + +## 附录 + +### 常见问题 + +#### Q1: 如何添加新的业务模块? + +1. 在 `lyzsys-module-xxx` 目录下创建新模块 +2. 按照标准模块结构创建包和类 +3. 在 `lyzsys-server/pom.xml` 中添加模块依赖 +4. 在 `application.yaml` 中配置模块扫描路径 + +#### Q2: 如何自定义异常? + +1. 在 `module-system/enums/ErrorCodeConstants.java` 中添加错误码 +2. 使用 `throw exception(ERROR_CODE)` 抛出异常 +3. 全局异常处理器会自动处理并返回统一格式 + +#### Q3: 如何实现数据权限? + +1. 在 `@Table` 注解中配置 `dataPermission` 属性 +2. 使用 `@DataPermission` 注解标记需要数据权限的方法 +3. 框架会自动添加数据权限过滤条件 + +### 参考资源 + +- [Spring Boot 官方文档](https://spring.io/projects/spring-boot) +- [MyBatis Plus 官方文档](https://baomidou.com/) +- [Flowable 官方文档](https://www.flowable.com/open-source/docs) +- [Redis 官方文档](https://redis.io/documentation) +- [芋道源码文档](https://doc.iocoder.cn/) + +--- + +**文档版本**: v1.0.0 +**最后更新**: 2025-01-19 +**维护团队**: Lyzsys 开发团队 diff --git a/doc/常见问题.md b/doc/常见问题.md new file mode 100644 index 0000000..58f5dcc --- /dev/null +++ b/doc/常见问题.md @@ -0,0 +1,804 @@ +# Lyzsys 常见问题 (FAQ) + +## 📖 目录 + +- [快速导航](#快速导航) +- [后端开发问题](#后端开发问题) +- [前端开发问题](#前端开发问题) +- [部署运维问题](#部署运维问题) +- [性能优化问题](#性能优化问题) +- [功能定制问题](#功能定制问题) +- [故障排查问题](#故障排查问题) + +--- + +## 快速导航 + +### 新手入门 + +- [如何快速开始?](#如何快速开始) +- [项目运行需要什么环境?](#项目运行需要什么环境) +- [如何获取项目源码?](#如何获取项目源码) + +### 开发相关 + +- [如何添加新的业务模块?](#如何添加新的业务模块) +- [如何修改前端页面?](#如何修改前端页面) +- [如何自定义接口?](#如何自定义接口) +- [如何实现权限控制?](#如何实现权限控制) + +### 部署相关 + +- [如何部署到生产环境?](#如何部署到生产环境) +- [如何配置数据库连接?](#如何配置数据库连接) +- [如何配置 SSL 证书?](#如何配置-ssl-证书) +- [如何进行性能优化?](#如何进行性能优化) + +--- + +## 后端开发问题 + +### Q1: 如何快速开始? + +**A**: 按照以下步骤操作: + +1. **克隆项目** + ```bash + git clone https://github.com/your-org/lyzsys.git + cd lyzsys/lyzsys_backend + ``` + +2. **导入数据库** + ```bash + mysql -u root -p < sql/lyzsys.sql + ``` + +3. **修改配置** + ```yaml + # application.yaml + spring: + datasource: + url: jdbc:mysql://localhost:3306/lyzsys + username: root + password: your_password + ``` + +4. **启动项目** + ```bash + mvn spring-boot:run + ``` + +5. **访问系统** + - 后端地址: http://localhost:48080 + - API 文档: http://localhost:48080/doc.html + +### Q2: 如何添加新的业务模块? + +**A**: 按照以下步骤创建新模块: + +1. **创建模块目录** + ``` + lyzsys-module-xxx/ + ├── src/ + │ └── main/ + │ ├── java/ + │ └── resources/ + └── pom.xml + ``` + +2. **创建模块 pom.xml** + ```xml + + cn.iocoder + lyzsys-backend + 1.0.0 + + + lyzsys-module-xxx + jar + + + + + ``` + +3. **创建标准包结构** + ``` + cn.iocoder.lyzsys.module.xxx/ + ├── api/ + ├── controller/ + │ ├── admin/ + │ └── app/ + ├── service/ + ├── dal/ + │ ├── dataobject/ + │ ├── mysql/ + │ └── redis/ + ├── convert/ + └── enums/ + ``` + +4. **在主 pom.xml 中添加模块** + ```xml + + lyzsys-module-xxx + + ``` + +5. **在 lyzsys-server 中引入** + ```xml + + cn.iocoder + lyzsys-module-xxx + + ``` + +### Q3: 如何实现权限控制? + +**A**: Lyzsys 提供了多层次的权限控制: + +#### 1. 接口权限 + +使用 `@PreAuthorize` 注解: + +```java +@PostMapping("/create") +@PreAuthorize("@ss.hasPermission('system:user:create')") +public CommonResult createUser(@Valid @RequestBody UserCreateReqVO reqVO) { + return success(userService.createUser(reqVO)); +} +``` + +#### 2. 数据权限 + +使用 `@DataScope` 注解: + +```java +@DataScope(deptAlias = "d", userAlias = "u") +public List getUserList() { + return userMapper.selectList(); +} +``` + +#### 3. 前端权限 + +使用权限指令: + +```vue + +创建 + + +管理员操作 +``` + +### Q4: 如何使用代码生成器? + +**A**: 代码生成器使用步骤: + +1. **访问代码生成** + - 登录系统后,进入「基础设施」→「代码生成」 + +2. **导入数据库表** + - 点击「导入」按钮 + - 选择要生成的表 + +3. **配置生成信息** + - 基本信息:模块名、业务名、功能名 + - 生成信息:包路径、模块名、业务名 + - 字段信息:字段显示、查询条件、必填项 + +4. **生成代码** + - 点击「生成代码」按钮 + - 下载代码压缩包 + +5. **导入项目** + - 解压代码到对应模块 + - 创建菜单和权限 + +### Q5: 如何实现文件上传? + +**A**: 文件上传实现步骤: + +#### 1. 配置文件存储 + +```yaml +lyzsys: + upload: + base-url: http://your-domain.com + storage: + minio: + endpoint: http://localhost:9000 + access-key: your_access_key + secret-key: your_secret_key + bucket-name: lyzsys +``` + +#### 2. 后端上传 + +```java +@PostMapping("/upload") +public CommonResult uploadFile(@RequestParam("file") MultipartFile file) { + String url = fileService.uploadFile(file); + return success(url); +} +``` + +#### 3. 前端上传 + +```vue + + 上传文件 + +``` + +### Q6: 如何使用 Redis 缓存? + +**A**: Redis 缓存使用方法: + +#### 1. 使用 Spring Cache + +```java +@Cacheable(value = "user", key = "#id") +public UserDO getUser(Long id) { + return userMapper.selectById(id); +} + +@CachePut(value = "user", key = "#user.id") +public UserDO updateUser(UserDO user) { + userMapper.updateById(user); + return user; +} + +@CacheEvict(value = "user", key = "#id") +public void deleteUser(Long id) { + userMapper.deleteById(id); +} +``` + +#### 2. 使用 RedisTemplate + +```java +@Autowired +private RedisTemplate redisTemplate; + +public UserDO getUser(Long id) { + String key = "user:" + id; + UserDO user = redisTemplate.opsForValue().get(key); + + if (user == null) { + user = userMapper.selectById(id); + redisTemplate.opsForValue().set(key, user, 1, TimeUnit.HOURS); + } + + return user; +} +``` + +--- + +## 前端开发问题 + +### Q7: 如何修改前端页面? + +**A**: 前端页面修改步骤: + +1. **找到页面文件** + - 页面文件位于 `src/views/` 目录 + - 按照模块分类,如 `src/views/system/user/` + +2. **修改页面内容** + ```vue + + + + + + ``` + +3. **热更新** + - 修改后自动热更新,无需重启 + +4. **构建测试** + ```bash + pnpm build:prod + ``` + +### Q8: 如何调用后端 API? + +**A**: API 调用方法: + +#### 1. 定义 API + +```typescript +// src/api/system/user/index.ts +import request from '@/utils/request' + +export function getUserPage(params: UserPageReqVO) { + return request.get({ url: '/system/user/page', params }) +} + +export function createUser(data: UserCreateReqVO) { + return request.post({ url: '/system/user/create', data }) +} +``` + +#### 2. 调用 API + +```vue + +``` + +### Q9: 如何实现国际化? + +**A**: 国际化实现步骤: + +#### 1. 添加语言文件 + +```typescript +// src/locales/zh-CN/common.ts +export default { + title: 'Lyzsys 管理系统', + logout: '退出登录' +} +``` + +```typescript +// src/locales/en/common.ts +export default { + title: 'Lyzsys Admin', + logout: 'Logout' +} +``` + +#### 2. 使用翻译 + +```vue + + + +``` + +### Q10: 如何自定义主题? + +**A**: 主题定制方法: + +#### 1. 修改主题色 + +```scss +// styles/variables.scss +$primary-color: #409eff; +$success-color: #67c23a; +$warning-color: #e6a23c; +$danger-color: #f56c6c; +``` + +#### 2. 动态切换主题 + +```typescript +import { useAppStore } from '@/store/modules/app' + +const appStore = useAppStore() + +// 切换暗黑模式 +function toggleDarkMode() { + appStore.setDarkMode(!appStore.getDarkMode) +} +``` + +### Q11: 如何使用 Element Plus 组件? + +**A**: Element Plus 组件使用: + +#### 1. 表格组件 + +```vue + + + + + + + +``` + +#### 2. 表单组件 + +```vue + + + + + + 提交 + + +``` + +#### 3. 对话框组件 + +```vue + + 这是一段内容 + + +``` + +--- + +## 部署运维问题 + +### Q12: 如何部署到生产环境? + +**A**: 生产部署步骤: + +#### 后端部署 + +1. **打包项目** + ```bash + mvn clean package -DskipTests + ``` + +2. **上传到服务器** + ```bash + scp lyzsys-server.jar user@server:/opt/lyzsys/ + ``` + +3. **启动服务** + ```bash + java -jar lyzsys-server.jar --spring.profiles.active=prod + ``` + +#### 前端部署 + +1. **构建项目** + ```bash + pnpm build:prod + ``` + +2. **部署到 Nginx** + ```bash + scp -r dist/* user@server:/var/www/lyzsys/ + ``` + +3. **配置 Nginx** + ```nginx + server { + listen 80; + server_name your-domain.com; + root /var/www/lyzsys; + + location / { + try_files $uri $uri/ /index.html; + } + + location /admin-api/ { + proxy_pass http://localhost:48080/admin-api/; + } + } + ``` + +### Q13: 如何配置数据库连接? + +**A**: 数据库连接配置: + +```yaml +spring: + datasource: + url: jdbc:mysql://localhost:3306/lyzsys?useSSL=false&serverTimezone=Asia/Shanghai + username: root + password: your_password + driver-class-name: com.mysql.cj.jdbc.Driver + + # 连接池配置 + hikari: + minimum-idle: 5 + maximum-pool-size: 20 + idle-timeout: 30000 + connection-timeout: 30000 +``` + +### Q14: 如何配置 SSL 证书? + +**A**: SSL 证书配置步骤: + +1. **获取证书** + ```bash + certbot certonly --standalone -d your-domain.com + ``` + +2. **配置 Nginx** + ```nginx + server { + listen 443 ssl http2; + server_name your-domain.com; + + ssl_certificate /etc/letsencrypt/live/your-domain.com/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/your-domain.com/privkey.pem; + + ssl_protocols TLSv1.2 TLSv1.3; + ssl_ciphers HIGH:!aNULL:!MD5; + } + + server { + listen 80; + server_name your-domain.com; + return 301 https://$server_name$request_uri; + } + ``` + +### Q15: 如何进行备份和恢复? + +**A**: 备份恢复方法: + +#### 数据库备份 + +```bash +# 备份 +mysqldump -u root -p lyzsys > lyzsys_backup.sql + +# 恢复 +mysql -u root -p lyzsys < lyzsys_backup.sql +``` + +#### 文件备份 + +```bash +# 备份 +tar -czf lyzsys_backup.tar.gz /var/www/lyzsys + +# 恢复 +tar -xzf lyzsys_backup.tar.gz -C / +``` + +--- + +## 性能优化问题 + +### Q16: 如何进行性能优化? + +**A**: 性能优化建议: + +#### 后端优化 + +1. **数据库优化** + - 添加索引 + - 优化 SQL + - 使用缓存 + +2. **代码优化** + - 批量操作 + - 异步处理 + - 减少数据库查询 + +3. **JVM 优化** + ```bash + java -Xms2g -Xmx2g \ + -XX:+UseG1GC \ + -XX:MaxGCPauseMillis=200 \ + -jar lyzsys-server.jar + ``` + +#### 前端优化 + +1. **代码分割** + ```typescript + const UserList = defineAsyncComponent(() => import('./views/system/user/index.vue')) + ``` + +2. **资源优化** + - 压缩代码 + - 使用 CDN + - 图片优化 + +3. **缓存优化** + - 浏览器缓存 + - 本地存储 + - Service Worker + +### Q17: 如何处理高并发? + +**A**: 高并发处理方案: + +1. **水平扩展** + - 应用集群 + - 负载均衡 + - 数据库主从 + +2. **缓存策略** + - Redis 缓存 + - 本地缓存 + - 缓存预热 + +3. **异步处理** + - 消息队列 + - 异步任务 + - 线程池 + +4. **限流降级** + - 接口限流 + - 服务降级 + - 熔断保护 + +--- + +## 功能定制问题 + +### Q18: 如何修改 Logo 和标题? + +**A**: 品牌定制方法: + +#### 1. 修改前端 + +```typescript +// src/config/index.ts +export default { + title: '你的系统名称', + logo: '/logo.png' +} +``` + +#### 2. 修改后端 + +```yaml +lyzsys: + info: + name: '你的系统名称' + version: '1.0.0' +``` + +### Q19: 如何集成第三方服务? + +**A**: 第三方集成方法: + +#### 1. 短信集成 + +```java +@Service +public class SmsServiceImpl implements SmsService { + + @Autowired + private SmsClient smsClient; + + public void sendSms(String mobile, String content) { + SmsSendReqDTO req = new SmsSendReqDTO(); + req.setMobile(mobile); + req.setContent(content); + smsClient.send(req); + } +} +``` + +#### 2. 支付集成 + +```java +@Service +public class PayServiceImpl implements PayService { + + @Autowired + private PayClient payClient; + + public String createOrder(PayOrderCreateReqDTO req) { + return payClient.createOrder(req); + } +} +``` + +--- + +## 故障排查问题 + +### Q20: 如何查看错误日志? + +**A**: 日志查看方法: + +#### 后端日志 + +```bash +# 查看应用日志 +tail -f logs/lyzsys.log + +# 查看错误日志 +grep ERROR logs/lyzsys.log + +# 查看 Nginx 日志 +tail -f /var/log/nginx/error.log +``` + +#### 前端日志 + +```javascript +// 浏览器控制台 +console.log('日志信息') +console.error('错误信息') + +// 网络请求 +// Network 标签查看请求详情 +``` + +### Q21: 常见错误及解决方案 + +#### 1. 数据库连接失败 + +**错误**: `Could not get JDBC Connection` + +**解决方案**: +- 检查数据库是否启动 +- 检查连接信息是否正确 +- 检查防火墙是否开放端口 + +#### 2. Redis 连接失败 + +**错误**: `Unable to connect to Redis` + +**解决方案**: +- 检查 Redis 是否启动 +- 检查 Redis 密码是否正确 +- 检查 Redis 地址是否正确 + +#### 3. 前端页面空白 + +**错误**: 页面无法显示 + +**解决方案**: +- 检查 Nginx 配置 +- 检查前端路由配置 +- 检查浏览器控制台错误 + +#### 4. API 请求失败 + +**错误**: `Network Error` + +**解决方案**: +- 检查后端服务是否启动 +- 检查 API 地址是否正确 +- 检查跨域配置 + +--- + +**文档版本**: v1.0.0 +**最后更新**: 2025-01-19 +**维护团队**: Lyzsys 开发团队 diff --git a/doc/数据库设计.md b/doc/数据库设计.md new file mode 100644 index 0000000..db670e2 --- /dev/null +++ b/doc/数据库设计.md @@ -0,0 +1,697 @@ +# Lyzsys 数据库设计文档 + +## 📖 目录 + +- [数据库概述](#数据库概述) +- [设计规范](#设计规范) +- [核心表设计](#核心表设计) +- [索引设计](#索引设计) +- [数据字典](#数据字典) +- [多租户设计](#多租户设计) +- [数据库优化](#数据库优化) +- [数据库管理](#数据库管理) + +--- + +## 数据库概述 + +### 技术选型 + +| 特性 | 说明 | +|------|------| +| 数据库 | MySQL 5.7+ / 8.0+ | +| 字符集 | utf8mb4 | +| 排序规则 | utf8mb4_unicode_ci | +| 引擎 | InnoDB | +| 时区 | Asia/Shanghai | + +### 支持的数据库 + +- MySQL 5.7、8.0+ +- PostgreSQL 9.6+ +| Oracle 11g+ +| SQL Server 2012+ +| H2 2.x (开发测试) + +### 数据库特点 + +1. **多数据库支持**: 通过 MyBatis Plus 实现 +2. **租户隔离**: 支持多租户数据隔离 +3. **逻辑删除**: 支持软删除 +4. **数据权限**: 支持行级数据权限 +5. **审计日志**: 完整的创建、更新日志 + +--- + +## 设计规范 + +### 命名规范 + +#### 数据库命名 + +- 格式: `lyzsys` +- 示例: `lyzsys` + +#### 表命名 + +- 格式: `{模块}_{业务}_{实体}` +- 规则: 小写字母 + 下划线 +- 示例: + - `system_users` - 系统用户表 + - `system_roles` - 系统角色表 + - `mall_orders` - 商城订单表 + - `bpm_process_instance` - 工作流实例表 + +#### 字段命名 + +- 格式: 小写字母 + 下划线 +- 规则: 使用有意义的单词组合 +- 示例: + - `user_id` - 用户 ID + - `user_name` - 用户名 + - `create_time` - 创建时间 + - `update_time` - 更新时间 + +#### 索引命名 + +- 主键索引: `PRIMARY` +- 唯一索引: `uniq_{字段名}` +- 普通索引: `idx_{字段名}` +- 示例: + - `uniq_username` - 用户名唯一索引 + - `idx_dept_id` - 部门 ID 普通索引 + +### 字段类型 + +#### 整数类型 + +| 类型 | 字节 | 范围 | 用途 | +|------|------|------|------| +| TINYINT | 1 | -128 ~ 127 | 状态、标识 | +| SMALLINT | 2 | -32768 ~ 32767 | 枚举值 | +| INT | 4 | -21亿 ~ 21亿 | 数量、序号 | +| BIGINT | 8 | 极大数值 | 主键、外键 | + +#### 字符串类型 + +| 类型 | 长度 | 用途 | +|------|------|------| +| CHAR | 0-255 | 固定长度字符串 | +| VARCHAR | 0-65535 | 变长字符串 | +| TEXT | 0-65535 | 长文本 | +| LONGTEXT | 0-4294967295 | 超长文本 | + +#### 日期时间类型 + +| 类型 | 格式 | 用途 | +|------|------|------| +| DATE | YYYY-MM-DD | 日期 | +| DATETIME | YYYY-MM-DD HH:MM:SS | 日期时间 | +| TIMESTAMP | 时间戳 | 时间戳 | + +#### 小数类型 + +| 类型 | 用途 | +|------|------| +| DECIMAL(M,D) | 金额、精度数值 | + +### 通用字段 + +每张表都包含以下通用字段: + +```sql +-- 主键 +id BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键' + +-- 创建信息 +create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间' +creator VARCHAR(64) COMMENT '创建人' + +-- 更新信息 +update_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间' +updater VARCHAR(64) COMMENT '更新人' + +-- 删除标记 +deleted BIT NOT NULL DEFAULT FALSE COMMENT '是否删除' + +-- 租户 ID (多租户表) +tenant_id BIGINT NOT NULL COMMENT '租户 ID' +``` + +--- + +## 核心表设计 + +### 系统管理模块 + +#### 1. 用户表 (system_users) + +```sql +CREATE TABLE `system_users` ( + `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '用户ID', + `username` VARCHAR(30) NOT NULL COMMENT '用户账号', + `password` VARCHAR(100) NOT NULL COMMENT '密码', + `nickname` VARCHAR(30) NOT NULL COMMENT '用户昵称', + `remark` VARCHAR(500) COMMENT '备注', + `dept_id` BIGINT NOT NULL COMMENT '部门ID', + `post_ids` VARCHAR(255) COMMENT '岗位编号数组', + `email` VARCHAR(50) COMMENT '用户邮箱', + `mobile` VARCHAR(11) COMMENT '手机号码', + `sex` TINYINT COMMENT '用户性别', + `avatar` VARCHAR(100) COMMENT '头像地址', + `status` TINYINT NOT NULL DEFAULT 0 COMMENT '帐号状态(0正常 1停用)', + `login_ip` VARCHAR(50) COMMENT '最后登录IP', + `login_date` DATETIME COMMENT '最后登录时间', + `tenant_id` BIGINT NOT NULL COMMENT '租户 ID', + `create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `update_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `creator` VARCHAR(64) COMMENT '创建人', + `updater` VARCHAR(64) COMMENT '更新人', + `deleted` BIT NOT NULL DEFAULT FALSE COMMENT '是否删除', + PRIMARY KEY (`id`), + UNIQUE KEY `uniq_username` (`username`, `update_time`, `tenant_id`, `deleted`) +) ENGINE=InnoDB COMMENT='用户信息表'; +``` + +#### 2. 角色表 (system_roles) + +```sql +CREATE TABLE `system_roles` ( + `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '角色ID', + `name` VARCHAR(30) NOT NULL COMMENT '角色名称', + `code` VARCHAR(100) NOT NULL COMMENT '角色权限字符串', + `sort` INT NOT NULL COMMENT '显示顺序', + `data_scope` TINYINT NOT NULL DEFAULT 1 COMMENT '数据范围(1:全部数据权限 2:本部门及以下数据权限 3:本部门数据权限 4:仅本人数据权限)', + `data_scope_dept_ids` VARCHAR(500) COMMENT '数据范围-部门数组', + `status` TINYINT NOT NULL COMMENT '角色状态(0正常 1停用)', + `type` TINYINT NOT NULL COMMENT '角色类型(1:系统内置 2:自定义)', + `remark` VARCHAR(500) COMMENT '备注', + `tenant_id` BIGINT NOT NULL COMMENT '租户 ID', + `create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `update_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `creator` VARCHAR(64) COMMENT '创建人', + `updater` VARCHAR(64) COMMENT '更新人', + `deleted` BIT NOT NULL DEFAULT FALSE COMMENT '是否删除', + PRIMARY KEY (`id`) +) ENGINE=InnoDB COMMENT='角色信息表'; +``` + +#### 3. 菜单表 (system_menu) + +```sql +CREATE TABLE `system_menu` ( + `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '菜单ID', + `name` VARCHAR(50) NOT NULL COMMENT '菜单名称', + `permission` VARCHAR(100) NOT NULL COMMENT '权限标识', + `type` TINYINT NOT NULL COMMENT '菜单类型(1:目录 2:菜单 3:按钮)', + `sort` INT NOT NULL DEFAULT 0 COMMENT '显示顺序', + `parent_id` BIGINT NOT NULL DEFAULT 0 COMMENT '父菜单ID', + `path` VARCHAR(200) COMMENT '路由地址', + `icon` VARCHAR(100) COMMENT '菜单图标', + `component` VARCHAR(255) COMMENT '组件路径', + `component_name` VARCHAR(255) COMMENT '组件名', + `status` TINYINT NOT NULL DEFAULT 0 COMMENT '菜单状态(0正常 1停用)', + `visible` BIT NOT NULL DEFAULT TRUE COMMENT '是否可见', + `keep_alive` BIT NOT NULL DEFAULT FALSE COMMENT '是否缓存', + `always_show` BIT NOT NULL DEFAULT FALSE COMMENT '是否总是显示', + `create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `update_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `creator` VARCHAR(64) COMMENT '创建人', + `updater` VARCHAR(64) COMMENT '更新人', + `deleted` BIT NOT NULL DEFAULT FALSE COMMENT '是否删除', + PRIMARY KEY (`id`) +) ENGINE=InnoDB COMMENT='菜单权限表'; +``` + +#### 4. 部门表 (system_dept) + +```sql +CREATE TABLE `system_dept` ( + `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '部门id', + `parent_id` BIGINT NOT NULL DEFAULT 0 COMMENT '父部门id', + `name` VARCHAR(30) NOT NULL COMMENT '部门名称', + `sort` INT NOT NULL DEFAULT 0 COMMENT '显示顺序', + `leader_user_id` BIGINT COMMENT '负责人', + `phone` VARCHAR(11) COMMENT '联系电话', + `email` VARCHAR(64) COMMENT '邮箱', + `status` TINYINT NOT NULL COMMENT '部门状态(0正常 1停用)', + `tenant_id` BIGINT NOT NULL COMMENT '租户 ID', + `create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `update_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `creator` VARCHAR(64) COMMENT '创建人', + `updater` VARCHAR(64) COMMENT '更新人', + `deleted` BIT NOT NULL DEFAULT FALSE COMMENT '是否删除', + PRIMARY KEY (`id`) +) ENGINE=InnoDB COMMENT='部门表'; +``` + +#### 5. 字典表 (system_dict_type) + +```sql +CREATE TABLE `system_dict_type` ( + `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '字典主键', + `name` VARCHAR(100) NOT NULL COMMENT '字典名称', + `type` VARCHAR(100) NOT NULL COMMENT '字典类型', + `status` TINYINT NOT NULL DEFAULT 0 COMMENT '状态(0正常 1停用)', + `remark` VARCHAR(500) COMMENT '备注', + `create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `update_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `creator` VARCHAR(64) COMMENT '创建人', + `updater` VARCHAR(64) COMMENT '更新人', + `deleted` BIT NOT NULL DEFAULT FALSE COMMENT '是否删除', + PRIMARY KEY (`id`), + UNIQUE KEY `uniq_type` (`type`, `update_time`, `deleted`) +) ENGINE=InnoDB COMMENT='字典类型表'; +``` + +### 基础设施模块 + +#### 6. 代码生成表 (infra_codegen_column) + +```sql +CREATE TABLE `infra_codegen_column` ( + `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '编号', + `table_id` BIGINT NOT NULL COMMENT '表编号', + `column_name` VARCHAR(200) NOT NULL COMMENT '字段名', + `data_type` VARCHAR(100) NOT NULL COMMENT '字段类型', + `column_comment` VARCHAR(500) COMMENT '字段描述', + `nullable` BIT NOT NULL COMMENT '是否允许为空', + `pk` BIT NOT NULL COMMENT '是否主键', + `ordinal_position` INT NOT NULL COMMENT '排序', + `create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `update_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `creator` VARCHAR(64) COMMENT '创建人', + `updater` VARCHAR(64) COMMENT '更新人', + `deleted` BIT NOT NULL DEFAULT FALSE COMMENT '是否删除', + PRIMARY KEY (`id`) +) ENGINE=InnoDB COMMENT='代码生成字段表'; +``` + +#### 7. 定时任务表 (infra_job) + +```sql +CREATE TABLE `infra_job` ( + `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '任务ID', + `name` VARCHAR(200) NOT NULL COMMENT '任务名称', + `status` TINYINT NOT NULL COMMENT '任务状态', + `handler_name` VARCHAR(200) NOT NULL COMMENT '处理器的名字', + `handler_param` VARCHAR(500) COMMENT '处理器的参数', + `cron_expression` VARCHAR(100) NOT NULL COMMENT 'Cron 表达式', + `retry_count` INT NOT NULL DEFAULT 0 COMMENT '重试次数', + `retry_interval` INT NOT NULL DEFAULT 0 COMMENT '重试间隔', + `monitor_timeout` INT NOT NULL DEFAULT 0 COMMENT '监控超时时间', + `create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `update_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `creator` VARCHAR(64) COMMENT '创建人', + `updater` VARCHAR(64) COMMENT '更新人', + `deleted` BIT NOT NULL DEFAULT FALSE COMMENT '是否删除', + PRIMARY KEY (`id`) +) ENGINE=InnoDB COMMENT='定时任务表'; +``` + +### 工作流模块 + +#### 8. 流程实例表 (bpm_process_instance) + +```sql +CREATE TABLE `bpm_process_instance` ( + `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '编号', + `process_definition_id` VARCHAR(64) NOT NULL COMMENT '流程定义的编号', + `process_instance_id` VARCHAR(64) NOT NULL COMMENT '流程实例的编号', + `start_user_id` BIGINT NOT NULL COMMENT '发起人的用户编号', + `name` VARCHAR(255) COMMENT '流程实例的名字', + `business_key` VARCHAR(64) COMMENT '业务标识', + `status` TINYINT NOT NULL COMMENT '流程实例的状态', + `tenant_id` BIGINT NOT NULL COMMENT '租户 ID', + `create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `update_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `creator` VARCHAR(64) COMMENT '创建人', + `updater` VARCHAR(64) COMMENT '更新人', + `deleted` BIT NOT NULL DEFAULT FALSE COMMENT '是否删除', + PRIMARY KEY (`id`) +) ENGINE=InnoDB COMMENT='流程实例表'; +``` + +### 商城模块 + +#### 9. 商品表 (mall_product) + +```sql +CREATE TABLE `mall_product` ( + `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '商品编号', + `name` VARCHAR(200) NOT NULL COMMENT '商品名称', + `sell_point` VARCHAR(500) COMMENT '卖点', + `description` VARCHAR(2000) COMMENT '商品详情', + `category_id` BIGINT NOT NULL COMMENT '分类编号', + `brand_id` BIGINT COMMENT '品牌编号', + `price` BIGINT NOT NULL COMMENT '价格,单位:分', + `stock` INT NOT NULL COMMENT '库存', + `pic_url` VARCHAR(500) COMMENT '商品主图', + `status` TINYINT NOT NULL COMMENT '商品状态', + `create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `update_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `creator` VARCHAR(64) COMMENT '创建人', + `updater` VARCHAR(64) COMMENT '更新人', + `deleted` BIT NOT NULL DEFAULT FALSE COMMENT '是否删除', + PRIMARY KEY (`id`) +) ENGINE=InnoDB COMMENT='商品表'; +``` + +#### 10. 订单表 (mall_order) + +```sql +CREATE TABLE `mall_order` ( + `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '订单编号', + `user_id` BIGINT NOT NULL COMMENT '用户编号', + `order_no` VARCHAR(64) NOT NULL COMMENT '订单号', + `total_price` BIGINT NOT NULL COMMENT '订单总价,单位:分', + `status` TINYINT NOT NULL COMMENT '订单状态', + `pay_time` DATETIME COMMENT '付款时间', + `delivery_time` DATETIME COMMENT '发货时间', + `receiver_time` DATETIME COMMENT '收货时间', + `comment_time` DATETIME COMMENT '评论时间', + `create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `update_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `creator` VARCHAR(64) COMMENT '创建人', + `updater` VARCHAR(64) COMMENT '更新人', + `deleted` BIT NOT NULL DEFAULT FALSE COMMENT '是否删除', + PRIMARY KEY (`id`), + UNIQUE KEY `uniq_order_no` (`order_no`) +) ENGINE=InnoDB COMMENT='订单表'; +``` + +--- + +## 索引设计 + +### 索引类型 + +#### 1. 主键索引 (PRIMARY KEY) + +每张表都有主键索引: + +```sql +PRIMARY KEY (`id`) +``` + +#### 2. 唯一索引 (UNIQUE) + +用于保证字段的唯一性: + +```sql +UNIQUE KEY `uniq_username` (`username`, `update_time`, `tenant_id`, `deleted`) +``` + +#### 3. 普通索引 (INDEX) + +用于提升查询性能: + +```sql +KEY `idx_dept_id` (`dept_id`) +``` + +#### 4. 联合索引 + +用于多字段查询: + +```sql +KEY `idx_user_id_status` (`user_id`, `status`) +``` + +### 索引规范 + +1. **主键索引**: 使用自增 BIGINT +2. **唯一索引**: 业务唯一字段 +3. **普通索引**: 频繁查询的字段 +4. **联合索引**: 多字段组合查询,遵循最左前缀原则 +5. **索引数量**: 单表索引不超过 5 个 + +### 索引示例 + +```sql +-- 用户表索引 +PRIMARY KEY (`id`) +UNIQUE KEY `uniq_username` (`username`, `update_time`, `tenant_id`, `deleted`) +KEY `idx_dept_id` (`dept_id`) +KEY `idx_status` (`status`) + +-- 订单表索引 +PRIMARY KEY (`id`) +UNIQUE KEY `uniq_order_no` (`order_no`) +KEY `idx_user_id` (`user_id`) +KEY `idx_status` (`status`) +KEY `idx_create_time` (`create_time`) +``` + +--- + +## 数据字典 + +### 通用数据字典 + +#### 1. 用户性别 (system_user_sex) + +| 字典值 | 字典标签 | 颜色 | +|--------|----------|------| +| 1 | 男 | blue | +| 2 | 女 | pink | +| 3 | 未知 | gray | + +#### 2. 用户状态 (system_common_status) + +| 字典值 | 字典标签 | 颜色 | +|--------|----------|------| +| 0 | 启用 | success | +| 1 | 停用 | danger | + +#### 3. 菜单类型 (system_menu_type) + +| 字典值 | 字典标签 | 颜色 | +|--------|----------|------| +| 1 | 目录 | | +| 2 | 菜单 | | +| 3 | 按钮 | | + +#### 4. 数据范围 (system_data_scope) + +| 字典值 | 字典标签 | +|--------|----------| +| 1 | 全部数据权限 | +| 2 | 本部门及以下数据权限 | +| 3 | 本部门数据权限 | +| 4 | 仅本人数据权限 | + +#### 5. 流程实例状态 (bpm_process_instance_status) + +| 字典值 | 字典标签 | 颜色 | +|--------|----------|------| +| 1 | 进行中 | primary | +| 2 | 已结束 | success | + +--- + +## 多租户设计 + +### 租户隔离策略 + +#### 1. 共享数据库、共享 Schema + +所有租户共享同一个数据库,通过 `tenant_id` 字段隔离。 + +#### 2. 自动过滤 + +MyBatis Plus 拦截器自动添加租户条件: + +```java +// 查询时自动添加租户条件 +List users = userMapper.selectList(); + +// 实际 SQL +SELECT * FROM system_users +WHERE deleted = 0 + AND tenant_id = 1 +``` + +### 租户表设计 + +#### 租户表 (system_tenant) + +```sql +CREATE TABLE `system_tenant` ( + `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '租户编号', + `name` VARCHAR(30) NOT NULL COMMENT '租户名', + `contact_user_id` BIGINT NOT NULL COMMENT '联系人的用户编号', + `contact_name` VARCHAR(30) NOT NULL COMMENT '联系人', + `contact_mobile` VARCHAR(11) COMMENT '联系手机', + `status` TINYINT NOT NULL COMMENT '租户状态', + `website` VARCHAR(256) COMMENT '绑定域名', + `package_id` BIGINT NOT NULL COMMENT '租户套餐编号', + `expire_time` DATETIME NOT NULL COMMENT '过期时间', + `account_count` INT NOT NULL COMMENT '账号数量', + `create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `update_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `creator` VARCHAR(64) COMMENT '创建人', + `updater` VARCHAR(64) COMMENT '更新人', + `deleted` BIT NOT NULL DEFAULT FALSE COMMENT '是否删除', + PRIMARY KEY (`id`) +) ENGINE=InnoDB COMMENT='租户表'; +``` + +#### 租户套餐表 (system_tenant_package) + +```sql +CREATE TABLE `system_tenant_package` ( + `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '套餐编号', + `name` VARCHAR(30) NOT NULL COMMENT '套餐名', + `status` TINYINT NOT NULL COMMENT '套餐状态', + `remark` VARCHAR(500) COMMENT '备注', + `menu_ids` VARCHAR(500) NOT NULL COMMENT '关联的菜单编号', + `create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `update_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `creator` VARCHAR(64) COMMENT '创建人', + `updater` VARCHAR(64) COMMENT '更新人', + `deleted` BIT NOT NULL DEFAULT FALSE COMMENT '是否删除', + PRIMARY KEY (`id`) +) ENGINE=InnoDB COMMENT='租户套餐表'; +``` + +--- + +## 数据库优化 + +### SQL 优化 + +#### 1. 避免全表扫描 + +```sql +-- 不推荐 +SELECT * FROM system_users + +-- 推荐 +SELECT id, username, nickname FROM system_users +``` + +#### 2. 使用索引 + +```sql +-- 不推荐 +SELECT * FROM system_users WHERE SUBSTRING(username, 1, 3) = 'adm' + +-- 推荐 +SELECT * FROM system_users WHERE username LIKE 'adm%' +``` + +#### 3. 分页查询 + +```sql +-- 使用分页插件 +SELECT * FROM system_users +LIMIT 10 OFFSET 0 +``` + +### 表结构优化 + +#### 1. 字段类型选择 + +```sql +-- 不推荐 +VARCHAR(1000) -- 过长 + +-- 推荐 +VARCHAR(200) -- 合理长度 +``` + +#### 2. 字段数量控制 + +单表字段数量不超过 50 个。 + +#### 3. 表分区 + +大表可以采用分区策略: + +```sql +-- 按时间分区 +CREATE TABLE `system_operate_log` ( + `id` BIGINT NOT NULL AUTO_INCREMENT, + `create_time` DATETIME NOT NULL, + PRIMARY KEY (`id`, `create_time`) +) ENGINE=InnoDB +PARTITION BY RANGE (TO_DAYS(create_time)) ( + PARTITION p202301 VALUES LESS THAN (TO_DAYS('2023-02-01')), + PARTITION p202302 VALUES LESS THAN (TO_DAYS('2023-03-01')) +); +``` + +--- + +## 数据库管理 + +### 数据库备份 + +#### 1. 逻辑备份 + +```bash +# 备份 +mysqldump -u root -p lyzsys > lyzsys_backup.sql + +# 恢复 +mysql -u root -p lyzsys < lyzsys_backup.sql +``` + +#### 2. 物理备份 + +```bash +# 复制数据文件 +cp -r /var/lib/mysql/lyzsys /backup/lyzsys +``` + +### 数据库监控 + +#### 1. 慢查询日志 + +```sql +-- 开启慢查询日志 +SET GLOBAL slow_query_log = 'ON'; +SET GLOBAL long_query_time = 2; +``` + +#### 2. 性能监控 + +```sql +-- 查看连接数 +SHOW PROCESSLIST; + +-- 查看状态 +SHOW STATUS; +``` + +### 数据库维护 + +#### 1. 表优化 + +```sql +-- 优化表 +OPTIMIZE TABLE system_users; + +-- 分析表 +ANALYZE TABLE system_users; + +-- 修复表 +REPAIR TABLE system_users; +``` + +#### 2. 索引优化 + +```sql +-- 查看索引使用情况 +SHOW INDEX FROM system_users; + +-- 删除无用索引 +DROP INDEX idx_unused ON system_users; +``` + +--- + +**文档版本**: v1.0.0 +**最后更新**: 2025-01-19 +**维护团队**: Lyzsys 数据库团队 diff --git a/doc/架构设计.md b/doc/架构设计.md new file mode 100644 index 0000000..187374b --- /dev/null +++ b/doc/架构设计.md @@ -0,0 +1,734 @@ +# Lyzsys 架构设计文档 + +## 📖 目录 + +- [架构概述](#架构概述) +- [架构设计原则](#架构设计原则) +- [分层架构](#分层架构) +- [模块化设计](#模块化设计) +- [数据架构](#数据架构) +- [安全架构](#安全架构) +- [技术架构](#技术架构) +- [部署架构](#部署架构) +- [性能优化](#性能优化) +- [扩展性设计](#扩展性设计) + +--- + +## 架构概述 + +### 整体架构 + +Lyzsys 采用**前后端分离**的**模块化单体架构**,基于**领域驱动设计(DDD)**思想进行模块划分,支持未来向微服务架构演进。 + +``` +┌─────────────────────────────────────────────────────────────────┐ +│ 客户端层 │ +│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │ +│ │ Web 浏览器 │ │ 移动 App │ │ 小程序 │ │ +│ │ (Vue3) │ │ (UniApp) │ │ (UniApp) │ │ +│ └──────────────┘ └──────────────┘ └──────────────┘ │ +└─────────────────────────────────────────────────────────────────┘ + │ + ▼ +┌─────────────────────────────────────────────────────────────────┐ +│ 接入层 │ +│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │ +│ │ Nginx / │ │ API 网关 │ │ 负载均衡 │ │ +│ │ CDN │ │ (可选) │ │ │ │ +│ └──────────────┘ └──────────────┘ └──────────────┘ │ +└─────────────────────────────────────────────────────────────────┘ + │ + ▼ +┌─────────────────────────────────────────────────────────────────┐ +│ 应用层 │ +│ ┌──────────────────────────────────────────────────────────┐ │ +│ │ lyzsys-server │ │ +│ │ (Spring Boot 应用) │ │ +│ │ ┌────────────┐ ┌────────────┐ ┌────────────┐ │ │ +│ │ │ Controller │ │ Service │ │ DAL │ │ │ +│ │ │ 层 │ │ 层 │ │ 层 │ │ │ +│ │ └────────────┘ └────────────┘ └────────────┘ │ │ +│ └──────────────────────────────────────────────────────────┘ │ +└─────────────────────────────────────────────────────────────────┘ + │ + ┌─────────────────────┼─────────────────────┐ + │ │ │ + ▼ ▼ ▼ +┌──────────────┐ ┌──────────────────┐ ┌──────────────┐ +│lyzsys-module-│ │lyzsys-module-xxx │ │lyzsys-module-│ +│ system │ │ (业务模块) │ │ infra │ +└──────────────┘ └──────────────────┘ └──────────────┘ + │ + ┌─────────────────────┼─────────────────────┐ + │ │ │ + ▼ ▼ ▼ +┌──────────────┐ ┌──────────────────┐ ┌──────────────┐ +│lyzsys- │ │lyzsys-framework │ │lyzsys- │ +│dependencies │ │ (框架组件) │ │common │ +└──────────────┘ └──────────────────┘ └──────────────┘ + │ + ▼ +┌─────────────────────────────────────────────────────────────────┐ +│ 数据层 │ +│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │ +│ │ MySQL │ │ Redis │ │ MinIO │ │ +│ │ (主数据库) │ │ (缓存) │ │ (文件存储) │ │ +│ └──────────────┘ └──────────────┘ └──────────────┘ │ +└─────────────────────────────────────────────────────────────────┘ + │ + ▼ +┌─────────────────────────────────────────────────────────────────┐ +│ 外部服务 │ +│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │ +│ │ AI 服务 │ │ 短信服务 │ │ 支付服务 │ │ +│ │ (OpenAI等) │ │ (阿里云等) │ │ (微信等) │ │ +│ └──────────────┘ └──────────────┘ └──────────────┘ │ +└─────────────────────────────────────────────────────────────────┘ +``` + +### 架构特点 + +1. **前后端分离**: 前端和后端独立开发、部署、扩展 +2. **模块化设计**: 业务模块独立,低耦合、高内聚 +3. **分层架构**: 清晰的分层,职责明确 +4. **微服务就绪**: 模块化设计便于微服务化改造 +5. **多租户支持**: 原生支持 SaaS 多租户场景 +6. **高可用**: 支持集群部署,无状态设计 + +--- + +## 架构设计原则 + +### 1. 单一职责原则 (SRP) + +每个模块、每个类只负责一个职责。 + +**示例**: +- `UserController` 只负责接收 HTTP 请求 +- `UserService` 只负责业务逻辑处理 +- `UserMapper` 只负责数据库操作 + +### 2. 开闭原则 (OCP) + +对扩展开放,对修改关闭。 + +**示例**: +- 通过实现接口扩展功能,而非修改原有代码 +- 使用策略模式实现不同的支付方式 + +### 3. 里氏替换原则 (LSP) + +子类可以替换父类。 + +**示例**: +- `UserServiceImpl` 可以替换 `UserService` +- `BaseMapperX` 可以替换 `BaseMapper` + +### 4. 接口隔离原则 (ISP) + +使用多个细粒度的接口,而非单一的总接口。 + +**示例**: +- `UserService`、`RoleService`、`MenuService` 各司其职 +- 前端 API 按模块划分(`/system/user`、`/system/role`) + +### 5. 依赖倒置原则 (DIP) + +高层模块不依赖低层模块,都依赖于抽象。 + +**示例**: +- Controller 依赖 Service 接口,而非实现 +- Service 依赖 Mapper 接口,而非实现 + +### 6. 迪米特法则 (LoD) + +最少知识原则,模块之间尽量少交互。 + +**示例**: +- 模块之间通过 API 接口交互 +- 避免跨层调用(如 Controller 直接调用 Mapper) + +--- + +## 分层架构 + +### 应用分层 + +``` +┌─────────────────────────────────────────────────────────────┐ +│ Controller 层 │ +│ • 接收 HTTP 请求 │ +│ • 参数校验 │ +│ • 调用 Service 层 │ +│ • 返回响应 │ +└─────────────────────────────────────────────────────────────┘ + │ + ▼ +┌─────────────────────────────────────────────────────────────┐ +│ Service 层 │ +│ • 业务逻辑处理 │ +│ • 事务控制 │ +│ • 调用 DAL 层 │ +│ • 返回处理结果 │ +└─────────────────────────────────────────────────────────────┘ + │ + ▼ +┌─────────────────────────────────────────────────────────────┐ +│ DAL 层 │ +│ • 数据访问 │ +│ • 数据库操作 │ +│ • 缓存操作 │ +│ • 返回数据对象 │ +└─────────────────────────────────────────────────────────────┘ +``` + +### 层次交互规则 + +1. **自上而下调用**: Controller → Service → DAL +2. **跨层访问**: 允许 Service 直接调用多个 DAL +3. **禁止反向调用**: 下层不能调用上层 +4. **同层交互**: 同层之间通过接口交互 + +### 分层示例 + +#### Controller 层 + +```java +@RestController +@RequestMapping("/system/user") +@Tag(name = "管理后台 - 用户") +public class UserController { + + @Autowired + private UserService userService; + + @PostMapping("/create") + @Operation(summary = "创建用户") + public CommonResult createUser(@Valid @RequestBody UserCreateReqVO reqVO) { + return success(userService.createUser(reqVO)); + } + + @GetMapping("/get") + @Operation(summary = "获取用户详情") + public CommonResult getUser(@RequestParam("id") Long id) { + return success(userService.getUser(id)); + } +} +``` + +#### Service 层 + +```java +@Service +public class UserServiceImpl implements UserService { + + @Autowired + private UserMapper userMapper; + + @Autowired + private DeptMapper deptMapper; + + @Override + @Transactional(rollbackFor = Exception.class) + public Long createUser(UserCreateReqVO reqVO) { + // 业务逻辑 + UserDO user = UserConvert.INSTANCE.convert(reqVO); + userMapper.insert(user); + return user.getId(); + } + + @Override + public UserRespVO getUser(Long id) { + UserDO user = userMapper.selectById(id); + DeptDO dept = deptMapper.selectById(user.getDeptId()); + return UserConvert.INSTANCE.convert(user, dept); + } +} +``` + +#### DAL 层 + +```java +@Mapper +public interface UserMapper extends BaseMapperX { + + default UserDO selectByUsername(String username) { + return selectOne("username", username); + } + + default PageResult selectPage(UserPageReqVO pageReqVO) { + return selectPage(pageReqVO, new LambdaQueryWrapperX() + .likeIfPresent(UserDO::getUsername, pageReqVO.getUsername()) + .betweenIfPresent(UserDO::getCreateTime, pageReqVO.getCreateTime()) + .orderByDesc(UserDO::getId)); + } +} +``` + +--- + +## 模块化设计 + +### 模块划分 + +项目按照**领域驱动设计(DDD)**思想进行模块划分。 + +#### 基础模块 + +| 模块 | 职责 | +|------|------| +| lyzsys-dependencies | 依赖版本管理 | +| lyzsys-framework | 框架组件封装 | +| lyzsys-server | 应用启动入口 | + +#### 业务模块 + +| 模块 | 领域 | 职责 | +|------|------|------| +| lyzsys-module-system | 系统管理 | 用户、角色、菜单、部门、字典等 | +| lyzsys-module-infra | 基础设施 | 代码生成、文件、配置、任务等 | +| lyzsys-module-bpm | 工作流 | 流程定义、流程实例、任务管理 | +| lyzsys-module-pay | 支付 | 支付订单、退款、回调 | +| lyzsys-module-member | 会员 | 会员、积分、等级 | +| lyzsys-module-mall | 商城 | 商品、订单、营销 | +| lyzsys-module-crm | CRM | 客户、商机、合同 | +| lyzsys-module-erp | ERP | 采购、销售、库存 | +| lyzsys-module-ai | AI | AI 聊天、绘图、知识库 | +| lyzsys-module-mp | 微信公众号 | 公众号管理、粉丝、消息 | +| lyzsys-module-iot | IoT | 设备、产品、数据采集 | +| lyzsys-module-report | 报表 | 报表设计、大屏设计 | + +### 模块结构 + +每个业务模块都遵循统一的结构: + +``` +lyzsys-module-xxx/ +├── api/ # 对外 API +│ ├── xxxApi.java +│ └── xxxApiImpl.java +├── controller/ # 控制器 +│ ├── admin/ # 管理后台 API +│ │ ├── xxxController.java +│ │ └── vo/ +│ │ ├── xxxReqVO.java +│ │ └── xxxRespVO.java +│ └── app/ # 用户 App API +│ └── xxxController.java +├── service/ # 服务层 +│ ├── xxxService.java +│ └── xxxServiceImpl.java +├── dal/ # 数据访问层 +│ ├── dataobject/ # 数据对象 +│ │ └── xxxDO.java +│ ├── mysql/ # MySQL Mapper +│ │ └── xxxMapper.java +│ └── redis/ # Redis DAO +│ └── xxxRedisDAO.java +├── convert/ # 对象转换 +│ └── xxxConvert.java +├── enums/ # 枚举 +│ └── xxxEnum.java +└── framework/ # 框架配置 + └── xxxConfiguration.java +``` + +### 模块交互 + +#### 模块间调用规则 + +1. **禁止直接依赖**: 模块之间不能直接依赖 +2. **通过 API 调用**: 通过 API 接口进行调用 +3. **事件驱动**: 通过消息队列进行异步通信 + +#### 示例 + +```java +// mall 模块调用 pay 模块 +@DubboReference +private PayOrderApi payOrderApi; + +public void createOrder(OrderCreateReqVO reqVO) { + // 创建订单 + OrderDO order = createOrder(reqVO); + + // 调用支付模块 + PayOrderCreateReqDTO payReq = new PayOrderCreateReqDTO(); + payReq.setOrderId(order.getId()); + payOrderApi.createOrder(payReq); +} +``` + +--- + +## 数据架构 + +### 数据存储 + +``` +┌─────────────────────────────────────────────────────────────┐ +│ 数据层 │ +│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │ +│ │ MySQL │ │ Redis │ │ MinIO │ │ +│ │ (主数据库) │ │ (缓存) │ │ (文件存储) │ │ +│ └──────────────┘ └──────────────┘ └──────────────┘ │ +└─────────────────────────────────────────────────────────────┘ +``` + +### 数据库设计 + +#### 表命名规范 + +- 格式: `{模块}_{业务}_{实体}` +- 示例: `system_users`、`system_roles`、`mall_orders` + +#### 字段命名规范 + +- 小写字母 + 下划线 +- 示例: `user_id`、`user_name`、`create_time` + +#### 通用字段 + +每张表都包含以下通用字段: + +```sql +id BIGINT 主键 +create_time DATETIME 创建时间 +update_time DATETIME 更新时间 +creator VARCHAR(64) 创建人 +updater VARCHAR(64) 更新人 +deleted BIT 是否删除 +tenant_id BIGINT 租户 ID (多租户表) +``` + +### 多租户数据隔离 + +#### 策略 + +- **共享数据库、共享 Schema**: 所有租户共享数据库,通过 `tenant_id` 隔离 +- **自动过滤**: MyBatis Plus 拦截器自动添加租户条件 + +#### 实现 + +```java +@TableName("system_users") +public class UserDO extends TenantBaseDO { + private Long id; + private String username; + // tenant_id 由 TenantBaseDO 提供 +} + +// 查询时自动过滤 +List users = userMapper.selectList(); +// SQL: SELECT * FROM system_users WHERE deleted = 0 AND tenant_id = ? +``` + +### 缓存设计 + +#### 缓存策略 + +1. **本地缓存**: Caffeine(本地缓存) +2. **分布式缓存**: Redis(分布式缓存) + +#### 缓存使用 + +```java +// 使用 Spring Cache +@Cacheable(value = "user", key = "#id") +public UserDO getUser(Long id) { + return userMapper.selectById(id); +} + +// 使用 RedisTemplate +@Service +public class UserServiceImpl { + + @Autowired + private RedisTemplate redisTemplate; + + public UserDO getUser(Long id) { + String key = "user:" + id; + UserDO user = redisTemplate.opsForValue().get(key); + + if (user == null) { + user = userMapper.selectById(id); + redisTemplate.opsForValue().set(key, user, 1, TimeUnit.HOURS); + } + + return user; + } +} +``` + +--- + +## 安全架构 + +### 认证授权 + +#### 认证流程 + +``` +1. 用户登录 + ↓ +2. 后端验证用户名密码 + ↓ +3. 生成 JWT Token + ↓ +4. 返回 Token 给前端 + ↓ +5. 前端存储 Token + ↓ +6. 后续请求携带 Token + ↓ +7. 后端验证 Token + ↓ +8. 允许访问 +``` + +#### 授权模型 + +``` +用户 (User) + ↓ +角色 (Role) + ↓ +权限 (Permission) + ↓ +资源 (Resource) +``` + +### 数据权限 + +#### 权限范围 + +| 权限范围 | 说明 | +|---------|------| +| 全部数据权限 | 查看所有数据 | +| 本部门数据权限 | 只能查看本部门数据 | +| 本部门及以下数据权限 | 查看本部门及子部门数据 | +| 仅本人数据权限 | 只能查看自己的数据 | +| 自定义数据权限 | 自定义数据权限规则 | + +#### 实现 + +```java +@DataScope(deptAlias = "d", userAlias = "u") +public List getUserList() { + return userMapper.selectList(); +} + +// SQL 自动添加 +// AND (d.id = ? OR d.id IN (?, ?) OR u.id = ?) +``` + +### API 安全 + +#### 接口加密 + +```java +// 请求加密 +@PostMapping("/create") +public CommonResult createUser(@RequestBody String encryptedData) { + // 解密 + String json = decrypt(encryptedData); + UserCreateReqVO reqVO = JSON.parseObject(json, UserCreateReqVO.class); + + // 业务处理 + Long id = userService.createUser(reqVO); + + // 加密返回 + return success(encrypt(id)); +} +``` + +#### 接口签名 + +```java +// 请求签名 +@PostMapping("/create") +public CommonResult createUser( + @RequestHeader("X-Signature") String signature, + @RequestBody UserCreateReqVO reqVO +) { + // 验证签名 + if (!verifySignature(signature, reqVO)) { + return error(401, "签名验证失败"); + } + + // 业务处理 + return success(userService.createUser(reqVO)); +} +``` + +--- + +## 技术架构 + +### 技术选型 + +#### 后端技术栈 + +| 技术 | 版本 | 用途 | +|------|------|------| +| Spring Boot | 2.7.18 | 应用框架 | +| Spring Security | 5.8.16 | 安全框架 | +| MyBatis Plus | 3.5.15 | ORM 框架 | +| Flowable | 6.8.0 | 工作流引擎 | +| Quartz | 2.3.2 | 定时任务 | +| Redisson | 3.52.0 | 分布式锁 | +| Knife4j | 3.0.3 | API 文档 | + +#### 前端技术栈 + +| 技术 | 版本 | 用途 | +|------|------|------| +| Vue | 3.2+ | 前端框架 | +| TypeScript | 4.x | 类型系统 | +| Vite | 4.x | 构建工具 | +| Element Plus | 2.x | UI 组件库 | +| Pinia | 2.x | 状态管理 | + +### 框架封装 + +#### Web 封装 + +- 全局异常处理 +- 统一响应格式 +- 请求日志记录 +- 参数校验 + +#### 安全封装 + +- JWT 认证 +- 权限注解 +- 数据权限 +- API 加密 + +#### 数据库封装 + +- BaseMapperX +- LambdaQueryWrapperX +- 分页插件 +- 租户插件 + +--- + +## 部署架构 + +### 单机部署 + +``` +┌─────────────────────────────────────────────────────────────┐ +│ 服务器 │ +│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │ +│ │ Nginx │ │ JDK 8 │ │ MySQL │ │ +│ │ (前端) │ │ (后端) │ │ (数据库) │ │ +│ └──────────────┘ └──────────────┘ └──────────────┘ │ +│ ┌──────────────┐ ┌──────────────┐ │ +│ │ Redis │ │ MinIO │ │ +│ │ (缓存) │ │ (文件存储) │ │ +│ └──────────────┘ └──────────────┘ │ +└─────────────────────────────────────────────────────────────┘ +``` + +### 集群部署 + +``` +┌─────────────────────────────────────────────────────────────┐ +│ 负载均衡 │ +│ (Nginx / F5) │ +└─────────────────────────────────────────────────────────────┘ + │ │ │ + ▼ ▼ ▼ +┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ +│ 应用服务器 1 │ │ 应用服务器 2 │ │ 应用服务器 3 │ +│ (后端服务) │ │ (后端服务) │ │ (后端服务) │ +└─────────────────┘ └─────────────────┘ └─────────────────┘ + │ │ │ + └────────────────┼────────────────┘ + ▼ + ┌─────────────────┐ + │ MySQL 主从 │ + │ Redis 集群 │ + └─────────────────┘ +``` + +### 容器化部署 + +``` +┌─────────────────────────────────────────────────────────────┐ +│ Kubernetes 集群 │ +│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │ +│ │ Pod 1 │ │ Pod 2 │ │ Pod 3 │ │ +│ │ (后端服务) │ │ (后端服务) │ │ (后端服务) │ │ +│ └──────────────┘ └──────────────┘ └──────────────┘ │ +│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │ +│ │ MySQL │ │ Redis │ │ MinIO │ │ +│ │ (StatefulSet)│ │ (StatefulSet)│ │ (Deployment)│ │ +│ └──────────────┘ └──────────────┘ └──────────────┘ │ +└─────────────────────────────────────────────────────────────┘ +``` + +--- + +## 性能优化 + +### 数据库优化 + +1. **索引优化**: 合理创建索引 +2. **SQL 优化**: 避免全表扫描 +3. **分页查询**: 使用分页插件 +4. **读写分离**: 主从数据库配置 +5. **连接池**: Druid 连接池优化 + +### 缓存优化 + +1. **本地缓存**: Caffeine 本地缓存 +2. **分布式缓存**: Redis 缓存 +3. **缓存预热**: 系统启动时加载热点数据 +4. **缓存更新**: 定时更新缓存 + +### 接口优化 + +1. **批量操作**: 批量插入、批量更新 +2. **异步处理**: 消息队列异步处理 +3. **接口合并**: 减少请求次数 +4. **压缩传输**: Gzip 压缩 + +### 前端优化 + +1. **代码分割**: 路由懒加载 +2. **资源压缩**: Gzip、Brotli 压缩 +3. **CDN 加速**: 静态资源 CDN +4. **浏览器缓存**: 合理设置缓存策略 + +--- + +## 扩展性设计 + +### 水平扩展 + +1. **应用集群**: 多台应用服务器 +2. **数据库集群**: 主从、分库分表 +3. **缓存集群**: Redis 集群 +4. **文件存储**: 分布式文件系统 + +### 垂直扩展 + +1. **升级硬件**: CPU、内存、磁盘 +2. **优化配置**: JVM、数据库参数 + +### 微服务化 + +1. **模块拆分**: 按业务模块拆分 +2. **服务注册**: Nacos、Eureka +3. **服务调用**: Dubbo、Feign +4. **网关路由**: Spring Cloud Gateway + +--- + +**文档版本**: v1.0.0 +**最后更新**: 2025-01-19 +**维护团队**: Lyzsys 架构团队 diff --git a/doc/部署指南.md b/doc/部署指南.md new file mode 100644 index 0000000..c9d2c3a --- /dev/null +++ b/doc/部署指南.md @@ -0,0 +1,805 @@ +# Lyzsys 部署指南 + +## 📖 目录 + +- [部署概述](#部署概述) +- [环境准备](#环境准备) +- [后端部署](#后端部署) +- [前端部署](#前端部署) +- [数据库部署](#数据库部署) +- [缓存部署](#缓存部署) +- [文件存储部署](#文件存储部署) +- [生产环境部署](#生产环境部署) +- [容器化部署](#容器化部署) +- [监控部署](#监控部署) + +--- + +## 部署概述 + +### 部署架构 + +``` +┌─────────────────────────────────────────────────────────────┐ +│ 用户端 │ +│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │ +│ │ PC 浏览器 │ │ 移动 App │ │ 小程序 │ │ +│ └──────────────┘ └──────────────┘ └──────────────┘ │ +└─────────────────────────────────────────────────────────────┘ + │ + ▼ +┌─────────────────────────────────────────────────────────────┐ +│ Nginx │ +│ (反向代理 + 静态资源) │ +└─────────────────────────────────────────────────────────────┘ + │ + ┌─────────────┴─────────────┐ + │ │ + ▼ ▼ +┌──────────────────────────┐ ┌──────────────────────────┐ +│ 前端静态资源 │ │ 后端 API 服务 │ +│ (Vue3 SPA 应用) │ │ (Spring Boot 应用) │ +└──────────────────────────┘ └──────────────────────────┘ + │ + ┌─────────────────────────┼─────────────────────────┐ + │ │ │ + ▼ ▼ ▼ +┌──────────────────┐ ┌──────────────────┐ ┌──────────────────┐ +│ MySQL │ │ Redis │ │ MinIO │ +│ (主数据库) │ │ (缓存/会话) │ │ (文件存储) │ +└──────────────────┘ └──────────────────┘ └──────────────────┘ +``` + +### 部署方式 + +1. **传统部署**: 直接在服务器上部署 +2. **Docker 部署**: 使用 Docker 容器部署 +3. **Kubernetes 部署**: 使用 K8s 编排部署 + +--- + +## 环境准备 + +### 服务器要求 + +#### 最低配置 + +| 组件 | CPU | 内存 | 硬盘 | +|------|-----|------|------| +| 后端服务 | 2核 | 4GB | 20GB | +| MySQL | 1核 | 2GB | 50GB | +| Redis | 1核 | 1GB | 10GB | +| 前端 | 1核 | 1GB | 10GB | + +#### 推荐配置 + +| 组件 | CPU | 内存 | 硬盘 | +|------|-----|------|------| +| 后端服务 | 4核 | 8GB | 50GB | +| MySQL | 4核 | 16GB | 500GB | +| Redis | 2核 | 4GB | 50GB | +| 前端 | 2核 | 2GB | 20GB | + +### 软件要求 + +| 软件 | 版本 | 用途 | +|------|------|------| +| JDK | 8+ | 后端运行环境 | +| MySQL | 5.7+ / 8.0+ | 数据库 | +| Redis | 5.0+ | 缓存 | +| Nginx | 1.18+ | Web 服务器 | +| Node.js | 16+ | 前端构建 | +| Docker | 20.10+ | 容器化(可选) | + +--- + +## 后端部署 + +### 方式一: JAR 包部署 + +#### 1. 打包项目 + +```bash +cd lyzsys_backend +mvn clean package -DskipTests +``` + +生成的 JAR 包位于 `lyzsys-server/target/lyzsys-server.jar` + +#### 2. 上传文件 + +将 JAR 包上传到服务器: + +```bash +scp lyzsys-server/target/lyzsys-server.jar user@server:/opt/lyzsys/ +``` + +#### 3. 配置文件 + +创建配置文件 `application-prod.yaml`: + +```yaml +spring: + # 数据源配置 + datasource: + url: jdbc:mysql://mysql-server:3306/lyzsys?useSSL=false&serverTimezone=Asia/Shanghai + username: lyzsys + password: your_password + driver-class-name: com.mysql.cj.jdbc.Driver + + # Redis 配置 + redis: + host: redis-server + port: 6379 + database: 1 + password: your_redis_password + +# 项目配置 +lyzsys: + web: + api-prefix: /admin-api + security: + mock-enable: false + upload: + base-url: http://your-domain.com +``` + +#### 4. 启动服务 + +```bash +# 启动服务 +java -jar lyzsys-server.jar --spring.profiles.active=prod + +# 后台启动 +nohup java -jar lyzsys-server.jar --spring.profiles.active=prod > lyzsys.log 2>&1 & + +# 指定内存启动 +java -Xms512m -Xmx1024m -jar lyzsys-server.jar --spring.profiles.active=prod +``` + +#### 5. 创建系统服务 + +创建 `/etc/systemd/system/lyzsys.service`: + +```ini +[Unit] +Description=Lyzsys Server +After=syslog.target network.target + +[Service] +Type=simple +ExecStart=/usr/bin/java -jar /opt/lyzsys/lyzsys-server.jar --spring.profiles.active=prod +ExecStop=/bin/kill -15 $MAINPID +User=lyzsys +Group=lyzsys +WorkingDirectory=/opt/lyzsys +Restart=always +RestartSec=10 + +[Install] +WantedBy=multi-user.target +``` + +启动服务: + +```bash +# 重载配置 +systemctl daemon-reload + +# 启动服务 +systemctl start lyzsys + +# 开机启动 +systemctl enable lyzsys + +# 查看状态 +systemctl status lyzsys +``` + +### 方式二: Docker 部署 + +#### 1. 创建 Dockerfile + +创建 `Dockerfile`: + +```dockerfile +FROM openjdk:8-jre-slim + +LABEL maintainer="lyzsys" + +# 设置工作目录 +WORKDIR /opt/lyzsys + +# 复制 JAR 包 +COPY lyzsys-server/target/lyzsys-server.jar app.jar + +# 暴露端口 +EXPOSE 48080 + +# 启动应用 +ENTRYPOINT ["java", "-jar", "app.jar"] +``` + +#### 2. 构建镜像 + +```bash +docker build -t lyzsys/lyzsys-server:latest . +``` + +#### 3. 运行容器 + +```bash +docker run -d \ + --name lyzsys-server \ + -p 48080:48080 \ + -e SPRING_PROFILES_ACTIVE=prod \ + -e SPRING_DATASOURCE_URL=jdbc:mysql://mysql:3306/lyzsys \ + -e SPRING_DATASOURCE_USERNAME=lyzsys \ + -e SPRING_DATASOURCE_PASSWORD=your_password \ + -e SPRING_DATA_REDIS_HOST=redis \ + -e SPRING_DATA_REDIS_PASSWORD=your_redis_password \ + lyzsys/lyzsys-server:latest +``` + +#### 4. 使用 Docker Compose + +创建 `docker-compose.yml`: + +```yaml +version: '3.8' + +services: + lyzsys-server: + image: lyzsys/lyzsys-server:latest + container_name: lyzsys-server + ports: + - "48080:48080" + environment: + - SPRING_PROFILES_ACTIVE=prod + - SPRING_DATASOURCE_URL=jdbc:mysql://mysql:3306/lyzsys + - SPRING_DATASOURCE_USERNAME=lyzsys + - SPRING_DATASOURCE_PASSWORD=your_password + - SPRING_DATA_REDIS_HOST=redis + - SPRING_DATA_REDIS_PASSWORD=your_redis_password + depends_on: + - mysql + - redis + restart: always +``` + +启动: + +```bash +docker-compose up -d +``` + +--- + +## 前端部署 + +### 方式一: Nginx 部署 + +#### 1. 构建项目 + +```bash +cd lyzsys-ui-admin + +# 安装依赖 +pnpm install + +# 构建生产版本 +pnpm build:prod +``` + +生成的文件位于 `dist/` 目录 + +#### 2. 上传文件 + +将 `dist/` 目录上传到服务器: + +```bash +scp -r dist/* user@server:/var/www/lyzsys/ +``` + +#### 3. 配置 Nginx + +创建 Nginx 配置 `/etc/nginx/conf.d/lyzsys.conf`: + +```nginx +server { + listen 80; + server_name your-domain.com; + + root /var/www/lyzsys; + index index.html; + + # 前端路由 + location / { + try_files $uri $uri/ /index.html; + } + + # API 代理 + location /admin-api/ { + proxy_pass http://localhost:48080/admin-api/; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_connect_timeout 60s; + proxy_read_timeout 60s; + proxy_send_timeout 60s; + } + + # 静态资源缓存 + location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ { + expires 1y; + add_header Cache-Control "public, immutable"; + } + + # Gzip 压缩 + gzip on; + gzip_types text/plain text/css application/json application/javascript; + gzip_min_length 1024; +} +``` + +#### 4. 重启 Nginx + +```bash +nginx -t +nginx -s reload +``` + +### 方式二: Docker 部署 + +#### 1. 创建 Dockerfile + +创建 `Dockerfile`: + +```dockerfile +FROM nginx:alpine + +# 复制构建文件 +COPY dist/ /usr/share/nginx/html/ + +# 复制 Nginx 配置 +COPY nginx.conf /etc/nginx/conf.d/default.conf + +# 暴露端口 +EXPOSE 80 + +# 启动 Nginx +CMD ["nginx", "-g", "daemon off;"] +``` + +#### 2. 构建镜像 + +```bash +docker build -t lyzsys/lyzsys-ui-admin:latest . +``` + +#### 3. 运行容器 + +```bash +docker run -d \ + --name lyzsys-ui-admin \ + -p 80:80 \ + lyzsys/lyzsys-ui-admin:latest +``` + +--- + +## 数据库部署 + +### MySQL 部署 + +#### 1. 安装 MySQL + +```bash +# CentOS/RHEL +yum install -y mysql-server + +# Ubuntu/Debian +apt-get install -y mysql-server +``` + +#### 2. 配置 MySQL + +编辑 `/etc/my.cnf`: + +```ini +[mysqld] +# 基础配置 +port = 3306 +character-set-server = utf8mb4 +collation-server = utf8mb4_unicode_ci + +# 连接配置 +max_connections = 500 +max_connect_errors = 100 + +# 缓存配置 +innodb_buffer_pool_size = 1G +query_cache_size = 128M + +# 日志配置 +slow_query_log = 1 +slow_query_log_file = /var/log/mysql/slow.log +long_query_time = 2 +``` + +#### 3. 创建数据库 + +```bash +mysql -u root -p + +CREATE DATABASE lyzsys CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; +CREATE USER 'lyzsys'@'%' IDENTIFIED BY 'your_password'; +GRANT ALL PRIVILEGES ON lyzsys.* TO 'lyzsys'@'%'; +FLUSH PRIVILEGES; +``` + +#### 4. 导入数据 + +```bash +mysql -u lyzsys -p lyzsys < lyzsys.sql +``` + +### Docker 部署 MySQL + +```bash +docker run -d \ + --name mysql \ + -p 3306:3306 \ + -e MYSQL_ROOT_PASSWORD=root_password \ + -e MYSQL_DATABASE=lyzsys \ + -e MYSQL_USER=lyzsys \ + -e MYSQL_PASSWORD=your_password \ + -v /data/mysql:/var/lib/mysql \ + mysql:8.0 +``` + +--- + +## 缓存部署 + +### Redis 部署 + +#### 1. 安装 Redis + +```bash +# CentOS/RHEL +yum install -y redis + +# Ubuntu/Debian +apt-get install -y redis-server +``` + +#### 2. 配置 Redis + +编辑 `/etc/redis/redis.conf`: + +```ini +# 绑定地址 +bind 0.0.0.0 + +# 端口 +port 6379 + +# 密码 +requirepass your_redis_password + +# 持久化 +save 900 1 +save 300 10 +save 60 10000 + +# 最大内存 +maxmemory 1gb +maxmemory-policy allkeys-lru +``` + +#### 3. 启动 Redis + +```bash +# 启动 Redis +redis-server /etc/redis/redis.conf + +# 或使用 systemd +systemctl start redis +systemctl enable redis +``` + +### Docker 部署 Redis + +```bash +docker run -d \ + --name redis \ + -p 6379:6379 \ + -v /data/redis:/data \ + redis:7-alpine \ + redis-server --appendonly yes --requirepass your_redis_password +``` + +--- + +## 文件存储部署 + +### MinIO 部署 + +#### 1. Docker 部署 MinIO + +```bash +docker run -d \ + --name minio \ + -p 9000:9000 \ + -p 9001:9001 \ + -e MINIO_ROOT_USER=admin \ + -e MINIO_ROOT_PASSWORD=admin123 \ + -v /data/minio:/data \ + minio/minio server /data --console-address ":9001" +``` + +#### 2. 配置 MinIO + +1. 访问 http://localhost:9001 +2. 登录(admin / admin123) +3. 创建 Bucket: `lyzsys` +4. 创建 Access Key 和 Secret Key +5. 配置后端 `application.yaml`: + +```yaml +lyzsys: + storage: + minio: + endpoint: http://localhost:9000 + access-key: your_access_key + secret-key: your_secret_key + bucket-name: lyzsys +``` + +--- + +## 生产环境部署 + +### 安全配置 + +#### 1. 配置防火墙 + +```bash +# 开放必要端口 +firewall-cmd --permanent --add-port=80/tcp +firewall-cmd --permanent --add-port=443/tcp +firewall-cmd --permanent --add-port=48080/tcp +firewall-cmd --reload +``` + +#### 2. 配置 SSL 证书 + +使用 Let's Encrypt 免费证书: + +```bash +# 安装 certbot +yum install -y certbot + +# 获取证书 +certbot certonly --standalone -d your-domain.com + +# 证书位置 +# /etc/letsencrypt/live/your-domain.com/fullchain.pem +# /etc/letsencrypt/live/your-domain.com/privkey.pem +``` + +配置 Nginx SSL: + +```nginx +server { + listen 443 ssl http2; + server_name your-domain.com; + + ssl_certificate /etc/letsencrypt/live/your-domain.com/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/your-domain.com/privkey.pem; + + ssl_protocols TLSv1.2 TLSv1.3; + ssl_ciphers HIGH:!aNULL:!MD5; + ssl_prefer_server_ciphers on; + + # ... 其他配置 +} + +# HTTP 跳转 HTTPS +server { + listen 80; + server_name your-domain.com; + return 301 https://$server_name$request_uri; +} +``` + +### 性能优化 + +#### 1. MySQL 优化 + +```ini +# my.cnf +[mysqld] +innodb_buffer_pool_size = 4G +innodb_log_file_size = 512M +innodb_flush_log_at_trx_commit = 2 +innodb_flush_method = O_DIRECT +``` + +#### 2. Redis 优化 + +```ini +# redis.conf +maxmemory 2gb +maxmemory-policy allkeys-lru +save "" +``` + +#### 3. JVM 优化 + +```bash +java -Xms2g -Xmx2g \ + -XX:+UseG1GC \ + -XX:MaxGCPauseMillis=200 \ + -XX:+HeapDumpOnOutOfMemoryError \ + -XX:HeapDumpPath=/opt/lyzsys/logs/ \ + -jar lyzsys-server.jar +``` + +--- + +## 容器化部署 + +### Docker Compose 完整部署 + +创建 `docker-compose.yml`: + +```yaml +version: '3.8' + +services: + # MySQL + mysql: + image: mysql:8.0 + container_name: lyzsys-mysql + environment: + - MYSQL_ROOT_PASSWORD=root_password + - MYSQL_DATABASE=lyzsys + - MYSQL_USER=lyzsys + - MYSQL_PASSWORD=your_password + volumes: + - mysql-data:/var/lib/mysql + ports: + - "3306:3306" + restart: always + + # Redis + redis: + image: redis:7-alpine + container_name: lyzsys-redis + command: redis-server --appendonly yes --requirepass your_redis_password + volumes: + - redis-data:/data + ports: + - "6379:6379" + restart: always + + # MinIO + minio: + image: minio/minio + container_name: lyzsys-minio + environment: + - MINIO_ROOT_USER=admin + - MINIO_ROOT_PASSWORD=admin123 + volumes: + - minio-data:/data + ports: + - "9000:9000" + - "9001:9001" + command: server /data --console-address ":9001" + restart: always + + # 后端服务 + backend: + image: lyzsys/lyzsys-server:latest + container_name: lyzsys-backend + environment: + - SPRING_PROFILES_ACTIVE=prod + - SPRING_DATASOURCE_URL=jdbc:mysql://mysql:3306/lyzsys + - SPRING_DATASOURCE_USERNAME=lyzsys + - SPRING_DATASOURCE_PASSWORD=your_password + - SPRING_DATA_REDIS_HOST=redis + - SPRING_DATA_REDIS_PASSWORD=your_redis_password + ports: + - "48080:48080" + depends_on: + - mysql + - redis + restart: always + + # 前端服务 + frontend: + image: lyzsys/lyzsys-ui-admin:latest + container_name: lyzsys-frontend + ports: + - "80:80" + depends_on: + - backend + restart: always + +volumes: + mysql-data: + redis-data: + minio-data: +``` + +启动: + +```bash +docker-compose up -d +``` + +--- + +## 监控部署 + +### Spring Boot Admin + +#### 1. 添加依赖 + +```xml + + de.codecentric + spring-boot-admin-starter-server + +``` + +#### 2. 配置应用 + +```yaml +spring: + application: + name: lyzsys-admin-server + +server: + port: 48081 +``` + +#### 3. 客户端配置 + +```yaml +spring: + boot: + admin: + client: + url: http://localhost:48081 +``` + +### SkyWalking + +#### 1. 安装 SkyWalking + +```bash +docker run -d \ + --name skywalking \ + -p 11800:11800 \ + -p 12800:12800 \ + apache/skywalking-oap-server +``` + +#### 2. 配置 Agent + +```bash +java -javaagent:/path/to/skywalking-agent.jar \ + -Dskywalking.agent.service_name=lyzsys \ + -Dskywalking.collector.backend_service=localhost:11800 \ + -jar lyzsys-server.jar +``` + +--- + +**文档版本**: v1.0.0 +**最后更新**: 2025-01-19 +**维护团队**: Lyzsys 运维团队 diff --git a/doc/项目介绍.md b/doc/项目介绍.md new file mode 100644 index 0000000..55ba24d --- /dev/null +++ b/doc/项目介绍.md @@ -0,0 +1,508 @@ +# Lyzsys 项目介绍 + +## 📖 目录 + +- [项目简介](#项目简介) +- [核心特性](#核心特性) +- [技术架构](#技术架构) +- [功能模块](#功能模块) +- [快速开始](#快速开始) +- [项目展示](#项目展示) +- [适用场景](#适用场景) +- [开源协议](#开源协议) + +--- + +## 项目简介 + +Lyzsys 是一个**企业级后台管理系统**,基于 Spring Boot + Vue 3 技术栈构建,采用前后端分离架构。项目集成了丰富的企业级功能,包括权限管理、工作流、多租户、AI 集成等,适用于各类企业管理系统的快速开发。 + +### 项目定位 + +- **快速开发平台**: 提供完整的代码生成器和脚手架,快速构建业务系统 +- **企业级框架**: 内置权限、工作流、多租户等企业通用功能 +- **微服务就绪**: 模块化设计,便于未来微服务化改造 +- **AI 集成**: 原生支持多个 AI 服务提供商,便于构建智能化应用 + +### 版本说明 + +| 版本 | JDK 8 + Spring Boot 2.7 | JDK 17/21 + Spring Boot 3.2 | +|------|-------------------------|----------------------------| +| 【完整版】lyzsys | `master` 分支 | `master-jdk17` 分支 | +| 【精简版】lyzsys-mini | `mini` 分支 | `mini-jdk17` 分支 | + +- **完整版**: 包括系统功能、基础设施、工作流、商城、CRM、ERP、AI 等所有模块 +- **精简版**: 只包括系统功能和基础设施,适用于简单场景 + +--- + +## 核心特性 + +### 🎯 技术特性 + +#### 1. 模块化架构 + +- **Maven 多模块**: 清晰的模块划分,便于维护和扩展 +- **前后端分离**: 独立部署,提升开发效率 +- **微服务就绪**: 模块化设计便于微服务化改造 + +#### 2. 权限管理 + +- **RBAC 权限模型**: 基于角色的访问控制 +- **数据权限**: 支持全部、本部门、本部门及以下、仅本人等数据权限 +- **按钮级权限**: 细粒度的功能权限控制 +- **动态菜单**: 根据权限动态生成菜单 + +#### 3. 多租户支持 + +- **SaaS 多租户**: 原生支持多租户场景 +- **租户隔离**: 数据库级别的租户隔离 +- **租户套餐**: 灵活的租户权限配置 + +#### 4. 工作流引擎 + +- **Flowable 集成**: 强大的工作流引擎 +- **双设计器**: BPMN 标准设计器 + 仿钉钉/飞书简易设计器 +- **流程管理**: 支持会签、或签、驳回、转办、委派等复杂流程操作 + +#### 5. AI 集成 + +- **多 AI 支持**: 支持 OpenAI、通义千问、文心一言等多个 AI 服务 +- **AI 聊天**: 内置 AI 对话功能 +- **AI 绘图**: 支持 AI 图片生成 +- **知识库**: AI 知识库管理和检索 + +#### 6. 开发效率 + +- **代码生成器**: 一键生成前后端代码、SQL 脚本、接口文档 +- **在线表单**: 拖拽式表单设计器 +- **报表设计**: 可视化报表和大屏设计器 +- **API 文档**: 自动生成 Swagger/Knife4j 接口文档 + +### 🛡️ 安全特性 + +- **Spring Security**: 企业级安全框架 +- **JWT 认证**: 无状态认证机制 +- **密码加密**: BCrypt 加密存储 +- **API 加密**: 支持请求/响应加密 +- **XSS 防护**: 内置 XSS 过滤器 +- **操作日志**: 完整的操作审计日志 + +### ⚡ 性能特性 + +- **Redis 缓存**: 高性能缓存支持 +- **数据库优化**: MyBatis Plus 增强,支持分页、排序、筛选 +- **分布式锁**: 基于 Redisson 的分布式锁 +- **消息队列**: 异步处理提升性能 +- **连接池**: Druid 监控的数据库连接池 + +--- + +## 技术架构 + +### 整体架构 + +``` +┌─────────────────────────────────────────────────────────────┐ +│ 前端应用 │ +│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │ +│ │ lyzsys-ui- │ │ lyzsys-ui- │ │ lyzsys-mall- │ │ +│ │ admin-vue3 │ │ admin-uniapp │ │ uniapp │ │ +│ │ (PC端管理) │ │ (移动端管理) │ │ (用户App) │ │ +│ └──────────────┘ └──────────────┘ └──────────────┘ │ +└─────────────────────────────────────────────────────────────┘ + │ + ▼ +┌─────────────────────────────────────────────────────────────┐ +│ lyzsys-server │ +│ (后端服务启动模块) │ +└─────────────────────────────────────────────────────────────┘ + │ + ┌─────────────────────┼─────────────────────┐ + │ │ │ + ▼ ▼ ▼ +┌──────────────┐ ┌──────────────────┐ ┌──────────────┐ +│ lyzsys- │ │ lyzsys-module-xxx│ │lyzsys- │ +│ framework │ │ (业务模块) │ │dependencies │ +│ (框架组件) │ │ │ │ (依赖管理) │ +└──────────────┘ └──────────────────┘ └──────────────┘ + │ + ├─── lyzsys-common (通用组件) + ├─── lyzsys-spring-boot-starter-web (Web 封装) + ├─── lyzsys-spring-boot-starter-security (安全认证) + ├─── lyzsys-spring-boot-starter-mybatis (数据库) + ├─── lyzsys-spring-boot-starter-redis (缓存) + ├─── lyzsys-spring-boot-starter-biz-tenant (多租户) + └─── ... + │ + ┌─────────────────────┼─────────────────────┐ + │ │ │ + ▼ ▼ ▼ +┌──────────────┐ ┌──────────────────┐ ┌──────────────┐ +│ MySQL │ │ Redis │ │ MinIO │ +│ (主数据库) │ │ (缓存数据库) │ │ (文件存储) │ +└──────────────┘ └──────────────────┘ └──────────────┘ +``` + +### 技术选型 + +#### 后端技术栈 + +| 技术 | 版本 | 说明 | +|------|------|------| +| Spring Boot | 2.7.18 | 应用开发框架 | +| Spring Security | 5.8.16 | 安全框架 | +| MyBatis Plus | 3.5.15 | ORM 增强框架 | +| Flowable | 6.8.0 | 工作流引擎 | +| Redisson | 3.52.0 | 分布式锁客户端 | +| Quartz | 2.3.2 | 定时任务 | +| Knife4j | 3.0.3 | API 文档 | +| MySQL | 5.7+ | 关系型数据库 | +| Redis | 5.0+ | 缓存数据库 | + +#### 前端技术栈 + +| 技术 | 版本 | 说明 | +|------|------|------| +| Vue | 3.2+ | 渐进式 JavaScript 框架 | +| TypeScript | 4.x | JavaScript 超集 | +| Vite | 4.x | 构建工具 | +| Element Plus | 2.x | UI 组件库 | +| Pinia | 2.x | 状态管理 | +| Vue Router | 4.x | 路由管理 | +| ECharts | 5.x | 数据可视化 | +| WangEditor | 5.x | 富文本编辑器 | + +--- + +## 功能模块 + +### 核心模块(必选) + +#### 1. 系统功能模块 (lyzsys-module-system) + +提供系统基础功能,是整个系统的基础。 + +| 功能 | 说明 | +|------|------| +| 用户管理 | 用户的增删改查、密码重置、导入导出 | +| 角色管理 | 角色权限分配、数据权限配置 | +| 菜单管理 | 动态菜单配置、按钮权限标识 | +| 部门管理 | 组织机构树形结构管理 | +| 岗位管理 | 用户岗位配置 | +| 字典管理 | 系统字典项维护 | +| 参数配置 | 系统动态参数配置 | +| 通知公告 | 系统通知发布管理 | +| 操作日志 | 用户操作审计日志 | +| 登录日志 | 登录成功/失败日志 | +| 在线用户 | 当前在线用户监控,支持踢出 | +| 租户管理 | SaaS 租户配置 | +| 租户套餐 | 租户权限套餐管理 | + +#### 2. 基础设施模块 (lyzsys-module-infra) + +提供技术基础设施功能。 + +| 功能 | 说明 | +|------|------| +| 代码生成 | 可视化代码生成,支持单表、树表、主子表 | +| 表单构建 | 拖拽式表单设计器 | +| 系统接口 | Swagger/Knife4j 接口文档 | +| 数据库文档 | Screw 自动生成数据库文档 | +| 文件管理 | 支持本地、MinIO、阿里云、腾讯云等存储 | +| 定时任务 | Quartz 在线定时任务管理 | +| API 日志 | 接口访问日志、异常日志 | +| MySQL 监控 | 数据库连接池监控 | +| Redis 监控 | Redis 使用情况监控 | +| 服务监控 | Spring Boot Admin 监控 | +| 链路追踪 | SkyWalking 链路追踪集成 | +| 日志中心 | 远程日志查看 | +| 服务保障 | 分布式锁、幂等、限流、熔断 | +| 消息队列 | Redis 消息队列支持 | + +### 业务模块(可选) + +#### 3. 工作流模块 (lyzsys-module-bpm) + +基于 Flowable 的业务流程管理。 + +| 功能 | 说明 | +|------|------| +| 流程模型 | BPMN 2.0 流程建模 | +| 流程设计 | BPMN 设计器 + 简易设计器 | +| 流程实例 | 流程实例管理、发起、审批 | +| 任务管理 | 待办、已办、抄送任务 | +| 表单管理 | 流程表单配置 | +| 流程监听 | 流程事件监听配置 | + +#### 4. 支付模块 (lyzsys-module-pay) + +统一的支付接入平台。 + +| 功能 | 说明 | +|------|------| +| 应用管理 | 支付应用配置 | +| 支付渠道 | 微信支付、支付宝等渠道接入 | +| 支付订单 | 支付订单管理 | +| 退款订单 | 退款订单管理 | +| 回调通知 | 支付回调处理 | + +#### 5. 会员模块 (lyzsys-module-member) + +C 端会员管理功能。 + +| 功能 | 说明 | +|------|------| +| 会员管理 | 会员信息管理 | +| 会员标签 | 会员标签体系 | +| 会员等级 | 会员等级配置 | +| 会员分组 | 会员分组管理 | +| 积分签到 | 积分规则、签到记录 | + +#### 6. 商城模块 (lyzsys-module-mall) + +完整的电商系统。 + +| 功能 | 说明 | +|------|------| +| 商品管理 | 商品、分类、品牌管理 | +| 营销管理 | 优惠券、满减、秒杀等活动 | +| 订单管理 | 订单、售后、退款管理 | +| 购物车 | 购物车管理 | +| 收货地址 | 用户地址管理 | +| 物流管理 | 物流公司、物流跟踪 | +| 统计分析 | 销售统计、商品分析 | + +#### 7. CRM 模块 (lyzsys-module-crm) + +客户关系管理。 + +| 功能 | 说明 | +|------|------| +| 客户管理 | 客户信息管理 | +| 联系人 | 客户联系人管理 | +| 商机管理 | 销售商机跟进 | +| 合同管理 | 合同签订、管理 | +| 回款管理 | 回款计划、记录 | +| 产品管理 | CRM 产品管理 | + +#### 8. ERP 模块 (lyzsys-module-erp) + +企业资源计划。 + +| 功能 | 说明 | +|------|------| +| 采购管理 | 采购订单、入库单 | +| 销售管理 | 销售订单、出库单 | +| 库存管理 | 库存查询、库存预警 | +| 产品管理 | 产品、物料管理 | +| 供应商管理 | 供应商信息管理 | + +#### 9. AI 模块 (lyzsys-module-ai) + +AI 大模型集成。 + +| 功能 | 说明 | +|------|------| +| AI 聊天 | 对话式 AI 交互 | +| AI 绘图 | AI 图片生成 | +| 知识库 | AI 知识库管理 | +| API 管理 | AI API 密钥管理 | + +#### 10. 报表模块 (lyzsys-module-report) + +数据报表和大屏。 + +| 功能 | 说明 | +|------|------| +| 报表设计 | 可视化报表设计器 | +| 大屏设计 | 拖拽式大屏设计器 | +| 数据源 | 多种数据源支持 | + +#### 11. 微信公众号 (lyzsys-module-mp) + +微信公众号管理。 + +| 功能 | 说明 | +|------|------| +| 账号管理 | 公众号配置 | +| 粉丝管理 | 粉丝信息、标签管理 | +| 消息管理 | 消息发送、接收 | +| 自动回复 | 关注、关键词、消息回复 | +| 菜单管理 | 公众号菜单配置 | +| 素材管理 | 图片、视频等素材管理 | +| 图文管理 | 图文素材管理 | + +#### 12. IoT 物联网 (lyzsys-module-iot) + +物联网设备管理。 + +| 功能 | 说明 | +|------|------| +| 设备管理 | 设备注册、管理 | +| 产品管理 | IoT 产品定义 | +| 属性定义 | 设备属性配置 | +| 数据采集 | 设备数据采集 | +| 场景联动 | 设备场景规则 | + +--- + +## 快速开始 + +### 环境要求 + +| 软件 | 版本要求 | 必需 | +|------|----------|------| +| JDK | 8+ | √ | +| MySQL | 5.7+ | √ | +| Redis | 5.0+ | √ | +| Node.js | 16+ | √ | +| Maven | 3.6+ | √ | + +### 后端启动 + +```bash +# 1. 克隆项目 +git clone https://github.com/your-org/lyzsys.git +cd lyzsys/lyzsys_backend + +# 2. 导入数据库 +mysql -u root -p < sql/lyzsys.sql + +# 3. 修改配置 +vi lyzsys-server/src/main/resources/application.yaml +# 配置数据库、Redis 连接信息 + +# 4. 启动后端 +cd lyzsys-server +mvn spring-boot:run +``` + +访问: http://localhost:48080/doc.html + +### 前端启动 + +```bash +# 1. 安装依赖 +cd lyzsys-ui-admin +pnpm install + +# 2. 启动开发服务器 +pnpm dev +``` + +访问: http://localhost:5173 + +默认账号: `admin` / `admin123` + +--- + +## 项目展示 + +### 系统功能 + +| 登录 & 首页 | 用户 & 应用 | 租户 & 套餐 | 部门 & 岗位 | +|------------|------------|------------|------------| +| ![登录](../.image/登录.jpg) | ![用户管理](../.image/用户管理.jpg) | ![租户管理](../.image/租户管理.jpg) | ![部门管理](../.image/部门管理.jpg) | + +| 菜单 & 角色 | 审计日志 | 短信管理 | 字典 & 敏感词 | +|------------|------------|------------|------------| +| ![菜单管理](../.image/菜单管理.jpg) | ![操作日志](../.image/操作日志.jpg) | ![短信渠道](../.image/短信渠道.jpg) | ![字典类型](../.image/字典类型.jpg) | + +### 工作流程 + +| 流程模型 | 我的流程 | 待办 & 已办 | OA 请假 | +|---------|---------|-----------|---------| +| ![流程模型](../.image/流程模型-列表.jpg) | ![我的流程](../.image/我的流程-列表.jpg) | ![任务列表](../.image/任务列表-待办.jpg) | ![OA请假](../.image/OA请假-列表.jpg) | + +### 基础设施 + +| 代码生成 | 文档 | 文件 & 配置 | 定时任务 | +|---------|-----|------------|---------| +| ![代码生成](../.image/代码生成.jpg) | ![系统接口](../.image/系统接口.jpg) | ![文件配置](../.image/文件配置.jpg) | ![定时任务](../.image/定时任务.jpg) | + +--- + +## 适用场景 + +### 适用行业 + +- **互联网**: SaaS 平台、内容管理、用户系统 +- **制造业**: ERP、MES、设备管理 +- **零售电商**: 商城系统、CRM、会员管理 +- **金融服务**: 风控系统、审批流程 +- **政府机构**: OA 系统、审批平台 +- **教育培训**: 在线教育、学员管理 +- **医疗健康**: HIS 系统、预约管理 + +### 适用场景 + +1. **企业内部系统**: OA、ERP、CRM、HR 等管理系统 +2. **SaaS 平台**: 多租户 SaaS 应用开发 +3. **电商系统**: 商城、订单、支付系统 +4. **审批系统**: 工作流、审批流程定制 +5. **AI 应用**: AI 对话、AI 知识库、AI 绘图 + +--- + +## 开源协议 + +本项目采用 **MIT 协议**开源,这意味着: + +✅ 个人和企业可以 100% 免费使用 +✅ 可以用于商业项目,无需保留类作者、Copyright 信息 +✅ 可以自由修改、分发、二次开发 +✅ 无任何商业版本限制 + +> 严肃声明:现在、未来都不会有商业版本,所有代码全部开源! + +--- + +## 相关资源 + +### 官方资源 + +- **在线文档**: https://doc.iocoder.cn +- **视频教程**: https://doc.iocoder.cn/video/ +- **Gitee 仓库**: https://gitee.com/zhijiantianya/ruoyi-vue-pro +- **GitHub 仓库**: https://github.com/YunaiV/ruoyi-vue-pro + +### 参考项目 + +本项目基于以下开源项目进行二次开发和优化: + +- **RuoYi-Vue**: 优秀的后台管理系统框架 +- **Yudao Framework**: 芋道源码框架 + +### 技术支持 + +- **文档中心**: 完整的开发文档和使用指南 +- **视频教程**: 从零开始的视频教程 +- **社区支持**: GitHub Issues、Gitee Issues + +--- + +## 更新日志 + +### v1.0.0 (2025-01-19) + +- 🎉 首次发布 Lyzsys 系统 +- ✨ 完整的系统功能和基础设施 +- ✨ 工作流模块 (BPM) +- ✨ 支付模块 (Pay) +- ✨ 会员模块 (Member) +- ✨ 商城模块 (Mall) +- ✨ CRM 模块 +- ✨ ERP 模块 +- ✨ AI 模块 +- ✨ 微信公众号模块 (MP) +- ✨ IoT 物联网模块 +- 🐛 修复已知问题 +- 📝 完善开发文档 + +--- + +**项目**: Lyzsys 企业级后台管理系统 +**版本**: v1.0.0 +**更新**: 2025-01-19 +**团队**: Lyzsys 开发团队 diff --git a/pom.xml b/pom.xml index f567d0d..0ae3f05 100644 --- a/pom.xml +++ b/pom.xml @@ -8,12 +8,15 @@ ${revision} pom + lyzsys-dependencies + lyzsys-framework lyzsys-server lyzsys-module-system + lyzsys-module-infra @@ -29,8 +32,8 @@ ${project.artifactId} - 芋道项目基础脚手架 - https://github.com/YunaiV/ruoyi-vue-pro + 项目基础脚手架 + https://aaaaa.com 2025.12-jdk8-SNAPSHOT