From 7a43e9c38cf5267cd5844379d353d124d5381fb0 Mon Sep 17 00:00:00 2001 From: "Ray.Hao" <1490493387@qq.com> Date: Sat, 25 Apr 2026 16:29:32 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E5=B7=B2=E7=9F=A5=E9=97=AE=E9=A2=98?= =?UTF-8?q?=E4=BF=AE=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .editorconfig | 35 -- .gitattributes | 14 - README.md | 83 ++- docker/docker-compose.yml | 2 +- docs/images/qr/wechat-mp.jpg | Bin 0 -> 44188 bytes pom.xml | 2 +- sql/mysql/youlai_admin_template.sql | 524 ------------------ .../youlai_admin.sql => youlai-admin.sql} | 0 .../youlai/boot/YouLaiBootApplication.java | 2 + .../message/registry/SseSessionRegistry.java | 24 + src/main/resources/application-dev.yml | 1 + src/main/resources/application-prod.yml | 1 + 12 files changed, 83 insertions(+), 605 deletions(-) delete mode 100644 .editorconfig delete mode 100644 .gitattributes create mode 100644 docs/images/qr/wechat-mp.jpg delete mode 100644 sql/mysql/youlai_admin_template.sql rename sql/{mysql/youlai_admin.sql => youlai-admin.sql} (100%) diff --git a/.editorconfig b/.editorconfig deleted file mode 100644 index fd230fd6..00000000 --- a/.editorconfig +++ /dev/null @@ -1,35 +0,0 @@ -# EditorConfig is awesome: https://EditorConfig.org - -# top-most EditorConfig file -root = true - -# Unix-style newlines with a newline ending every file -[*] -charset = utf-8 -end_of_line = lf -insert_final_newline = true -trim_trailing_whitespace = true - -# Java files -[*.java] -indent_style = space -indent_size = 4 - -# XML files -[*.xml] -indent_style = space -indent_size = 4 - -# YAML files -[*.{yml,yaml}] -indent_style = space -indent_size = 2 - -# Properties files -[*.properties] -indent_style = space -indent_size = 4 - -# Markdown files -[*.md] -trim_trailing_whitespace = false diff --git a/.gitattributes b/.gitattributes deleted file mode 100644 index a3fd9cca..00000000 --- a/.gitattributes +++ /dev/null @@ -1,14 +0,0 @@ -# Auto detect text files and perform LF normalization -* text=auto eol=lf - -# Java files -*.java text eol=lf -*.xml text eol=lf - -# Config files -*.yml text eol=lf -*.yaml text eol=lf -*.properties text eol=lf - -# Shell scripts -*.sh text eol=lf diff --git a/README.md b/README.md index 5b140fb4..06fef97f 100644 --- a/README.md +++ b/README.md @@ -6,18 +6,23 @@ **Spring Boot 4 企业级权限管理系统后端** -[![Spring Boot](https://img.shields.io/badge/Spring%20Boot-4.0.1-6DB33F?logo=spring-boot)](https://spring.io/projects/spring-boot) +[![Spring Boot](https://img.shields.io/badge/Spring%20Boot-4.0.5-6DB33F?logo=spring-boot)](https://spring.io/projects/spring-boot) [![JDK](https://img.shields.io/badge/JDK-17%2B-007396?logo=openjdk)](https://openjdk.org/) [![License](https://img.shields.io/badge/License-Apache%202.0-blue?logo=apache)](LICENSE) - -[![文档](https://img.shields.io/badge/📖%20文档-youlai.tech-blue)](https://www.youlai.tech/docs/admin/backend/java/) -[![在线预览](https://img.shields.io/badge/🖥️%20在线预览-vue.youlai.tech-10B981)](https://vue.youlai.tech) [![Gitee Star](https://gitee.com/youlaiorg/youlai-boot/badge/star.svg)](https://gitee.com/youlaiorg/youlai-boot/stargazers) [![GitHub Star](https://img.shields.io/github/stars/youlaitech/youlai-boot?style=social)](https://github.com/youlaitech/youlai-boot) [![GitCode Star](https://gitcode.com/youlai/youlai-boot/star/badge.svg)](https://gitcode.com/youlai/youlai-boot/stargazers) +![](https://foruda.gitee.com/images/1708618984641188532/a7cca095_716974.png "rainbow.png") + +
+ +[🖥️ 在线预览](https://vue.youlai.tech) | [📲 移动端预览](https://app.youlai.tech) | [📖 文档](https://www.youlai.tech/docs/admin/backend/java/) + +
+ ## 简介 **youlai-boot** 是一套基于 Spring Boot 4 的企业级权限管理系统后端,配套前端 [vue3-element-admin](https://gitee.com/youlaiorg/vue3-element-admin) 和移动端 [youlai-app](https://gitee.com/youlaiorg/youlai-app),并提供 **6 种语言实现**(Java / Node.js / Go / Python / PHP / C#),共享同一套 API 规范与数据库结构。适用于企业中后台管理系统的学习参考与二次开发。 @@ -72,13 +77,13 @@ **环境要求**:JDK 17+ · MySQL 8.0+ · Redis 6.0+ 1. 克隆项目:`git clone https://gitee.com/youlaiorg/youlai-boot.git` -2. 导入数据库:`sql/mysql/youlai_admin.sql` +2. 导入数据库:`sql/youlai-admin.sql` 3. 修改配置(可选,默认已配置线上只读数据源):`src/main/resources/application-dev.yml` 4. 启动服务,访问 http://localhost:8000/doc.html 默认账号:`admin` / `123456` -**Docker 部署**:`cd docker && docker-compose up -d` +**Docker 部署**:`cd deploy/docker`,然后 `docker-compose up -d` 详细指南:[部署文档](https://www.youlai.tech/docs/admin/backends/java/deploy) · [开发规范](https://www.youlai.tech/docs/admin/backends/java/dev-standards) @@ -86,7 +91,7 @@ | 技术 | 版本 | 说明 | |:-----|:-----|:-----| -| Spring Boot | 4.0.1 | 核心框架 | +| Spring Boot | 4.0.5 | 核心框架 | | Spring Security | 6.x | 认证授权 | | MyBatis-Plus | 3.5.15 | ORM 框架 | | Druid | 1.2.24 | 数据库连接池 | @@ -101,7 +106,9 @@ ``` youlai-boot/ -├── docker/ # Docker 部署编排 +├── deploy/ +│ └── docker/ # Docker 部署编排 +├── docs/ # 项目文档与图片资源 ├── sql/ # 数据库初始化脚本 ├── src/main/java/com/youlai/boot/ │ ├── YouLaiBootApplication.java # 启动类 @@ -125,18 +132,25 @@ youlai-boot/ ## 生态矩阵 -| 项目 | 技术栈 | 定位 | -|:-----|:-------|:-----| -| [**vue3-element-admin**](https://gitee.com/youlaiorg/vue3-element-admin) | Vue 3 + Element Plus | **PC 管理前端**(主推) | -| [**youlai-app**](https://gitee.com/youlaiorg/youlai-app) | Vue 3 + UniApp | **移动端 App** | -| [**youlai-boot-tenant**](https://gitee.com/youlaiorg/youlai-boot-tenant) | Spring Boot 4 | **SaaS 多租户版本** | -| [**youlai-boot-flex**](https://gitee.com/youlaiorg/youlai-boot-flex) | Spring Boot 3 + MyBatis-Flex | MyBatis-Flex 版 | -| [**youlai-nest**](https://gitee.com/youlaiorg/youlai-nest) | NestJS + TypeORM | **Node.js 后端** | -| [**youlai-gin**](https://gitee.com/youlaiorg/youlai-gin) | Go + Gorm | **Go 后端** | -| [**youlai-django**](https://gitee.com/youlaiorg/youlai-django) | Django + DRF | **Python 后端** | -| [**youlai-thinkphp**](https://gitee.com/youlaiorg/youlai-thinkphp) | ThinkPHP 8 | **PHP 后端** | -| [**youlai-aspnet**](https://gitee.com/youlaiorg/youlai-aspnet) | ASP.NET Core | **C# 后端** | +**前端** +| 项目 | 技术栈 | 说明 | +|:-----|:-------|:-----| +| [vue3-element-admin](https://gitee.com/youlaiorg/vue3-element-admin) | Vue 3 + Element Plus | PC 管理前端(主推) | +| [youlai-app](https://gitee.com/youlaiorg/youlai-app) | Vue 3 + UniApp | 移动端 App | + +**后端** + +| 项目 | 技术栈 | 说明 | +|:-----|:-------|:-----| +| [youlai-nest](https://gitee.com/youlaiorg/youlai-nest) | NestJS + TypeORM | Node.js | +| [youlai-gin](https://gitee.com/youlaiorg/youlai-gin) | Go + Gorm | Go | +| [youlai-django](https://gitee.com/youlaiorg/youlai-django) | Django + DRF | Python | +| [youlai-thinkphp](https://gitee.com/youlaiorg/youlai-thinkphp) | ThinkPHP 8 | PHP | +| [youlai-aspnet](https://gitee.com/youlaiorg/youlai-aspnet) | ASP.NET Core | C# | + +> **youlai-boot** 还提供以下变种和分支版本:[多租户](https://gitee.com/youlaiorg/youlai-boot-tenant)(Spring Boot 4)· [MyBatis-Flex](https://gitee.com/youlaiorg/youlai-boot-flex)(Spring Boot 4)· [Spring Boot 3](https://gitee.com/youlaiorg/youlai-boot/tree/spring-boot-3) · [PostgreSQL](https://gitee.com/youlaiorg/youlai-boot/tree/db-pg) · [多模块](https://gitee.com/youlaiorg/youlai-boot/tree/multi-module) +> > 六种后端共享同一套 **RESTful API 规范** 和 **数据库结构**,前端可无缝切换。 ## 文档资源 @@ -146,7 +160,7 @@ youlai-boot/ | 📖 完整文档站 | [www.youlai.tech/docs/admin](https://www.youlai.tech/docs/admin/) | | 🖥️ PC 端在线预览 | [vue.youlai.tech](https://vue.youlai.tech) | | 📱 移动端在线预览 | [app.youlai.tech](https://app.youlai.tech) | -| 🔗 Apifox 接口文档 | [apifox.com](https://apifox.com/apidoc/shared-xxx) | +| 🔗 Apifox 接口文档 | [apifox.com](https://www.apifox.cn/apidoc/shared-195e783f-4d85-4235-a038-eec696de4ea5) | | 🔗 本地接口文档 | [localhost:8000/doc.html](http://localhost:8000/doc.html) | ## 参与贡献 @@ -161,14 +175,23 @@ youlai-boot/ --- -

- 有来技术公众号 -      - 个人微信 -

-

- 公众号「有来技术」 -              - 添加作者微信 -

+ + + + + + + + +
+ 公众号「有来技术」
+ 公众号「有来技术」 +
     + 小程序「有来技术」
+ 小程序「有来技术」 +
     + 添加作者微信
+ 添加作者微信 +
+

技术交流 · 问题反馈 · 商务合作

diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml index 2144edd7..4e7c2841 100644 --- a/docker/docker-compose.yml +++ b/docker/docker-compose.yml @@ -15,7 +15,7 @@ services: volumes: - ./mysql/conf/my.cnf:/etc/my.cnf # 挂载 my.cnf 文件到容器的指定路径 - ./mysql/data:/var/lib/mysql # 持久化 MySQL 数据 - - ../sql/mysql:/docker-entrypoint-initdb.d # 初始化 SQL 脚本目录 + - ../sql:/docker-entrypoint-initdb.d # 初始化 SQL 脚本目录 ports: - 3306:3306 networks: diff --git a/docs/images/qr/wechat-mp.jpg b/docs/images/qr/wechat-mp.jpg new file mode 100644 index 0000000000000000000000000000000000000000..8c06ee372f27bf5961aa929c83e5a84970d6a1bf GIT binary patch literal 44188 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 literal 0 HcmV?d00001 diff --git a/pom.xml b/pom.xml index 7a6fd2fc..6bbc8410 100644 --- a/pom.xml +++ b/pom.xml @@ -12,7 +12,7 @@ org.springframework.boot spring-boot-starter-parent - 4.0.1 + 4.0.5 diff --git a/sql/mysql/youlai_admin_template.sql b/sql/mysql/youlai_admin_template.sql deleted file mode 100644 index 48db9455..00000000 --- a/sql/mysql/youlai_admin_template.sql +++ /dev/null @@ -1,524 +0,0 @@ -# YouLai_Admin 数据库(MySQL 5.7 ~ MySQL 8.x) -# Copyright (c) 2021-present, youlai.tech - - --- ---------------------------- --- 1. 创建数据库 --- ---------------------------- -CREATE DATABASE IF NOT EXISTS youlai_admin_template CHARACTER SET utf8mb4 DEFAULT COLLATE utf8mb4_unicode_ci; - - --- ---------------------------- --- 2. 创建表 && 数据初始化 --- ---------------------------- -USE youlai_admin_template; - -SET NAMES utf8mb4; # 设置字符集 -SET FOREIGN_KEY_CHECKS = 0; # 关闭外键检查,加快导入速度 - --- ---------------------------- --- Table structure for sys_dept --- ---------------------------- -DROP TABLE IF EXISTS `sys_dept`; -CREATE TABLE `sys_dept` ( - `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键', - `name` varchar(100) NOT NULL COMMENT '部门名称', - `code` varchar(100) NOT NULL COMMENT '部门编号', - `parent_id` bigint DEFAULT 0 COMMENT '父节点id', - `tree_path` varchar(255) NOT NULL COMMENT '父节点id路径', - `sort` smallint DEFAULT 0 COMMENT '显示顺序', - `status` tinyint DEFAULT 1 COMMENT '状态(1-正常 0-禁用)', - `create_by` bigint NULL COMMENT '创建人ID', - `create_time` datetime NULL COMMENT '创建时间', - `update_by` bigint NULL COMMENT '修改人ID', - `update_time` datetime NULL COMMENT '更新时间', - `is_deleted` tinyint DEFAULT 0 COMMENT '逻辑删除标识(1-已删除 0-未删除)', - PRIMARY KEY (`id`) USING BTREE, - UNIQUE INDEX `uk_code`(`code` ASC) USING BTREE COMMENT '部门编号唯一索引' -) ENGINE = InnoDB CHARACTER SET = utf8mb4 COMMENT = '部门管理表'; - --- ---------------------------- --- Records of sys_dept --- ---------------------------- -INSERT INTO `sys_dept` VALUES (1, '有来技术', 'YOULAI', 0, '0', 1, 1, 1, NULL, 1, now(), 0); -INSERT INTO `sys_dept` VALUES (2, '研发部门', 'RD001', 1, '0,1', 1, 1, 2, NULL, 2, now(), 0); -INSERT INTO `sys_dept` VALUES (3, '测试部门', 'QA001', 1, '0,1', 1, 1, 2, NULL, 2, now(), 0); - --- ---------------------------- --- Table structure for sys_dict --- ---------------------------- -DROP TABLE IF EXISTS `sys_dict`; -CREATE TABLE `sys_dict` ( - `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键 ', - `dict_code` varchar(50) COMMENT '类型编码', - `name` varchar(50) COMMENT '类型名称', - `status` tinyint(1) DEFAULT '0' COMMENT '状态(0:正常;1:禁用)', - `remark` varchar(255) COMMENT '备注', - `create_time` datetime COMMENT '创建时间', - `create_by` bigint COMMENT '创建人ID', - `update_time` datetime COMMENT '更新时间', - `update_by` bigint COMMENT '修改人ID', - `is_deleted` tinyint DEFAULT '0' COMMENT '是否删除(1-删除,0-未删除)', - PRIMARY KEY (`id`) USING BTREE, - KEY `idx_dict_code` (`dict_code`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='数据字典类型表'; --- ---------------------------- --- Records of sys_dict --- ---------------------------- -INSERT INTO `sys_dict` VALUES (1, 'gender', '性别', 1, NULL, now() , 1,now(), 1,0); -INSERT INTO `sys_dict` VALUES (2, 'notice_type', '通知类型', 1, NULL, now(), 1,now(), 1,0); -INSERT INTO `sys_dict` VALUES (3, 'notice_level', '通知级别', 1, NULL, now(), 1,now(), 1,0); - - --- ---------------------------- --- Table structure for sys_dict_item --- ---------------------------- -DROP TABLE IF EXISTS `sys_dict_item`; -CREATE TABLE `sys_dict_item` ( - `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键', - `dict_code` varchar(50) COMMENT '关联字典编码,与sys_dict表中的dict_code对应', - `value` varchar(50) COMMENT '字典项值', - `label` varchar(100) COMMENT '字典项标签', - `tag_type` varchar(50) COMMENT '标签类型,用于前端样式展示(如success、warning等)', - `status` tinyint DEFAULT '0' COMMENT '状态(1-正常,0-禁用)', - `sort` int DEFAULT '0' COMMENT '排序', - `remark` varchar(255) COMMENT '备注', - `create_time` datetime COMMENT '创建时间', - `create_by` bigint COMMENT '创建人ID', - `update_time` datetime COMMENT '更新时间', - `update_by` bigint COMMENT '修改人ID', - PRIMARY KEY (`id`) USING BTREE -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='数据字典项表'; - --- ---------------------------- --- Records of sys_dict_item --- ---------------------------- -INSERT INTO `sys_dict_item` VALUES (1, 'gender', '1', '男', 'primary', 1, 1, NULL, now(), 1,now(),1); -INSERT INTO `sys_dict_item` VALUES (2, 'gender', '2', '女', 'danger', 1, 2, NULL, now(), 1,now(),1); -INSERT INTO `sys_dict_item` VALUES (3, 'gender', '0', '保密', 'info', 1, 3, NULL, now(), 1,now(),1); -INSERT INTO `sys_dict_item` VALUES (4, 'notice_type', '1', '系统升级', 'success', 1, 1, '', now(), 1,now(),1); -INSERT INTO `sys_dict_item` VALUES (5, 'notice_type', '2', '系统维护', 'primary', 1, 2, '', now(), 1,now(),1); -INSERT INTO `sys_dict_item` VALUES (6, 'notice_type', '3', '安全警告', 'danger', 1, 3, '', now(), 1,now(),1); -INSERT INTO `sys_dict_item` VALUES (7, 'notice_type', '4', '假期通知', 'success', 1, 4, '', now(), 1,now(),1); -INSERT INTO `sys_dict_item` VALUES (8, 'notice_type', '5', '公司新闻', 'primary', 1, 5, '', now(), 1,now(),1); -INSERT INTO `sys_dict_item` VALUES (9, 'notice_type', '99', '其他', 'info', 1, 99, '', now(), 1,now(),1); -INSERT INTO `sys_dict_item` VALUES (10, 'notice_level', 'L', '低', 'info', 1, 1, '', now(), 1,now(),1); -INSERT INTO `sys_dict_item` VALUES (11, 'notice_level', 'M', '中', 'warning', 1, 2, '', now(), 1,now(),1); -INSERT INTO `sys_dict_item` VALUES (12, 'notice_level', 'H', '高', 'danger', 1, 3, '', now(), 1,now(),1); - --- ---------------------------- --- Table structure for sys_menu --- ---------------------------- -DROP TABLE IF EXISTS `sys_menu`; -CREATE TABLE `sys_menu` ( - `id` bigint NOT NULL AUTO_INCREMENT COMMENT 'ID', - `parent_id` bigint NOT NULL COMMENT '父菜单ID', - `tree_path` varchar(255) COMMENT '父节点ID路径', - `name` varchar(64) NOT NULL COMMENT '菜单名称', - `type` char(1) NOT NULL COMMENT '菜单类型(C-目录 M-菜单 B-按钮)', - `route_name` varchar(255) COMMENT '路由名称(Vue Router 中用于命名路由)', - `route_path` varchar(128) COMMENT '路由路径(Vue Router 中定义的 URL 路径)', - `component` varchar(128) COMMENT '组件路径(组件页面完整路径,相对于 src/views/,缺省后缀 .vue)', - `perm` varchar(128) COMMENT '【按钮】权限标识', - `always_show` tinyint DEFAULT 0 COMMENT '【目录】只有一个子路由是否始终显示(1-是 0-否)', - `keep_alive` tinyint DEFAULT 0 COMMENT '【菜单】是否开启页面缓存(1-是 0-否)', - `visible` tinyint(1) DEFAULT 1 COMMENT '显示状态(1-显示 0-隐藏)', - `sort` int DEFAULT 0 COMMENT '排序', - `icon` varchar(64) COMMENT '菜单图标', - `redirect` varchar(128) COMMENT '跳转路径', - `create_time` datetime NULL COMMENT '创建时间', - `update_time` datetime NULL COMMENT '更新时间', - `params` varchar(255) NULL COMMENT '路由参数', - PRIMARY KEY (`id`) USING BTREE -) ENGINE = InnoDB CHARACTER SET = utf8mb4 COMMENT = '系统菜单表'; - --- ---------------------------- --- Records of sys_menu --- ---------------------------- --- 顶级目录:系统管理/代码生成/平台文档/接口文档 -INSERT INTO `sys_menu` VALUES (1, 0, '0', '系统管理', 'C', '', '/system', 'Layout', NULL, NULL, NULL, 1, 1, 'system', '/system/user', now(), now(), NULL); -INSERT INTO `sys_menu` VALUES (2, 0, '0', '代码生成', 'C', '', '/codegen', 'Layout', NULL, NULL, NULL, 1, 2, 'code', '/codegen/index', now(), now(), NULL); -INSERT INTO `sys_menu` VALUES (4, 0, '0', '平台文档', 'C', '', '/doc', 'Layout', NULL, NULL, NULL, 1, 4, 'document', '', now(), now(), NULL); -INSERT INTO `sys_menu` VALUES (5, 0, '0', '接口文档', 'C', '', '/api', 'Layout', NULL, NULL, NULL, 1, 5, 'api', '', now(), now(), NULL); - --- 系统管理 -INSERT INTO `sys_menu` VALUES (210, 1, '0,1', '用户管理', 'M', 'User', 'user', 'system/user/index', NULL, NULL, 1, 1, 1, 'el-icon-User', NULL, now(), now(), NULL); -INSERT INTO `sys_menu` VALUES (2101, 210, '0,1,210', '用户查询', 'B', NULL, '', NULL, 'sys:user:list', NULL, NULL, 1, 1, '', NULL, now(), now(), NULL); -INSERT INTO `sys_menu` VALUES (2102, 210, '0,1,210', '用户新增', 'B', NULL, '', NULL, 'sys:user:create', NULL, NULL, 1, 2, '', NULL, now(), now(), NULL); -INSERT INTO `sys_menu` VALUES (2103, 210, '0,1,210', '用户编辑', 'B', NULL, '', NULL, 'sys:user:update', NULL, NULL, 1, 3, '', NULL, now(), now(), NULL); -INSERT INTO `sys_menu` VALUES (2104, 210, '0,1,210', '用户删除', 'B', NULL, '', NULL, 'sys:user:delete', NULL, NULL, 1, 4, '', NULL, now(), now(), NULL); -INSERT INTO `sys_menu` VALUES (2105, 210, '0,1,210', '重置密码', 'B', NULL, '', NULL, 'sys:user:reset-password', NULL, NULL, 1, 5, '', NULL, now(), now(), NULL); -INSERT INTO `sys_menu` VALUES (2106, 210, '0,1,210', '用户导入', 'B', NULL, '', NULL, 'sys:user:import', NULL, NULL, 1, 6, '', NULL, now(), now(), NULL); -INSERT INTO `sys_menu` VALUES (2107, 210, '0,1,210', '用户导出', 'B', NULL, '', NULL, 'sys:user:export', NULL, NULL, 1, 7, '', NULL, now(), now(), NULL); - -INSERT INTO `sys_menu` VALUES (220, 1, '0,1', '角色管理', 'M', 'Role', 'role', 'system/role/index', NULL, NULL, 1, 1, 2, 'role', NULL, now(), now(), NULL); -INSERT INTO `sys_menu` VALUES (2201, 220, '0,1,220', '角色查询', 'B', NULL, '', NULL, 'sys:role:list', NULL, NULL, 1, 1, '', NULL, now(), now(), NULL); -INSERT INTO `sys_menu` VALUES (2202, 220, '0,1,220', '角色新增', 'B', NULL, '', NULL, 'sys:role:create', NULL, NULL, 1, 2, '', NULL, now(), now(), NULL); -INSERT INTO `sys_menu` VALUES (2203, 220, '0,1,220', '角色编辑', 'B', NULL, '', NULL, 'sys:role:update', NULL, NULL, 1, 3, '', NULL, now(), now(), NULL); -INSERT INTO `sys_menu` VALUES (2204, 220, '0,1,220', '角色删除', 'B', NULL, '', NULL, 'sys:role:delete', NULL, NULL, 1, 4, '', NULL, now(), now(), NULL); -INSERT INTO `sys_menu` VALUES (2205, 220, '0,1,220', '角色分配权限', 'B', NULL, '', NULL, 'sys:role:assign', NULL, NULL, 1, 5, '', NULL, now(), now(), NULL); - -INSERT INTO `sys_menu` VALUES (230, 1, '0,1', '菜单管理', 'M', 'SysMenu', 'menu', 'system/menu/index', NULL, NULL, 1, 1, 3, 'menu', NULL, now(), now(), NULL); -INSERT INTO `sys_menu` VALUES (2301, 230, '0,1,230', '菜单查询', 'B', NULL, '', NULL, 'sys:menu:list', NULL, NULL, 1, 1, '', NULL, now(), now(), NULL); -INSERT INTO `sys_menu` VALUES (2302, 230, '0,1,230', '菜单新增', 'B', NULL, '', NULL, 'sys:menu:create', NULL, NULL, 1, 2, '', NULL, now(), now(), NULL); -INSERT INTO `sys_menu` VALUES (2303, 230, '0,1,230', '菜单编辑', 'B', NULL, '', NULL, 'sys:menu:update', NULL, NULL, 1, 3, '', NULL, now(), now(), NULL); -INSERT INTO `sys_menu` VALUES (2304, 230, '0,1,230', '菜单删除', 'B', NULL, '', NULL, 'sys:menu:delete', NULL, NULL, 1, 4, '', NULL, now(), now(), NULL); - -INSERT INTO `sys_menu` VALUES (240, 1, '0,1', '部门管理', 'M', 'Dept', 'dept', 'system/dept/index', NULL, NULL, 1, 1, 4, 'tree', NULL, now(), now(), NULL); -INSERT INTO `sys_menu` VALUES (2401, 240, '0,1,240', '部门查询', 'B', NULL, '', NULL, 'sys:dept:list', NULL, NULL, 1, 1, '', NULL, now(), now(), NULL); -INSERT INTO `sys_menu` VALUES (2402, 240, '0,1,240', '部门新增', 'B', NULL, '', NULL, 'sys:dept:create', NULL, NULL, 1, 2, '', NULL, now(), now(), NULL); -INSERT INTO `sys_menu` VALUES (2403, 240, '0,1,240', '部门编辑', 'B', NULL, '', NULL, 'sys:dept:update', NULL, NULL, 1, 3, '', NULL, now(), now(), NULL); -INSERT INTO `sys_menu` VALUES (2404, 240, '0,1,240', '部门删除', 'B', NULL, '', NULL, 'sys:dept:delete', NULL, NULL, 1, 4, '', NULL, now(), now(), NULL); - -INSERT INTO `sys_menu` VALUES (250, 1, '0,1', '字典管理', 'M', 'Dict', 'dict', 'system/dict/index', NULL, NULL, 1, 1, 5, 'dict', NULL, now(), now(), NULL); -INSERT INTO `sys_menu` VALUES (2501, 250, '0,1,250', '字典查询', 'B', NULL, '', NULL, 'sys:dict:list', NULL, NULL, 1, 1, '', NULL, now(), now(), NULL); -INSERT INTO `sys_menu` VALUES (2502, 250, '0,1,250', '字典新增', 'B', NULL, '', NULL, 'sys:dict:create', NULL, NULL, 1, 2, '', NULL, now(), now(), NULL); -INSERT INTO `sys_menu` VALUES (2503, 250, '0,1,250', '字典编辑', 'B', NULL, '', NULL, 'sys:dict:update', NULL, NULL, 1, 3, '', NULL, now(), now(), NULL); -INSERT INTO `sys_menu` VALUES (2504, 250, '0,1,250', '字典删除', 'B', NULL, '', NULL, 'sys:dict:delete', NULL, NULL, 1, 4, '', NULL, now(), now(), NULL); - -INSERT INTO `sys_menu` VALUES (251, 1, '0,1', '字典项', 'M', 'DictItem', 'dict-item', 'system/dict/dict-item', NULL, 0, 1, 0, 6, '', NULL, now(), now(), NULL); -INSERT INTO `sys_menu` VALUES (2511, 251, '0,1,251', '字典项查询', 'B', NULL, '', NULL, 'sys:dict-item:list', NULL, NULL, 1, 1, '', NULL, now(), now(), NULL); -INSERT INTO `sys_menu` VALUES (2512, 251, '0,1,251', '字典项新增', 'B', NULL, '', NULL, 'sys:dict-item:create', NULL, NULL, 1, 2, '', NULL, now(), now(), NULL); -INSERT INTO `sys_menu` VALUES (2513, 251, '0,1,251', '字典项编辑', 'B', NULL, '', NULL, 'sys:dict-item:update', NULL, NULL, 1, 3, '', NULL, now(), now(), NULL); -INSERT INTO `sys_menu` VALUES (2514, 251, '0,1,251', '字典项删除', 'B', NULL, '', NULL, 'sys:dict-item:delete', NULL, NULL, 1, 4, '', NULL, now(), now(), NULL); - -INSERT INTO `sys_menu` VALUES (260, 1, '0,1', '系统日志', 'M', 'Log', 'log', 'system/log/index', NULL, 0, 1, 1, 7, 'document', NULL, now(), now(), NULL); - -INSERT INTO `sys_menu` VALUES (270, 1, '0,1', '系统配置', 'M', 'Config', 'config', 'system/config/index', NULL, 0, 1, 1, 8, 'setting', NULL, now(), now(), NULL); -INSERT INTO `sys_menu` VALUES (2701, 270, '0,1,270', '系统配置查询', 'B', NULL, '', NULL, 'sys:config:list', 0, 1, 1, 1, '', NULL, now(), now(), NULL); -INSERT INTO `sys_menu` VALUES (2702, 270, '0,1,270', '系统配置新增', 'B', NULL, '', NULL, 'sys:config:create', 0, 1, 1, 2, '', NULL, now(), now(), NULL); -INSERT INTO `sys_menu` VALUES (2703, 270, '0,1,270', '系统配置修改', 'B', NULL, '', NULL, 'sys:config:update', 0, 1, 1, 3, '', NULL, now(), now(), NULL); -INSERT INTO `sys_menu` VALUES (2704, 270, '0,1,270', '系统配置删除', 'B', NULL, '', NULL, 'sys:config:delete', 0, 1, 1, 4, '', NULL, now(), now(), NULL); -INSERT INTO `sys_menu` VALUES (2705, 270, '0,1,270', '系统配置刷新', 'B', NULL, '', NULL, 'sys:config:refresh', 0, 1, 1, 5, '', NULL, now(), now(), NULL); - -INSERT INTO `sys_menu` VALUES (280, 1, '0,1', '通知公告', 'M', 'Notice', 'notice', 'system/notice/index', NULL, NULL, NULL, 1, 9, '', NULL, now(), now(), NULL); -INSERT INTO `sys_menu` VALUES (2801, 280, '0,1,280', '通知查询', 'B', NULL, '', NULL, 'sys:notice:list', NULL, NULL, 1, 1, '', NULL, now(), now(), NULL); -INSERT INTO `sys_menu` VALUES (2802, 280, '0,1,280', '通知新增', 'B', NULL, '', NULL, 'sys:notice:create', NULL, NULL, 1, 2, '', NULL, now(), now(), NULL); -INSERT INTO `sys_menu` VALUES (2803, 280, '0,1,280', '通知编辑', 'B', NULL, '', NULL, 'sys:notice:update', NULL, NULL, 1, 3, '', NULL, now(), now(), NULL); -INSERT INTO `sys_menu` VALUES (2804, 280, '0,1,280', '通知删除', 'B', NULL, '', NULL, 'sys:notice:delete', NULL, NULL, 1, 4, '', NULL, now(), now(), NULL); -INSERT INTO `sys_menu` VALUES (2805, 280, '0,1,280', '通知发布', 'B', NULL, '', NULL, 'sys:notice:publish', 0, 1, 1, 5, '', NULL, now(), now(), NULL); -INSERT INTO `sys_menu` VALUES (2806, 280, '0,1,280', '通知撤回', 'B', NULL, '', NULL, 'sys:notice:revoke', 0, 1, 1, 6, '', NULL, now(), now(), NULL); - --- 代码生成 -INSERT INTO `sys_menu` VALUES (310, 2, '0,2', '代码生成', 'M', 'Codegen', 'codegen', 'codegen/index', NULL, NULL, 1, 1, 1, 'code', NULL, now(), now(), NULL); - --- 平台文档(外链通过 route_path 识别) -INSERT INTO `sys_menu` VALUES (501, 4, '0,4', '平台文档(外链)', 'M', NULL, 'https://juejin.cn/post/7228990409909108793', '', NULL, NULL, NULL, 1, 1, 'document', '', now(), now(), NULL); -INSERT INTO `sys_menu` VALUES (502, 4, '0,4', '后端文档', 'M', NULL, 'https://youlai.blog.csdn.net/article/details/145178880', '', NULL, NULL, NULL, 1, 2, 'document', '', now(), now(), NULL); -INSERT INTO `sys_menu` VALUES (503, 4, '0,4', '移动端文档', 'M', NULL, 'https://youlai.blog.csdn.net/article/details/143222890', '', NULL, NULL, NULL, 1, 3, 'document', '', now(), now(), NULL); -INSERT INTO `sys_menu` VALUES (504, 4, '0,4', '内部文档', 'M', NULL, 'internal-doc', 'demo/internal-doc', NULL, NULL, NULL, 1, 4, 'document', '', now(), now(), NULL); - --- 接口文档 -INSERT INTO `sys_menu` VALUES (601, 5, '0,5', 'Apifox', 'M', 'Apifox', 'apifox', 'demo/api/apifox', NULL, NULL, 1, 1, 1, 'api', '', now(), now(), NULL); - --- ---------------------------- --- Table structure for sys_role --- ---------------------------- -DROP TABLE IF EXISTS `sys_role`; -CREATE TABLE `sys_role` ( - `id` bigint NOT NULL AUTO_INCREMENT, - `name` varchar(64) NOT NULL COMMENT '角色名称', - `code` varchar(32) NOT NULL COMMENT '角色编码', - `sort` int NULL COMMENT '显示顺序', - `status` tinyint(1) DEFAULT 1 COMMENT '角色状态(1-正常 0-停用)', - `data_scope` tinyint NULL COMMENT '数据权限(1-所有数据 2-部门及子部门数据 3-本部门数据 4-本人数据 5-自定义部门数据)', - `create_by` bigint NULL COMMENT '创建人 ID', - `create_time` datetime NULL COMMENT '创建时间', - `update_by` bigint NULL COMMENT '更新人ID', - `update_time` datetime NULL COMMENT '更新时间', - `is_deleted` tinyint(1) DEFAULT 0 COMMENT '逻辑删除标识(0-未删除 1-已删除)', - PRIMARY KEY (`id`) USING BTREE, - UNIQUE INDEX `uk_name`(`name` ASC) USING BTREE COMMENT '角色名称唯一索引', - UNIQUE INDEX `uk_code`(`code` ASC) USING BTREE COMMENT '角色编码唯一索引' -) ENGINE = InnoDB CHARACTER SET = utf8mb4 COMMENT = '系统角色表'; - --- ---------------------------- --- Records of sys_role --- ---------------------------- -INSERT INTO `sys_role` VALUES (1, '超级管理员', 'ROOT', 1, 1, 1, NULL, now(), NULL, now(), 0); -INSERT INTO `sys_role` VALUES (2, '系统管理员', 'ADMIN', 2, 1, 1, NULL, now(), NULL, NULL, 0); -INSERT INTO `sys_role` VALUES (3, '访问游客', 'GUEST', 3, 1, 3, NULL, now(), NULL, now(), 0); -INSERT INTO `sys_role` VALUES (4, '部门主管', 'DEPT_MANAGER', 4, 1, 2, NULL, now(), NULL, now(), 0); -INSERT INTO `sys_role` VALUES (5, '部门成员', 'DEPT_MEMBER', 5, 1, 3, NULL, now(), NULL, now(), 0); -INSERT INTO `sys_role` VALUES (6, '普通员工', 'EMPLOYEE', 6, 1, 4, NULL, now(), NULL, now(), 0); -INSERT INTO `sys_role` VALUES (7, '自定义权限用户', 'CUSTOM_USER', 7, 1, 5, NULL, now(), NULL, now(), 0); - --- ---------------------------- --- Table structure for sys_role_menu --- ---------------------------- -DROP TABLE IF EXISTS `sys_role_menu`; -CREATE TABLE `sys_role_menu` ( - `role_id` bigint NOT NULL COMMENT '角色ID', - `menu_id` bigint NOT NULL COMMENT '菜单ID', - UNIQUE INDEX `uk_roleid_menuid`(`role_id` ASC, `menu_id` ASC) USING BTREE COMMENT '角色菜单唯一索引' -) ENGINE = InnoDB CHARACTER SET = utf8mb4 COMMENT = '角色菜单关联表'; - --- ---------------------------- --- Table structure for sys_role_dept --- ---------------------------- -DROP TABLE IF EXISTS `sys_role_dept`; -CREATE TABLE `sys_role_dept` ( - `role_id` bigint NOT NULL COMMENT '角色ID', - `dept_id` bigint NOT NULL COMMENT '部门ID', - UNIQUE INDEX `uk_roleid_deptid`(`role_id` ASC, `dept_id` ASC) USING BTREE COMMENT '角色部门唯一索引' -) ENGINE = InnoDB CHARACTER SET = utf8mb4 COMMENT = '角色部门关联表'; - --- ---------------------------- --- Records of sys_role_dept --- ---------------------------- -INSERT IGNORE INTO `sys_role_dept` VALUES (7, 1); -INSERT IGNORE INTO `sys_role_dept` VALUES (7, 2); - --- ============================================ --- 系统管理员角色菜单权限(role_id=2) --- 顶级目录 -INSERT INTO `sys_role_menu` VALUES (2, 1), (2, 2), (2, 4), (2, 5); --- 系统管理 -INSERT INTO `sys_role_menu` VALUES (2, 210), (2, 2101), (2, 2102), (2, 2103), (2, 2104), (2, 2105), (2, 2106), (2, 2107); -INSERT INTO `sys_role_menu` VALUES (2, 220), (2, 2201), (2, 2202), (2, 2203), (2, 2204), (2, 2205); -INSERT INTO `sys_role_menu` VALUES (2, 230), (2, 2301), (2, 2302), (2, 2303), (2, 2304); -INSERT INTO `sys_role_menu` VALUES (2, 240), (2, 2401), (2, 2402), (2, 2403), (2, 2404); -INSERT INTO `sys_role_menu` VALUES (2, 250), (2, 2501), (2, 2502), (2, 2503), (2, 2504); -INSERT INTO `sys_role_menu` VALUES (2, 251), (2, 2511), (2, 2512), (2, 2513), (2, 2514); -INSERT INTO `sys_role_menu` VALUES (2, 260), (2, 2601); -INSERT INTO `sys_role_menu` VALUES (2, 270), (2, 2701), (2, 2702), (2, 2703), (2, 2704), (2, 2705); -INSERT INTO `sys_role_menu` VALUES (2, 280), (2, 2801), (2, 2802), (2, 2803), (2, 2804), (2, 2805), (2, 2806); - -INSERT IGNORE INTO `sys_role_menu` VALUES (4, 1); -INSERT IGNORE INTO `sys_role_menu` VALUES (4, 210), (4, 2101), (4, 2102), (4, 2103), (4, 2104), (4, 2105), (4, 2106), (4, 2107); -INSERT IGNORE INTO `sys_role_menu` VALUES (4, 220), (4, 2201), (4, 2202), (4, 2203), (4, 2204), (4, 2205); - -INSERT IGNORE INTO `sys_role_menu` VALUES (5, 1); -INSERT IGNORE INTO `sys_role_menu` VALUES (5, 210), (5, 2101), (5, 2102), (5, 2103), (5, 2104), (5, 2105), (5, 2106), (5, 2107); -INSERT IGNORE INTO `sys_role_menu` VALUES (5, 220), (5, 2201), (5, 2202), (5, 2203), (5, 2204), (5, 2205); - -INSERT IGNORE INTO `sys_role_menu` VALUES (6, 1); -INSERT IGNORE INTO `sys_role_menu` VALUES (6, 210), (6, 2101), (6, 2102), (6, 2103), (6, 2104), (6, 2105), (6, 2106), (6, 2107); -INSERT IGNORE INTO `sys_role_menu` VALUES (6, 220), (6, 2201), (6, 2202), (6, 2203), (6, 2204), (6, 2205); - -INSERT IGNORE INTO `sys_role_menu` VALUES (7, 1); -INSERT IGNORE INTO `sys_role_menu` VALUES (7, 210), (7, 2101), (7, 2102), (7, 2103), (7, 2104), (7, 2105), (7, 2106), (7, 2107); -INSERT IGNORE INTO `sys_role_menu` VALUES (7, 220), (7, 2201), (7, 2202), (7, 2203), (7, 2204), (7, 2205); --- 代码生成 -INSERT INTO `sys_role_menu` VALUES (2, 310); --- 平台文档 -INSERT INTO `sys_role_menu` VALUES (2, 501), (2, 502), (2, 503), (2, 504); --- 接口文档 -INSERT INTO `sys_role_menu` VALUES (2, 601); - --- ---------------------------- --- Table structure for sys_user --- ---------------------------- -DROP TABLE IF EXISTS `sys_user`; -CREATE TABLE `sys_user` ( - `id` bigint NOT NULL AUTO_INCREMENT, - `username` varchar(64) COMMENT '用户名', - `nickname` varchar(64) COMMENT '昵称', - `gender` tinyint(1) DEFAULT 1 COMMENT '性别((1-男 2-女 0-保密)', - `password` varchar(100) COMMENT '密码', - `dept_id` int COMMENT '部门ID', - `avatar` varchar(255) COMMENT '用户头像', - `mobile` varchar(20) COMMENT '联系方式', - `status` tinyint(1) DEFAULT 1 COMMENT '状态(1-正常 0-禁用)', - `email` varchar(128) COMMENT '用户邮箱', - `create_time` datetime COMMENT '创建时间', - `create_by` bigint COMMENT '创建人ID', - `update_time` datetime COMMENT '更新时间', - `update_by` bigint COMMENT '修改人ID', - `is_deleted` tinyint(1) DEFAULT 0 COMMENT '逻辑删除标识(0-未删除 1-已删除)', - PRIMARY KEY (`id`) USING BTREE -) ENGINE = InnoDB CHARACTER SET = utf8mb4 COMMENT = '系统用户表'; - --- ---------------------------- --- Records of sys_user --- ---------------------------- -INSERT INTO `sys_user` VALUES (1, 'root', '有来技术', 0, '$2a$10$xVWsNOhHrCxh5UbpCE7/HuJ.PAOKcYAqRxD2CO2nVnJS.IAXkr5aq', NULL, 'https://foruda.gitee.com/images/1723603502796844527/03cdca2a_716974.gif', '18812345677', 1, 'youlaitech@163.com', now(), NULL, now(), NULL, 0); -INSERT INTO `sys_user` VALUES (2, 'admin', '系统管理员', 1, '$2a$10$xVWsNOhHrCxh5UbpCE7/HuJ.PAOKcYAqRxD2CO2nVnJS.IAXkr5aq', 1, 'https://foruda.gitee.com/images/1723603502796844527/03cdca2a_716974.gif', '18888888888', 1, 'youlaitech@163.com', now(), NULL, now(), NULL, 0); -INSERT INTO `sys_user` VALUES (3, 'test', '测试小用户', 1, '$2a$10$xVWsNOhHrCxh5UbpCE7/HuJ.PAOKcYAqRxD2CO2nVnJS.IAXkr5aq', 3, 'https://foruda.gitee.com/images/1723603502796844527/03cdca2a_716974.gif', '18812345679', 1, 'youlaitech@163.com', now(), NULL, now(), NULL, 0); -INSERT INTO `sys_user` VALUES (4, 'dept_manager', '部门主管', 1, '$2a$10$xVWsNOhHrCxh5UbpCE7/HuJ.PAOKcYAqRxD2CO2nVnJS.IAXkr5aq', 1, 'https://foruda.gitee.com/images/1723603502796844527/03cdca2a_716974.gif', '18812345680', 1, 'manager@youlaitech.com', now(), NULL, now(), NULL, 0); -INSERT INTO `sys_user` VALUES (5, 'dept_member', '部门成员', 1, '$2a$10$xVWsNOhHrCxh5UbpCE7/HuJ.PAOKcYAqRxD2CO2nVnJS.IAXkr5aq', 1, 'https://foruda.gitee.com/images/1723603502796844527/03cdca2a_716974.gif', '18812345681', 1, 'member@youlaitech.com', now(), NULL, now(), NULL, 0); -INSERT INTO `sys_user` VALUES (6, 'employee', '普通员工', 1, '$2a$10$xVWsNOhHrCxh5UbpCE7/HuJ.PAOKcYAqRxD2CO2nVnJS.IAXkr5aq', 2, 'https://foruda.gitee.com/images/1723603502796844527/03cdca2a_716974.gif', '18812345682', 1, 'employee@youlaitech.com', now(), NULL, now(), NULL, 0); -INSERT INTO `sys_user` VALUES (7, 'custom_user', '自定义权限用户', 1, '$2a$10$xVWsNOhHrCxh5UbpCE7/HuJ.PAOKcYAqRxD2CO2nVnJS.IAXkr5aq', 3, 'https://foruda.gitee.com/images/1723603502796844527/03cdca2a_716974.gif', '18812345683', 1, 'custom@youlaitech.com', now(), NULL, now(), NULL, 0); - --- ---------------------------- --- Table structure for sys_user_role --- ---------------------------- -DROP TABLE IF EXISTS `sys_user_role`; -CREATE TABLE `sys_user_role` ( - `user_id` bigint NOT NULL COMMENT '用户ID', - `role_id` bigint NOT NULL COMMENT '角色ID', - PRIMARY KEY (`user_id`, `role_id`) USING BTREE -) ENGINE = InnoDB CHARACTER SET = utf8mb4 COMMENT = '用户角色关联表'; - --- ---------------------------- --- Records of sys_user_role --- ---------------------------- -INSERT INTO `sys_user_role` VALUES (1, 1); -INSERT INTO `sys_user_role` VALUES (2, 2); -INSERT INTO `sys_user_role` VALUES (3, 3); -INSERT IGNORE INTO `sys_user_role` VALUES (4, 4); -INSERT IGNORE INTO `sys_user_role` VALUES (5, 5); -INSERT IGNORE INTO `sys_user_role` VALUES (6, 6); -INSERT IGNORE INTO `sys_user_role` VALUES (7, 7); - --- ---------------------------- --- Table structure for sys_log --- ---------------------------- -DROP TABLE IF EXISTS `sys_log`; -CREATE TABLE `sys_log` ( - `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键', - `module` TINYINT NOT NULL COMMENT '模块,数字枚举,参考 LogModule 枚举', - `action_type` TINYINT NOT NULL COMMENT '操作类型,数字枚举,参考 ActionType 枚举', - `title` VARCHAR(100) NOT NULL COMMENT '前端显示标题', - `content` TEXT COMMENT '自定义日志内容', - `operator_id` BIGINT COMMENT '操作人ID', - `operator_name` VARCHAR(50) COMMENT '操作人名称', - `request_uri` VARCHAR(255) COMMENT '请求路径', - `request_method` VARCHAR(10) COMMENT '请求方法', - `ip` VARCHAR(45) COMMENT 'IP地址', - `province` VARCHAR(100) COMMENT '省份', - `city` VARCHAR(100) COMMENT '城市', - `device` VARCHAR(100) COMMENT '设备', - `os` VARCHAR(100) COMMENT '操作系统', - `browser` VARCHAR(100) COMMENT '浏览器', - `status` TINYINT DEFAULT 1 COMMENT '0失败 1成功', - `error_msg` VARCHAR(255) COMMENT '错误信息', - `execution_time` INT COMMENT '执行时间(ms)', - `create_time` DATETIME COMMENT '操作时间', - PRIMARY KEY (`id`) USING BTREE, - KEY `idx_module_action_time` (`module`, `action_type`, `create_time`), - KEY `idx_operator_time` (`operator_id`, `create_time`), - KEY `idx_time` (`create_time`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='系统操作日志表'; - --- ---------------------------- --- Table structure for gen_table --- ---------------------------- -DROP TABLE IF EXISTS `gen_table`; -CREATE TABLE `gen_table` ( - `id` bigint NOT NULL AUTO_INCREMENT, - `table_name` varchar(100) NOT NULL COMMENT '表名', - `module_name` varchar(100) COMMENT '模块名', - `package_name` varchar(255) NOT NULL COMMENT '包名', - `business_name` varchar(100) NOT NULL COMMENT '业务名', - `entity_name` varchar(100) NOT NULL COMMENT '实体类名', - `author` varchar(50) NOT NULL COMMENT '作者', - `parent_menu_id` bigint COMMENT '上级菜单ID,对应sys_menu的id ', - `remove_table_prefix` varchar(20) COMMENT '要移除的表前缀,如: sys_', - `page_type` varchar(20) COMMENT '页面类型(classic|curd)', - `create_time` datetime COMMENT '创建时间', - `update_time` datetime COMMENT '更新时间', - `is_deleted` tinyint(4) DEFAULT 0 COMMENT '是否删除', - PRIMARY KEY (`id`), - UNIQUE KEY `uk_tablename` (`table_name`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='代码生成配置表'; - --- ---------------------------- --- Table structure for gen_table_column --- ---------------------------- -DROP TABLE IF EXISTS `gen_table_column`; -CREATE TABLE `gen_table_column` ( - `id` bigint NOT NULL AUTO_INCREMENT, - `table_id` bigint NOT NULL COMMENT '关联的表配置ID', - `column_name` varchar(100) , - `column_type` varchar(50) , - `column_length` int , - `field_name` varchar(100) NOT NULL COMMENT '字段名称', - `field_type` varchar(100) COMMENT '字段类型', - `field_sort` int COMMENT '字段排序', - `field_comment` varchar(255) COMMENT '字段描述', - `max_length` int , - `is_required` tinyint(1) COMMENT '是否必填', - `is_show_in_list` tinyint(1) DEFAULT '0' COMMENT '是否在列表显示', - `is_show_in_form` tinyint(1) DEFAULT '0' COMMENT '是否在表单显示', - `is_show_in_query` tinyint(1) DEFAULT '0' COMMENT '是否在查询条件显示', - `query_type` tinyint COMMENT '查询方式', - `form_type` tinyint COMMENT '表单类型', - `dict_type` varchar(50) COMMENT '字典类型', - `create_time` datetime COMMENT '创建时间', - `update_time` datetime COMMENT '更新时间', - PRIMARY KEY (`id`), - KEY `idx_table_id` (`table_id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='代码生成字段配置表'; - --- ---------------------------- --- 系统配置表 --- ---------------------------- -DROP TABLE IF EXISTS `sys_config`; -CREATE TABLE `sys_config` ( - `id` bigint NOT NULL AUTO_INCREMENT, - `config_name` varchar(50) NOT NULL COMMENT '配置名称', - `config_key` varchar(50) NOT NULL COMMENT '配置key', - `config_value` varchar(100) NOT NULL COMMENT '配置值', - `remark` varchar(255) COMMENT '备注', - `create_time` datetime COMMENT '创建时间', - `create_by` bigint COMMENT '创建人ID', - `update_time` datetime COMMENT '更新时间', - `update_by` bigint COMMENT '更新人ID', - `is_deleted` tinyint(4) DEFAULT '0' NOT NULL COMMENT '逻辑删除标识(0-未删除 1-已删除)', - PRIMARY KEY (`id`) -) ENGINE=InnoDB COMMENT='系统配置表'; - -INSERT INTO `sys_config` VALUES (1, '系统限流QPS', 'IP_QPS_THRESHOLD_LIMIT', '10', '单个IP请求的最大每秒查询数(QPS)阈值Key', now(), 1, NULL, NULL, 0); - --- ---------------------------- --- 通知公告表 --- ---------------------------- -DROP TABLE IF EXISTS `sys_notice`; -CREATE TABLE `sys_notice` ( - `id` bigint NOT NULL AUTO_INCREMENT, - `title` varchar(50) COMMENT '通知标题', - `content` text COMMENT '通知内容', - `type` tinyint NOT NULL COMMENT '通知类型(关联字典编码:notice_type)', - `level` varchar(5) NOT NULL COMMENT '通知等级(字典code:notice_level)', - `target_type` tinyint NOT NULL COMMENT '目标类型(1: 全体, 2: 指定)', - `target_user_ids` varchar(255) COMMENT '目标人ID集合(多个使用英文逗号,分割)', - `publisher_id` bigint COMMENT '发布人ID', - `publish_status` tinyint DEFAULT '0' COMMENT '发布状态(0: 未发布, 1: 已发布, -1: 已撤回)', - `publish_time` datetime COMMENT '发布时间', - `revoke_time` datetime COMMENT '撤回时间', - `create_by` bigint NOT NULL COMMENT '创建人ID', - `create_time` datetime NOT NULL COMMENT '创建时间', - `update_by` bigint COMMENT '更新人ID', - `update_time` datetime COMMENT '更新时间', - `is_deleted` tinyint(1) DEFAULT '0' COMMENT '是否删除(0: 未删除, 1: 已删除)', - PRIMARY KEY (`id`) USING BTREE -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='系统通知公告表'; - -INSERT INTO `sys_notice` VALUES (1, 'v3.0.0 版本发布 - 多租户功能上线', '

🎉 新版本发布,主要更新内容:

1. 新增多租户功能,支持租户隔离和数据管理

2. 优化系统性能,提升响应速度

3. 完善权限管理,增强安全性

4. 修复已知问题,提升系统稳定性

', 1, 'H', 1, NULL, 1, 1, '2024-12-15 10:00:00', NULL, 1, '2024-12-15 10:00:00', 1, '2024-12-15 10:00:00', 0); -INSERT INTO `sys_notice` VALUES (2, '系统维护通知 - 2024年12月20日', '

⏰ 系统维护通知

系统将于 2024年12月20日(本周五)凌晨 2:00-4:00 进行例行维护升级。

维护期间系统将暂停服务,请提前做好数据备份工作。

给您带来的不便,敬请谅解!

', 2, 'H', 1, NULL, 1, 1, '2024-12-18 14:30:00', NULL, 1, '2024-12-18 14:30:00', 1, '2024-12-18 14:30:00', 0); -INSERT INTO `sys_notice` VALUES (3, '安全提醒 - 防范钓鱼邮件', '

⚠️ 安全提醒

近期发现有不法分子通过钓鱼邮件进行网络攻击,请大家提高警惕:

1. 不要点击来源不明的邮件链接

2. 不要下载可疑附件

3. 遇到可疑邮件请及时联系IT部门

4. 定期修改密码,使用强密码策略

', 3, 'H', 1, NULL, 1, 1, '2024-12-10 09:00:00', NULL, 1, '2024-12-10 09:00:00', 1, '2024-12-10 09:00:00', 0); -INSERT INTO `sys_notice` VALUES (4, '元旦假期安排通知', '

📅 元旦假期安排

根据国家法定节假日安排,公司元旦假期时间为:

2024年12月30日(周一)至 2025年1月1日(周三),共3天。

2024年12月29日(周日)正常上班。

祝大家元旦快乐,假期愉快!

', 4, 'M', 1, NULL, 1, 1, '2024-12-25 16:00:00', NULL, 1, '2024-12-25 16:00:00', 1, '2024-12-25 16:00:00', 0); -INSERT INTO `sys_notice` VALUES (5, '新产品发布会邀请', '

🎊 新产品发布会邀请

公司将于 2025年1月15日下午14:00 在总部会议室举办新产品发布会。

届时将展示最新研发的产品和技术成果,欢迎全体员工参加。

请各部门提前安排好工作,准时参加。

', 5, 'M', 1, NULL, 1, 1, '2024-12-28 11:00:00', NULL, 1, '2024-12-28 11:00:00', 1, '2024-12-28 11:00:00', 0); -INSERT INTO `sys_notice` VALUES (6, 'v2.16.1 版本更新', '

✨ 版本更新

v2.16.1 版本已发布,主要修复内容:

1. 修复 WebSocket 重复连接导致的后台线程阻塞问题

2. 优化通知公告功能,提升用户体验

3. 修复部分已知bug

建议尽快更新到最新版本。

', 1, 'M', 1, NULL, 1, 1, '2024-12-05 15:30:00', NULL, 1, '2024-12-05 15:30:00', 1, '2024-12-05 15:30:00', 0); -INSERT INTO `sys_notice` VALUES (7, '年终总结会议通知', '

📋 年终总结会议通知

各部门年终总结会议将于 2024年12月30日上午9:00 召开。

请各部门负责人提前准备好年度工作总结和下年度工作计划。

会议地点:总部大会议室

', 5, 'M', 2, '1,2', 1, 1, '2024-12-22 10:00:00', NULL, 1, '2024-12-22 10:00:00', 1, '2024-12-22 10:00:00', 0); -INSERT INTO `sys_notice` VALUES (8, '系统功能优化完成', '

✅ 系统功能优化

已完成以下功能优化:

1. 优化用户管理界面,提升操作体验

2. 增强数据导出功能,支持更多格式

3. 优化搜索功能,提升查询效率

4. 修复部分界面显示问题

', 1, 'L', 1, NULL, 1, 1, '2024-12-12 14:20:00', NULL, 1, '2024-12-12 14:20:00', 1, '2024-12-12 14:20:00', 0); -INSERT INTO `sys_notice` VALUES (9, '员工培训计划', '

📚 员工培训计划

为提升员工专业技能,公司将于 2025年1月8日-10日 组织技术培训。

培训内容:

1. 新技术框架应用

2. 代码规范与最佳实践

3. 系统架构设计

请各部门合理安排工作,确保培训顺利进行。

', 5, 'M', 1, NULL, 1, 1, '2024-12-20 09:30:00', NULL, 1, '2024-12-20 09:30:00', 1, '2024-12-20 09:30:00', 0); -INSERT INTO `sys_notice` VALUES (10, '数据备份提醒', '

💾 数据备份提醒

请各部门注意定期备份重要数据,建议每周至少备份一次。

备份方式:

1. 使用系统自带备份功能

2. 手动导出重要数据

3. 联系IT部门协助备份

数据安全,人人有责!

', 3, 'L', 1, NULL, 1, 1, '2024-12-08 08:00:00', NULL, 1, '2024-12-08 08:00:00', 1, '2024-12-08 08:00:00', 0); - --- ---------------------------- --- 用户通知公告表 --- ---------------------------- -DROP TABLE IF EXISTS `sys_user_notice`; -CREATE TABLE `sys_user_notice` ( - `id` bigint NOT NULL AUTO_INCREMENT COMMENT 'id', - `notice_id` bigint NOT NULL COMMENT '公共通知id', - `user_id` bigint NOT NULL COMMENT '用户id', - `is_read` bigint DEFAULT '0' COMMENT '读取状态(0: 未读, 1: 已读)', - `read_time` datetime COMMENT '阅读时间', - `create_time` datetime NOT NULL COMMENT '创建时间', - `update_time` datetime COMMENT '更新时间', - `is_deleted` tinyint DEFAULT '0' COMMENT '逻辑删除(0: 未删除, 1: 已删除)', - PRIMARY KEY (`id`) USING BTREE -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户通知公告关联表'; - -INSERT INTO `sys_user_notice` VALUES (1, 1, 2, 1, NULL, now(), now(), 0); -INSERT INTO `sys_user_notice` VALUES (2, 2, 2, 1, NULL, now(), now(), 0); -INSERT INTO `sys_user_notice` VALUES (3, 3, 2, 1, NULL, now(), now(), 0); -INSERT INTO `sys_user_notice` VALUES (4, 4, 2, 1, NULL, now(), now(), 0); -INSERT INTO `sys_user_notice` VALUES (5, 5, 2, 1, NULL, now(), now(), 0); -INSERT INTO `sys_user_notice` VALUES (6, 6, 2, 1, NULL, now(), now(), 0); -INSERT INTO `sys_user_notice` VALUES (7, 7, 2, 1, NULL, now(), now(), 0); -INSERT INTO `sys_user_notice` VALUES (8, 8, 2, 1, NULL, now(), now(), 0); -INSERT INTO `sys_user_notice` VALUES (9, 9, 2, 1, NULL, now(), now(), 0); -INSERT INTO `sys_user_notice` VALUES (10, 10, 2, 1, NULL, now(), now(), 0); diff --git a/sql/mysql/youlai_admin.sql b/sql/youlai-admin.sql similarity index 100% rename from sql/mysql/youlai_admin.sql rename to sql/youlai-admin.sql diff --git a/src/main/java/com/youlai/boot/YouLaiBootApplication.java b/src/main/java/com/youlai/boot/YouLaiBootApplication.java index 6c44e203..a40fcaaa 100644 --- a/src/main/java/com/youlai/boot/YouLaiBootApplication.java +++ b/src/main/java/com/youlai/boot/YouLaiBootApplication.java @@ -2,6 +2,7 @@ package com.youlai.boot; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.scheduling.annotation.EnableScheduling; /** * 应用启动类 @@ -9,6 +10,7 @@ import org.springframework.boot.autoconfigure.SpringBootApplication; * @author Ray.Hao * @since 0.0.1 */ +@EnableScheduling @SpringBootApplication public class YouLaiBootApplication { diff --git a/src/main/java/com/youlai/boot/message/registry/SseSessionRegistry.java b/src/main/java/com/youlai/boot/message/registry/SseSessionRegistry.java index 502ec3a4..f6923b41 100644 --- a/src/main/java/com/youlai/boot/message/registry/SseSessionRegistry.java +++ b/src/main/java/com/youlai/boot/message/registry/SseSessionRegistry.java @@ -6,10 +6,12 @@ import org.springframework.context.event.ContextClosedEvent; import org.springframework.context.event.EventListener; import org.springframework.core.Ordered; import org.springframework.core.annotation.Order; +import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; import org.springframework.web.servlet.mvc.method.annotation.SseEmitter; import java.io.IOException; +import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Set; @@ -198,6 +200,28 @@ public class SseSessionRegistry { } } + /** + * 心跳检测:每30秒向所有连接发送ping事件,及时清理已断开的僵尸连接 + */ + @Scheduled(fixedRate = 30000) + public void heartbeat() { + if (emitterUserMap.isEmpty()) { + return; + } + List failedEmitters = new ArrayList<>(); + for (SseEmitter emitter : emitterUserMap.keySet()) { + try { + emitter.send(SseEmitter.event().name("ping").data("heartbeat")); + } catch (Exception e) { + failedEmitters.add(emitter); + } + } + if (!failedEmitters.isEmpty()) { + log.debug("心跳检测清理{}个失效SSE连接", failedEmitters.size()); + failedEmitters.forEach(this::removeEmitter); + } + } + /** * 容器关闭时主动断开所有 SSE 连接,避免阻塞应用停止 */ diff --git a/src/main/resources/application-dev.yml b/src/main/resources/application-dev.yml index a8ddba0c..f4e55e74 100644 --- a/src/main/resources/application-dev.yml +++ b/src/main/resources/application-dev.yml @@ -94,6 +94,7 @@ security: - /v3/api-docs/** - /webjars/** - /favicon.ico + - /error # 文件存储配置 oss: diff --git a/src/main/resources/application-prod.yml b/src/main/resources/application-prod.yml index d3d3fa06..d1bc7ff1 100644 --- a/src/main/resources/application-prod.yml +++ b/src/main/resources/application-prod.yml @@ -93,6 +93,7 @@ security: - /v3/api-docs/** - /webjars/** - /favicon.ico + - /error # 文件存储配置 oss: