feat(plugin/tenant): 新增多租户插件模块 (#175)

This commit is contained in:
小熊
2025-07-10 20:38:59 +08:00
committed by GitHub
parent 72493f8161
commit ed6dd65a51
70 changed files with 3539 additions and 65 deletions

View File

@@ -64,6 +64,12 @@
<artifactId>liquibase-core</artifactId>
</dependency>
<!-- 多租户插件 -->
<dependency>
<groupId>top.continew.admin</groupId>
<artifactId>continew-plugin-tenant</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>

View File

@@ -23,6 +23,7 @@ import cn.hutool.core.convert.Convert;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.URLUtil;
import cn.hutool.extra.spring.SpringUtil;
import cn.hutool.http.HttpStatus;
import cn.hutool.json.JSONUtil;
import lombok.RequiredArgsConstructor;
@@ -41,6 +42,8 @@ import top.continew.admin.system.service.UserService;
import top.continew.starter.core.constant.StringConstants;
import top.continew.starter.core.util.ExceptionUtils;
import top.continew.starter.core.util.StrUtils;
import top.continew.starter.extension.tenant.TenantHandler;
import top.continew.starter.extension.tenant.context.TenantContextHolder;
import top.continew.starter.log.dao.LogDao;
import top.continew.starter.log.model.LogRecord;
import top.continew.starter.log.model.LogRequest;
@@ -85,7 +88,10 @@ public class LogDaoLocalImpl implements LogDao {
logDO.setCreateTime(LocalDateTime.ofInstant(logRecord.getTimestamp(), ZoneId.systemDefault()));
// 设置操作人
this.setCreateUser(logDO, logRequest, logResponse);
logMapper.insert(logDO);
Long tenantId = TenantContextHolder.getTenantId();
SpringUtil.getBean(TenantHandler.class).execute(tenantId, () -> {
logMapper.insert(logDO);
});
}
/**

View File

@@ -0,0 +1,59 @@
/*
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package top.continew.admin.config.tenant;
import com.baomidou.dynamic.datasource.toolkit.DynamicDataSourceContextHolder;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Component;
import top.continew.admin.common.constant.SysConstants;
import top.continew.starter.core.constant.PropertiesConstants;
import top.continew.starter.extension.tenant.context.TenantContextHolder;
import top.continew.starter.extension.tenant.enums.TenantIsolationLevel;
/**
* @description: 主数据源切面
* @author: 小熊
* @create: 2025-01-15 16:02
*/
@Aspect
@Component
@ConditionalOnProperty(prefix = PropertiesConstants.TENANT, name = PropertiesConstants.ENABLED, havingValue = "true")
public class DataSourceSwitchAspect {
@Pointcut("execution(* top.continew.admin.tenant.mapper..*(..)) || " + "execution(* top.continew.admin.tenant.service..*(..)) || " + "execution(* top.continew.admin.system.mapper.ClientMapper.*(..)) || " + "execution(* top.continew.admin.system.service.ClientService.*(..)) || " + "execution(* top.continew.admin.system.mapper.DictMapper.*(..)) || " + "execution(* top.continew.admin.system.service.DictService.*(..)) || " + "execution(* top.continew.admin.system.mapper.DictItemMapper.*(..)) || " + "execution(* top.continew.admin.system.service.DictItemService.*(..)) || " + "execution(* top.continew.admin.system.mapper.OptionMapper.*(..)) || " + "execution(* top.continew.admin.system.service.OptionService.*(..)) || " + "execution(* top.continew.admin.system.mapper.StorageMapper.*(..)) || " + "execution(* top.continew.admin.system.service.StorageService.*(..))")
public void MasterDataSourceMethods() {
}
@Before("MasterDataSourceMethods()")
public void switchToMasterDataSource() {
if (TenantContextHolder.getIsolationLevel() == TenantIsolationLevel.DATASOURCE) {
DynamicDataSourceContextHolder.push(SysConstants.DEFAULT_DATASOURCE);
}
}
@After("MasterDataSourceMethods()")
public void clearDataSourceContext() {
if (TenantContextHolder.getIsolationLevel() == TenantIsolationLevel.DATASOURCE) {
DynamicDataSourceContextHolder.poll();
}
}
}

View File

@@ -11,29 +11,37 @@ server:
--- ### 数据源配置
spring.datasource:
type: com.zaxxer.hikari.HikariDataSource
# 请务必提前创建好名为 continew_admin 的数据库,如果使用其他数据库名请注意同步修改 DB_NAME 配置
url: jdbc:p6spy:mysql://${DB_HOST:127.0.0.1}:${DB_PORT:3306}/${DB_NAME:continew_admin}?serverTimezone=Asia/Shanghai&useSSL=true&useUnicode=true&characterEncoding=utf8&rewriteBatchedStatements=true&autoReconnect=true&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true
username: ${DB_USER:root}
password: ${DB_PWD:123456}
driver-class-name: com.p6spy.engine.spy.P6SpyDriver
# # PostgreSQL 配置
# url: jdbc:p6spy:postgresql://${DB_HOST:127.0.0.1}:${DB_PORT:5432}/${DB_NAME:continew_admin}?serverTimezone=Asia/Shanghai&useSSL=true&useUnicode=true&characterEncoding=utf8&rewriteBatchedStatements=true&autoReconnect=true&stringtype=unspecified
# username: ${DB_USER:postgres}
# password: ${DB_PWD:123456}
# driver-class-name: com.p6spy.engine.spy.P6SpyDriver
# Hikari 连接池配置
hikari:
# 最大连接数量(默认 10根据实际环境调整
# 注意:当连接达到上限,并且没有空闲连接可用时,获取连接将在超时前阻塞最多 connectionTimeout 毫秒
maximum-pool-size: 20
# 获取连接超时时间(默认 30000 毫秒30 秒)
connection-timeout: 30000
# 空闲连接最大存活时间(默认 600000 毫秒10 分钟)
idle-timeout: 600000
# 保持连接活动的频率,以防止它被数据库或网络基础设施超时。该值必须小于 maxLifetime默认 0禁用
keepaliveTime: 30000
# 连接最大生存时间(默认 1800000 毫秒30 分钟
max-lifetime: 1800000
## 动态数据源配置可配多主多从m1、s1...纯粹多库mysql、oracle...混合配置m1、s1、oracle...
dynamic:
# 是否启用 P6SpySQL 性能分析组件,该插件有性能损耗,不建议生产环境使用)
p6spy: true
# 设置默认的数据源或者数据源组默认master
primary: master
# 严格匹配数据源true未匹配到指定数据源时抛异常false使用默认数据源默认 false
strict: false
datasource:
# 主库配置(可配多个,构成多主)
master:
url: jdbc:mysql://${DB_HOST:127.0.0.1}:${DB_PORT:3306}/${DB_NAME:continew_admin}?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf8&useSSL=false&allowMultiQueries=true&autoReconnect=true&maxReconnects=10&failOverReadOnly=false
username: ${DB_USER:root}
password: ${DB_PWD:123456}
driver-class-name: com.mysql.cj.jdbc.Driver
type: ${spring.datasource.type}
# Hikari 连接池配置完整配置请参阅https://github.com/brettwooldridge/HikariCP
hikari:
# 最大连接数量(默认 10根据实际环境调整
# 注意:当连接达到上限,并且没有空闲连接可用时,获取连接将在超时前阻塞最多 connectionTimeout 毫秒
maximum-pool-size: 20
# 获取连接超时时间(默认 30000 毫秒30
connection-timeout: 30000
# 空闲连接最大存活时间(默认 600000 毫秒10 分钟)
idle-timeout: 600000
# 保持连接活动的频率,以防止它被数据库或网络基础设施超时。该值必须小于 maxLifetime默认 0禁用
keepaliveTime: 30000
# 连接最大生存时间(默认 1800000 毫秒30 分钟)
max-lifetime: 1800000
## Liquibase 配置
spring.liquibase:
# 是否启用
@@ -168,7 +176,7 @@ captcha:
expirationInMinutes: 5
--- ### 短信配置
## 提示:配置文件方式和 [系统管理/系统配置/短信配置] 功能可任选其一方式使用,也可共同使用,但实际开发时建议选择一种,注释或删除另一方
## 提示:配置文件方式和 [短信配置] 功能可任选其一方式使用,也可共同使用,但实际开发时建议选择一种,注释或删除另一方
sms:
http-log: true
is-print: true
@@ -184,7 +192,7 @@ sms:
# sdk-app-id: 你的应用ID
--- ### 邮件配置
## 提示:配置文件方式和 [系统管理/系统配置/邮件配置] 功能可任选其一方式使用,实际开发时请注释或删除另一方
## 提示:配置文件方式和 [邮件配置] 功能可任选其一方式使用,实际开发时请注释或删除另一方
#spring.mail:
# # 根据需要更换
# host: smtp.126.com

View File

@@ -13,29 +13,36 @@ server:
--- ### 数据源配置
spring.datasource:
type: com.zaxxer.hikari.HikariDataSource
# 请务必提前创建好名为 continew_admin 的数据库,如果使用其他数据库名请注意同步修改 DB_NAME 配置
url: jdbc:mysql://${DB_HOST:127.0.0.1}:${DB_PORT:3306}/${DB_NAME:continew_admin}?serverTimezone=Asia/Shanghai&useSSL=true&useUnicode=true&characterEncoding=utf8&rewriteBatchedStatements=true&autoReconnect=true&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true
username: ${DB_USER:root}
password: ${DB_PWD:123456}
driver-class-name: com.mysql.cj.jdbc.Driver
# # PostgreSQL 配置
# url: jdbc:postgresql://${DB_HOST:127.0.0.1}:${DB_PORT:5432}/${DB_NAME:continew_admin}?serverTimezone=Asia/Shanghai&useSSL=true&useUnicode=true&characterEncoding=utf8&rewriteBatchedStatements=true&autoReconnect=true&stringtype=unspecified
# username: ${DB_USER:postgres}
# password: ${DB_PWD:123456}
# driver-class-name: org.postgresql.Driver
# Hikari 连接池配置
hikari:
# 最大连接数量(默认 10根据实际环境调整
# 注意:当连接达到上限,并且没有空闲连接可用时,获取连接将在超时前阻塞最多 connectionTimeout 毫秒
maximum-pool-size: 20
# 获取连接超时时间(默认 30000 毫秒30 秒)
connection-timeout: 30000
# 空闲连接最大存活时间(默认 600000 毫秒10 分钟)
idle-timeout: 600000
# 保持连接活动的频率,以防止它被数据库或网络基础设施超时。该值必须小于 maxLifetime默认 0禁用
keepaliveTime: 30000
# 连接最大生存时间(默认 1800000 毫秒30 分钟
max-lifetime: 1800000
## 动态数据源配置可配多主多从m1、s1...纯粹多库mysql、oracle...混合配置m1、s1、oracle...
dynamic:
# 是否启用 P6SpySQL 性能分析组件,该插件有性能损耗,不建议生产环境使用)
p6spy: false
# 设置默认的数据源或者数据源组默认master
primary: master
# 严格匹配数据源true未匹配到指定数据源时抛异常false使用默认数据源默认 false
strict: false
datasource:
# 主库配置(可配多个,构成多主)
master:
url: jdbc:mysql://${DB_HOST:127.0.0.1}:${DB_PORT:3306}/${DB_NAME:continew_admin}?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf8&useSSL=false&allowMultiQueries=true&autoReconnect=true&maxReconnects=10&failOverReadOnly=false
username: ${DB_USER:root}
password: ${DB_PWD:123456}
driver-class-name: com.mysql.cj.jdbc.Driver
type: ${spring.datasource.type}
# Hikari 连接池配置完整配置请参阅https://github.com/brettwooldridge/HikariCP
hikari:
# 最大连接数量(默认 10根据实际环境调整
# 注意:当连接达到上限,并且没有空闲连接可用时,获取连接将在超时前阻塞最多 connectionTimeout 毫秒
maximum-pool-size: 20
# 获取连接超时时间(默认 30000 毫秒30
connection-timeout: 30000
# 空闲连接最大存活时间(默认 600000 毫秒10 分钟)
idle-timeout: 600000
# 保持连接活动的频率,以防止它被数据库或网络基础设施超时。该值必须小于 maxLifetime默认 0禁用
keepaliveTime: 30000
# 连接最大生存时间(默认 1800000 毫秒30 分钟)
max-lifetime: 1800000
## Liquibase 配置
spring.liquibase:
# 是否启用

View File

@@ -261,7 +261,6 @@ mybatis-plus:
# 分页插件配置
pagination:
enabled: true
db-type: MYSQL
--- ### CosId 配置
cosid:
@@ -299,3 +298,32 @@ auth:
- /auth/logout
- /system/user/password
#多租户配置
continew-starter.tenant:
enabled: true
# 多租户忽略的表
ignore-tables:
- gen_config # 代码生成
- gen_field_config
- sys_dict # 字典表
- sys_dict_item
- sys_option #参数
- sys_storage # 存储配置
- sys_tenant # 租户
- sys_tenant_package
- sys_tenant_db_connect
- sys_app #应用
- sys_client #客户端管理
- sys_sms_config
- sys_sms_log
#租户不能使用的菜单
ignore-menus:
- 1130 #字典管理
- 1140
- 1150 #系统配置
- 2050 #短信日志
- 3000 #任务调度
- 9000 #代码生成
- 7000 #能力开放
- 7010 #应用管理
- 10010 #租户管理

View File

@@ -11,6 +11,8 @@ databaseChangeLog:
file: db/changelog/mysql/plugin/plugin_open.sql
- include:
file: db/changelog/mysql/plugin/plugin_generator.sql
- include:
file: db/changelog/mysql/plugin/plugin_tenant.sql
# PostgreSQL
# - include:
# file: db/changelog/postgresql/main_table.sql

View File

@@ -0,0 +1,145 @@
-- liquibase formatted sql
-- changeset 小熊:1
-- comment 初始化表结构
-- ----------------------------
-- Table structure for sys_tenant
-- ----------------------------
DROP TABLE IF EXISTS `sys_tenant`;
CREATE TABLE `sys_tenant` (
`id` bigint NOT NULL COMMENT 'ID',
`name` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '租户名称',
`tenant_sn` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '租户编号',
`user_id` bigint DEFAULT NULL COMMENT '租户对应的用户',
`domain` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '绑定的域名',
`package_id` bigint NOT NULL COMMENT '租户套餐编号',
`status` tinyint unsigned NOT NULL DEFAULT '1' COMMENT '状态1启用2禁用',
`expire_time` datetime DEFAULT NULL COMMENT '租户过期时间',
`create_user` bigint NOT NULL COMMENT '创建人',
`create_time` datetime NOT NULL COMMENT '创建时间',
`update_user` bigint DEFAULT NULL COMMENT '修改人',
`update_time` datetime DEFAULT NULL COMMENT '修改时间',
`isolation_level` tinyint unsigned NOT NULL COMMENT '隔离级别',
`db_connect_id` bigint DEFAULT NULL COMMENT '数据连接ID',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='租户表';
-- ----------------------------
-- Table structure for sys_tenant_package
-- ----------------------------
DROP TABLE IF EXISTS `sys_tenant_package`;
CREATE TABLE `sys_tenant_package` (
`id` bigint NOT NULL COMMENT 'ID',
`name` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '套餐名称',
`menu_ids` varchar(2000) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '关联的菜单ids',
`menu_check_strictly` bit(1) DEFAULT b'0' COMMENT '菜单选择是否父子节点关联',
`status` tinyint unsigned NOT NULL DEFAULT '1' COMMENT '状态1启用2禁用',
`create_user` bigint NOT NULL COMMENT '创建人',
`create_time` datetime NOT NULL COMMENT '创建时间',
`update_user` bigint DEFAULT NULL COMMENT '修改人',
`update_time` datetime DEFAULT NULL COMMENT '修改时间',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='租户套餐表';
-- ----------------------------
-- Table structure for sys_tenant_db_connect
-- ----------------------------
CREATE TABLE `sys_tenant_db_connect` (
`id` bigint NOT NULL COMMENT 'ID',
`connect_name` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '连接名称',
`type` tinyint(1) NOT NULL COMMENT '连接类型',
`host` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '连接主机地址',
`port` smallint NOT NULL COMMENT '连接端口',
`username` varchar(128) NOT NULL COMMENT '连接用户名',
`password` varchar(128) NOT NULL COMMENT '连接密码',
`create_user` bigint NOT NULL COMMENT '创建人',
`create_time` datetime NOT NULL COMMENT '创建时间',
`update_user` bigint DEFAULT NULL COMMENT '修改人',
`update_time` datetime DEFAULT NULL COMMENT '修改时间',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='租户数据库连接表';
-- changeset 小熊:2
-- comment 添加租户列和索引
ALTER TABLE sys_app ADD COLUMN tenant_id BIGINT NOT NULL DEFAULT 0;
CREATE INDEX idx_sys_app_tenant_id ON sys_app(tenant_id);
ALTER TABLE sys_dept ADD COLUMN tenant_id BIGINT NOT NULL DEFAULT 0;
CREATE INDEX idx_sys_dept_tenant_id ON sys_dept(tenant_id);
ALTER TABLE sys_file ADD COLUMN tenant_id BIGINT NOT NULL DEFAULT 0;
CREATE INDEX idx_sys_file_tenant_id ON sys_file(tenant_id);
ALTER TABLE sys_log ADD COLUMN tenant_id BIGINT NOT NULL DEFAULT 0;
CREATE INDEX idx_sys_log_tenant_id ON sys_log(tenant_id);
ALTER TABLE sys_menu ADD COLUMN tenant_id BIGINT NOT NULL DEFAULT 0;
CREATE INDEX idx_sys_menu_tenant_id ON sys_menu(tenant_id);
ALTER TABLE sys_message ADD COLUMN tenant_id BIGINT NOT NULL DEFAULT 0;
CREATE INDEX idx_sys_message_tenant_id ON sys_message(tenant_id);
ALTER TABLE sys_message_log ADD COLUMN tenant_id BIGINT NOT NULL DEFAULT 0;
CREATE INDEX idx_sys_message_log_tenant_id ON sys_message_log(tenant_id);
ALTER TABLE sys_notice ADD COLUMN tenant_id BIGINT NOT NULL DEFAULT 0;
CREATE INDEX idx_sys_notice_tenant_id ON sys_notice(tenant_id);
ALTER TABLE sys_notice_log ADD COLUMN tenant_id BIGINT NOT NULL DEFAULT 0;
CREATE INDEX idx_sys_notice_log_tenant_id ON sys_notice_log(tenant_id);
ALTER TABLE sys_role ADD COLUMN tenant_id BIGINT NOT NULL DEFAULT 0;
CREATE INDEX idx_sys_role_tenant_id ON sys_role(tenant_id);
ALTER TABLE sys_user ADD COLUMN tenant_id BIGINT NOT NULL DEFAULT 0;
CREATE INDEX idx_sys_user_tenant_id ON sys_user(tenant_id);
ALTER TABLE sys_role_dept ADD COLUMN tenant_id BIGINT NOT NULL DEFAULT 0;
CREATE INDEX idx_sys_role_dept_tenant_id ON sys_role_dept(tenant_id);
ALTER TABLE sys_role_menu ADD COLUMN tenant_id BIGINT NOT NULL DEFAULT 0;
CREATE INDEX idx_sys_role_menu_tenant_id ON sys_role_menu(tenant_id);
ALTER TABLE sys_user_password_history ADD COLUMN tenant_id BIGINT NOT NULL DEFAULT 0;
CREATE INDEX idx_sys_user_password_history_tenant_id ON sys_user_password_history(tenant_id);
ALTER TABLE sys_user_role ADD COLUMN tenant_id BIGINT NOT NULL DEFAULT 0;
CREATE INDEX idx_sys_user_role_tenant_id ON sys_user_role(tenant_id);
ALTER TABLE sys_user_social ADD COLUMN tenant_id BIGINT NOT NULL DEFAULT 0;
CREATE INDEX idx_sys_user_social_tenant_id ON sys_user_social(tenant_id);
-- changeset 小熊:3
-- comment 唯一索引变更
ALTER TABLE sys_app DROP INDEX `uk_access_key`;
ALTER TABLE sys_app ADD UNIQUE INDEX `uk_access_key` (`access_key`, `tenant_id`);
ALTER TABLE sys_dept DROP INDEX `uk_name_parent_id`;
ALTER TABLE sys_dept ADD UNIQUE INDEX `uk_name_parent_id` (`name`, `parent_id`, `tenant_id`);
ALTER TABLE sys_menu DROP INDEX `uk_title_parent_id`;
ALTER TABLE sys_menu ADD UNIQUE INDEX `uk_title_parent_id` (`title`, `parent_id`, `tenant_id`);
ALTER TABLE sys_role DROP INDEX `uk_name`;
ALTER TABLE sys_role ADD UNIQUE INDEX `uk_name` (`name`, `tenant_id`);
ALTER TABLE sys_role DROP INDEX `uk_code`;
ALTER TABLE sys_role ADD UNIQUE INDEX `uk_code` (`code`, `tenant_id`);
ALTER TABLE sys_user DROP INDEX `uk_username`;
ALTER TABLE sys_user ADD UNIQUE INDEX `uk_username` (`username`, `tenant_id`);
ALTER TABLE sys_user DROP INDEX `uk_email`;
ALTER TABLE sys_user ADD UNIQUE INDEX `uk_email` (`email`, `tenant_id`);
ALTER TABLE sys_user DROP INDEX `uk_phone`;
ALTER TABLE sys_user ADD UNIQUE INDEX `uk_phone` (`phone`, `tenant_id`);
-- changeset 小熊:4
-- comment 菜单录入
INSERT INTO `sys_menu`
(`id`, `title`, `parent_id`, `type`, `path`, `name`, `component`, `redirect`, `icon`, `is_external`, `is_cache`, `is_hidden`, `permission`, `sort`, `status`, `create_user`, `create_time`, `update_user`, `update_time`, `tenant_id`)
VALUES
(10010, '租户管理', 0, 1, '/tenant', 'Tenant', 'Layout', '/tenant/user', 'user-group', b'0', b'0', b'0', NULL, 6, 1, 1, NOW(), NULL, NULL, 0),
(10015, '租户套餐', 10010, 2, '/tenant/package', 'TenantPackage', 'tenant/package/index', NULL, 'menu', b'0', b'0', b'0', NULL, 2, 1, 1, NOW(), NULL, NULL, 0),
(10016, '列表', 10015, 3, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 'tenant:package:list', 1, 1, 1, NOW(), NULL, NULL, 0),
(10017, '详情', 10015, 3, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 'tenant:package:detail', 2, 1, 1, NOW(), NULL, NULL, 0),
(10018, '新增', 10015, 3, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 'tenant:package:add', 3, 1, 1, NOW(), NULL, NULL, 0),
(10019, '修改', 10015, 3, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 'tenant:package:update', 4, 1, 1, NOW(), NULL, NULL, 0),
(10020, '删除', 10015, 3, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 'tenant:package:delete', 5, 1, 1, NOW(), NULL, NULL, 0),
(10022, '租户管理', 10010, 2, '/tenant/user', 'TenantUser', 'tenant/user/index', NULL, 'user-group', b'0', b'0', b'0', NULL, 1, 1, 1, NOW(), NULL, NULL, 0),
(10023, '列表', 10022, 3, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 'tenant:user:list', 1, 1, 1, NOW(), NULL, NULL, 0),
(10024, '详情', 10022, 3, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 'tenant:user:detail', 2, 1, 1, NOW(), NULL, NULL, 0),
(10025, '新增', 10022, 3, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 'tenant:user:add', 3, 1, 1, NOW(), NULL, NULL, 0),
(10026, '修改', 10022, 3, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 'tenant:user:update', 4, 1, 1, NOW(), NULL, NULL, 0),
(10027, '删除', 10022, 3, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 'tenant:user:delete', 5, 1, 1, NOW(), NULL, NULL, 0),
(10028, '账号更新', 10022, 3, NULL, NULL, NULL, NULL, NULL, b'0', b'0', b'0', 'tenant:user:editLoginUserInfo', 6, 1, 1, NOW(), NULL, NULL, 0),
(10040, '数据连接', 10010, 2, '/tenant/dbConnect', 'TenantDbConnect', 'tenant/tenantDbConnect/index', NULL, 'storage', b'0', b'0', b'0', NULL, 3, 1, 1, NOW(), NULL, NULL, 0),
(10041, '列表', 10040, 3, NULL, NULL, NULL, NULL, NULL, b'0', b'0', b'0', 'tenant:dbConnect:list', 1, 1, 1, NOW(), NULL, NULL, 0),
(10042, '详情', 10040, 3, NULL, NULL, NULL, NULL, NULL, b'0', b'0', b'0', 'tenant:dbConnect:detail', 2, 1, 1, NOW(), NULL, NULL, 0),
(10043, '新增', 10040, 3, NULL, NULL, NULL, NULL, NULL, b'0', b'0', b'0', 'tenant:dbConnect:add', 3, 1, 1, NOW(), NULL, NULL, 0),
(10044, '修改', 10040, 3, NULL, NULL, NULL, NULL, NULL, b'0', b'0', b'0', 'tenant:dbConnect:update', 4, 1, 1, NOW(), NULL, NULL, 0),
(10045, '删除', 10040, 3, NULL, NULL, NULL, NULL, NULL, b'0', b'0', b'0', 'tenant:dbConnect:delete', 5, 1, 1, NOW(), NULL, NULL, 0);

View File

@@ -0,0 +1,241 @@
-- 数据源级别租户表结构
CREATE TABLE IF NOT EXISTS `sys_menu` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'ID',
`title` varchar(30) NOT NULL COMMENT '标题',
`parent_id` bigint(20) NOT NULL DEFAULT 0 COMMENT '上级菜单ID',
`type` tinyint(1) UNSIGNED NOT NULL DEFAULT 1 COMMENT '类型1目录2菜单3按钮',
`path` varchar(255) DEFAULT NULL COMMENT '路由地址',
`name` varchar(50) DEFAULT NULL COMMENT '组件名称',
`component` varchar(255) DEFAULT NULL COMMENT '组件路径',
`redirect` varchar(255) DEFAULT NULL COMMENT '重定向地址',
`icon` varchar(50) DEFAULT NULL COMMENT '图标',
`is_external` bit(1) DEFAULT b'0' COMMENT '是否外链',
`is_cache` bit(1) DEFAULT b'0' COMMENT '是否缓存',
`is_hidden` bit(1) DEFAULT b'0' COMMENT '是否隐藏',
`permission` varchar(100) DEFAULT NULL COMMENT '权限标识',
`sort` int NOT NULL DEFAULT 999 COMMENT '排序',
`status` tinyint(1) UNSIGNED NOT NULL DEFAULT 1 COMMENT '状态1启用2禁用',
`create_user` bigint(20) NOT NULL COMMENT '创建人',
`create_time` datetime NOT NULL COMMENT '创建时间',
`update_user` bigint(20) DEFAULT NULL COMMENT '修改人',
`update_time` datetime DEFAULT NULL COMMENT '修改时间',
PRIMARY KEY (`id`),
UNIQUE INDEX `uk_title_parent_id`(`title`, `parent_id`),
INDEX `idx_parent_id`(`parent_id`),
INDEX `idx_create_user`(`create_user`),
INDEX `idx_update_user`(`update_user`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='菜单表';
CREATE TABLE IF NOT EXISTS `sys_dept` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'ID',
`name` varchar(30) NOT NULL COMMENT '名称',
`parent_id` bigint(20) NOT NULL DEFAULT 0 COMMENT '上级部门ID',
`ancestors` varchar(512) NOT NULL DEFAULT '' COMMENT '祖级列表',
`description` varchar(200) DEFAULT NULL COMMENT '描述',
`sort` int NOT NULL DEFAULT 999 COMMENT '排序',
`status` tinyint(1) UNSIGNED NOT NULL DEFAULT 1 COMMENT '状态1启用2禁用',
`is_system` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否为系统内置数据',
`create_user` bigint(20) NOT NULL COMMENT '创建人',
`create_time` datetime NOT NULL COMMENT '创建时间',
`update_user` bigint(20) DEFAULT NULL COMMENT '修改人',
`update_time` datetime DEFAULT NULL COMMENT '修改时间',
PRIMARY KEY (`id`),
UNIQUE INDEX `uk_name_parent_id`(`name`, `parent_id`),
INDEX `idx_parent_id`(`parent_id`),
INDEX `idx_create_user`(`create_user`),
INDEX `idx_update_user`(`update_user`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='部门表';
CREATE TABLE IF NOT EXISTS `sys_role` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'ID',
`name` varchar(30) NOT NULL COMMENT '名称',
`code` varchar(30) NOT NULL COMMENT '编码',
`data_scope` tinyint(1) NOT NULL DEFAULT 4 COMMENT '数据权限1全部数据权限2本部门及以下数据权限3本部门数据权限4仅本人数据权限5自定义数据权限',
`description` varchar(200) DEFAULT NULL COMMENT '描述',
`sort` int NOT NULL DEFAULT 999 COMMENT '排序',
`is_system` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否为系统内置数据',
`menu_check_strictly` bit(1) DEFAULT b'0' COMMENT '菜单选择是否父子节点关联',
`dept_check_strictly` bit(1) DEFAULT b'0' COMMENT '部门选择是否父子节点关联',
`create_user` bigint(20) NOT NULL COMMENT '创建人',
`create_time` datetime NOT NULL COMMENT '创建时间',
`update_user` bigint(20) DEFAULT NULL COMMENT '修改人',
`update_time` datetime DEFAULT NULL COMMENT '修改时间',
PRIMARY KEY (`id`),
UNIQUE INDEX `uk_name`(`name`),
UNIQUE INDEX `uk_code`(`code`),
INDEX `idx_create_user`(`create_user`),
INDEX `idx_update_user`(`update_user`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='角色表';
CREATE TABLE IF NOT EXISTS `sys_user` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'ID',
`username` varchar(64) NOT NULL COMMENT '用户名',
`nickname` varchar(30) NOT NULL COMMENT '昵称',
`password` varchar(255) DEFAULT NULL COMMENT '密码',
`gender` tinyint(1) UNSIGNED NOT NULL DEFAULT 0 COMMENT '性别0未知12',
`email` varchar(255) DEFAULT NULL COMMENT '邮箱',
`phone` varchar(255) DEFAULT NULL COMMENT '手机号码',
`avatar` longtext DEFAULT NULL COMMENT '头像',
`description` varchar(200) DEFAULT NULL COMMENT '描述',
`status` tinyint(1) UNSIGNED NOT NULL DEFAULT 1 COMMENT '状态1启用2禁用',
`is_system` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否为系统内置数据',
`pwd_reset_time` datetime DEFAULT NULL COMMENT '最后一次修改密码时间',
`dept_id` bigint(20) NOT NULL COMMENT '部门ID',
`create_user` bigint(20) DEFAULT NULL COMMENT '创建人',
`create_time` datetime NOT NULL COMMENT '创建时间',
`update_user` bigint(20) DEFAULT NULL COMMENT '修改人',
`update_time` datetime DEFAULT NULL COMMENT '修改时间',
PRIMARY KEY (`id`),
UNIQUE INDEX `uk_username`(`username`),
UNIQUE INDEX `uk_email`(`email`),
UNIQUE INDEX `uk_phone`(`phone`),
INDEX `idx_dept_id`(`dept_id`),
INDEX `idx_create_user`(`create_user`),
INDEX `idx_update_user`(`update_user`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户表';
CREATE TABLE IF NOT EXISTS `sys_user_password_history` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'ID',
`user_id` bigint(20) NOT NULL COMMENT '用户ID',
`password` varchar(255) NOT NULL COMMENT '密码',
`create_time` datetime NOT NULL COMMENT '创建时间',
PRIMARY KEY (`id`),
INDEX `idx_user_id`(`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户历史密码表';
CREATE TABLE IF NOT EXISTS `sys_user_social` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'ID',
`source` varchar(255) NOT NULL COMMENT '来源',
`open_id` varchar(255) NOT NULL COMMENT '开放ID',
`user_id` bigint(20) NOT NULL COMMENT '用户ID',
`meta_json` text DEFAULT NULL COMMENT '附加信息',
`last_login_time` datetime DEFAULT NULL COMMENT '最后登录时间',
`create_time` datetime NOT NULL COMMENT '创建时间',
PRIMARY KEY (`id`),
UNIQUE INDEX `uk_source_open_id`(`source`, `open_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户社会化关联表';
CREATE TABLE IF NOT EXISTS `sys_user_role` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'ID',
`user_id` bigint(20) NOT NULL COMMENT '用户ID',
`role_id` bigint(20) NOT NULL COMMENT '角色ID',
PRIMARY KEY (`id`),
UNIQUE INDEX `uk_user_id_role_id`(`user_id`, `role_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户和角色关联表';
CREATE TABLE IF NOT EXISTS `sys_role_menu` (
`role_id` bigint(20) NOT NULL COMMENT '角色ID',
`menu_id` bigint(20) NOT NULL COMMENT '菜单ID',
PRIMARY KEY (`role_id`, `menu_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='角色和菜单关联表';
CREATE TABLE IF NOT EXISTS `sys_role_dept` (
`role_id` bigint(20) NOT NULL COMMENT '角色ID',
`dept_id` bigint(20) NOT NULL COMMENT '部门ID',
PRIMARY KEY (`role_id`, `dept_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='角色和部门关联表';
CREATE TABLE IF NOT EXISTS `sys_log` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'ID',
`trace_id` varchar(255) DEFAULT NULL COMMENT '链路ID',
`description` varchar(255) NOT NULL COMMENT '日志描述',
`module` varchar(100) NOT NULL COMMENT '所属模块',
`request_url` varchar(512) NOT NULL COMMENT '请求URL',
`request_method` varchar(10) NOT NULL COMMENT '请求方式',
`request_headers` text DEFAULT NULL COMMENT '请求头',
`request_body` text DEFAULT NULL COMMENT '请求体',
`status_code` int NOT NULL COMMENT '状态码',
`response_headers` text DEFAULT NULL COMMENT '响应头',
`response_body` mediumtext DEFAULT NULL COMMENT '响应体',
`time_taken` bigint(20) NOT NULL COMMENT '耗时ms',
`ip` varchar(100) DEFAULT NULL COMMENT 'IP',
`address` varchar(255) DEFAULT NULL COMMENT 'IP归属地',
`browser` varchar(100) DEFAULT NULL COMMENT '浏览器',
`os` varchar(100) DEFAULT NULL COMMENT '操作系统',
`status` tinyint(1) UNSIGNED NOT NULL DEFAULT 1 COMMENT '状态1成功2失败',
`error_msg` text DEFAULT NULL COMMENT '错误信息',
`create_user` bigint(20) DEFAULT NULL COMMENT '创建人',
`create_time` datetime NOT NULL COMMENT '创建时间',
PRIMARY KEY (`id`),
INDEX `idx_module`(`module`),
INDEX `idx_ip`(`ip`),
INDEX `idx_address`(`address`),
INDEX `idx_create_time`(`create_time`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='系统日志表';
CREATE TABLE IF NOT EXISTS `sys_message` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'ID',
`title` varchar(50) NOT NULL COMMENT '标题',
`content` text DEFAULT NULL COMMENT '内容',
`type` tinyint(1) UNSIGNED NOT NULL DEFAULT 1 COMMENT '类型1系统消息2安全消息',
`path` varchar(255) DEFAULT NULL COMMENT '跳转路径',
`scope` tinyint(1) UNSIGNED NOT NULL DEFAULT 1 COMMENT '通知范围1所有人2指定用户',
`users` json DEFAULT NULL COMMENT '通知用户',
`create_time` datetime NOT NULL COMMENT '创建时间',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='消息表';
CREATE TABLE IF NOT EXISTS `sys_message_log` (
`message_id` bigint(20) NOT NULL COMMENT '消息ID',
`user_id` bigint(20) NOT NULL COMMENT '用户ID',
`read_time` datetime DEFAULT NULL COMMENT '读取时间',
PRIMARY KEY (`message_id`, `user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='消息日志表';
CREATE TABLE IF NOT EXISTS `sys_notice` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'ID',
`title` varchar(150) NOT NULL COMMENT '标题',
`content` mediumtext NOT NULL COMMENT '内容',
`type` varchar(30) NOT NULL COMMENT '分类',
`notice_scope` tinyint(1) UNSIGNED NOT NULL DEFAULT 1 COMMENT '通知范围1所有人2指定用户',
`notice_users` json DEFAULT NULL COMMENT '通知用户',
`notice_methods` json DEFAULT NULL COMMENT '通知方式1系统消息2登录弹窗',
`is_timing` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否定时',
`publish_time` datetime DEFAULT NULL COMMENT '发布时间',
`is_top` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否置顶',
`status` tinyint(1) UNSIGNED NOT NULL DEFAULT 1 COMMENT '状态1草稿2待发布3已发布',
`create_user` bigint(20) NOT NULL COMMENT '创建人',
`create_time` datetime NOT NULL COMMENT '创建时间',
`update_user` bigint(20) DEFAULT NULL COMMENT '修改人',
`update_time` datetime DEFAULT NULL COMMENT '修改时间',
PRIMARY KEY (`id`),
INDEX `idx_create_user`(`create_user`),
INDEX `idx_update_user`(`update_user`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='公告表';
CREATE TABLE IF NOT EXISTS `sys_notice_log` (
`notice_id` bigint(20) NOT NULL COMMENT '公告ID',
`user_id` bigint(20) NOT NULL COMMENT '用户ID',
`read_time` datetime DEFAULT NULL COMMENT '读取时间',
PRIMARY KEY (`notice_id`, `user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='公告日志表';
CREATE TABLE IF NOT EXISTS `sys_file` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'ID',
`name` varchar(255) NOT NULL COMMENT '名称',
`original_name` varchar(255) NOT NULL COMMENT '原始名称',
`size` bigint(20) DEFAULT NULL COMMENT '大小(字节)',
`parent_path` varchar(512) NOT NULL DEFAULT '/' COMMENT '上级目录',
`path` varchar(512) NOT NULL COMMENT '路径',
`extension` varchar(32) DEFAULT NULL COMMENT '扩展名',
`content_type` varchar(255) DEFAULT NULL COMMENT '内容类型',
`type` tinyint(1) UNSIGNED NOT NULL DEFAULT 1 COMMENT '类型0: 目录1其他2图片3文档4视频5音频',
`sha256` varchar(256) DEFAULT NULL COMMENT 'SHA256值',
`metadata` text DEFAULT NULL COMMENT '元数据',
`thumbnail_name` varchar(255) DEFAULT NULL COMMENT '缩略图名称',
`thumbnail_size` bigint(20) DEFAULT NULL COMMENT '缩略图大小(字节)',
`thumbnail_metadata` text DEFAULT NULL COMMENT '缩略图元数据',
`storage_id` bigint(20) NOT NULL COMMENT '存储ID',
`create_user` bigint(20) NOT NULL COMMENT '创建人',
`create_time` datetime NOT NULL COMMENT '创建时间',
`update_user` bigint(20) DEFAULT NULL COMMENT '修改人',
`update_time` datetime DEFAULT NULL COMMENT '修改时间',
PRIMARY KEY (`id`),
INDEX `idx_type`(`type`),
INDEX `idx_sha256`(`sha256`),
INDEX `idx_storage_id`(`storage_id`),
INDEX `idx_create_user`(`create_user`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='文件表';