From 80146224ab5eefdd953174ce9dbde7e6e70d1c18 Mon Sep 17 00:00:00 2001 From: Wu Clan Date: Thu, 12 Mar 2026 23:12:30 +0800 Subject: [PATCH] Fix and improve tenant-related impls --- backend/app/admin/crud/crud_role.py | 28 +++- backend/app/admin/crud/crud_user.py | 31 +++-- backend/app/admin/model/opera_log.py | 6 +- backend/app/admin/schema/login_log.py | 4 + backend/app/admin/schema/opera_log.py | 6 + backend/app/admin/schema/user.py | 8 +- backend/app/admin/service/auth_service.py | 3 + .../app/admin/service/login_log_service.py | 4 + backend/cli.py | 21 ++- backend/common/context.py | 2 +- backend/common/security/jwt.py | 7 +- backend/core/conf.py | 1 + backend/middleware/opera_log_middleware.py | 5 + backend/middleware/state_middleware.py | 4 + backend/plugin/core.py | 67 +++++----- .../sql/mysql/init_snowflake_tenant.sql | 27 ++++ .../plugin/notice/sql/mysql/init_tenant.sql | 31 +++++ .../sql/postgresql/init_snowflake_tenant.sql | 27 ++++ .../notice/sql/postgresql/init_tenant.sql | 37 ++++++ .../mysql/init_snowflake_test_data_tenant.sql | 109 ++++++++++++++++ backend/sql/mysql/init_test_data_tenant.sql | 109 ++++++++++++++++ .../init_snowflake_test_data_tenant.sql | 109 ++++++++++++++++ .../sql/postgresql/init_test_data_tenant.sql | 120 ++++++++++++++++++ 23 files changed, 692 insertions(+), 74 deletions(-) create mode 100644 backend/plugin/notice/sql/mysql/init_snowflake_tenant.sql create mode 100644 backend/plugin/notice/sql/mysql/init_tenant.sql create mode 100644 backend/plugin/notice/sql/postgresql/init_snowflake_tenant.sql create mode 100644 backend/plugin/notice/sql/postgresql/init_tenant.sql create mode 100644 backend/sql/mysql/init_snowflake_test_data_tenant.sql create mode 100644 backend/sql/mysql/init_test_data_tenant.sql create mode 100644 backend/sql/postgresql/init_snowflake_test_data_tenant.sql create mode 100644 backend/sql/postgresql/init_test_data_tenant.sql diff --git a/backend/app/admin/crud/crud_role.py b/backend/app/admin/crud/crud_role.py index 2a6b38bf..ee29c560 100644 --- a/backend/app/admin/crud/crud_role.py +++ b/backend/app/admin/crud/crud_role.py @@ -14,8 +14,19 @@ from backend.app.admin.schema.role import ( UpdateRoleParam, UpdateRoleScopeParam, ) +from backend.core.conf import settings from backend.utils.serializers import select_join_serialize +if settings.TENANT_ENABLED: + try: + from backend.plugin.tenant.utils import get_tenant_dict as inject_tenant_dict + except ImportError: + raise ImportError('租户插件方法导入失败,请联系系统管理员') +else: + + def inject_tenant_dict(obj: dict[str, Any]) -> dict[str, Any]: + return obj + class CRUDRole(CRUDPlus[Role]): """角色数据库操作类""" @@ -136,9 +147,11 @@ class CRUDRole(CRUDPlus[Role]): await db.execute(role_menu_stmt) if menu_ids.menus: - role_menu_data = [ - CreateRoleMenuParam(role_id=role_id, menu_id=menu_id).model_dump() for menu_id in menu_ids.menus - ] + role_menu_data = [] + for menu_id in menu_ids.menus: + menu_dict = CreateRoleMenuParam(role_id=role_id, menu_id=menu_id).model_dump() + role_menu_data.append(inject_tenant_dict(menu_dict)) + role_menu_stmt = insert(role_menu) await db.execute(role_menu_stmt, role_menu_data) @@ -158,10 +171,11 @@ class CRUDRole(CRUDPlus[Role]): await db.execute(role_scope_stmt) if scope_ids.scopes: - role_scope_data = [ - CreateRoleScopeParam(role_id=role_id, data_scope_id=scope_id).model_dump() - for scope_id in scope_ids.scopes - ] + role_scope_data = [] + for scope_id in scope_ids.scopes: + scope_dict = CreateRoleScopeParam(role_id=role_id, data_scope_id=scope_id).model_dump() + role_scope_data.append(inject_tenant_dict(scope_dict)) + role_scope_stmt = insert(role_data_scope) await db.execute(role_scope_stmt, role_scope_data) diff --git a/backend/app/admin/crud/crud_user.py b/backend/app/admin/crud/crud_user.py index eb07e0e6..8e3c15da 100644 --- a/backend/app/admin/crud/crud_user.py +++ b/backend/app/admin/crud/crud_user.py @@ -33,11 +33,13 @@ from backend.utils.timezone import timezone if settings.TENANT_ENABLED: try: - from backend.plugin.tenant.filter import get_tenant_dict + from backend.plugin.tenant.utils import get_tenant_dict as inject_tenant_dict except ImportError: - raise ImportError('租户插件用法导入失败,请联系系统管理员') + raise ImportError('租户插件方法导入失败,请联系系统管理员') else: - get_tenant_dict = None # type: ignore + + def inject_tenant_dict(obj: dict[str, Any]) -> dict[str, Any]: + return obj class CRUDUser(CRUDPlus[User]): @@ -128,9 +130,7 @@ class CRUDUser(CRUDPlus[User]): dict_obj = obj.model_dump(exclude={'roles'}) dict_obj.update({'salt': salt}) - - if get_tenant_dict is not None: - dict_obj = get_tenant_dict(dict_obj) + dict_obj = inject_tenant_dict(dict_obj) new_user = self.model(**dict_obj) db.add(new_user) @@ -141,7 +141,11 @@ class CRUDUser(CRUDPlus[User]): result = await db.execute(role_stmt) roles = result.scalars().all() - user_role_data = [AddUserRoleParam(user_id=new_user.id, role_id=role.id).model_dump() for role in roles] + user_role_data = [] + for role in roles: + role_dict = AddUserRoleParam(user_id=new_user.id, role_id=role.id).model_dump() + user_role_data.append(inject_tenant_dict(role_dict)) + user_role_stmt = insert(user_role) await db.execute(user_role_stmt, user_role_data) @@ -155,9 +159,7 @@ class CRUDUser(CRUDPlus[User]): """ dict_obj = obj.model_dump() dict_obj.update({'is_staff': True, 'salt': None}) - - if get_tenant_dict is not None: - dict_obj = get_tenant_dict(dict_obj) + dict_obj = inject_tenant_dict(dict_obj) new_user = self.model(**dict_obj) db.add(new_user) @@ -167,7 +169,8 @@ class CRUDUser(CRUDPlus[User]): result = await db.execute(role_stmt) role = result.scalars().first() # 默认绑定第一个角色 - user_role_stmt = insert(user_role).values(AddUserRoleParam(user_id=new_user.id, role_id=role.id).model_dump()) + user_role_data = inject_tenant_dict(AddUserRoleParam(user_id=new_user.id, role_id=role.id).model_dump()) + user_role_stmt = insert(user_role).values(user_role_data) await db.execute(user_role_stmt) async def update(self, db: AsyncSession, user_id: int, obj: UpdateUserParam) -> int: @@ -192,7 +195,11 @@ class CRUDUser(CRUDPlus[User]): result = await db.execute(role_stmt) roles = result.scalars().all() - user_role_data = [AddUserRoleParam(user_id=user_id, role_id=role.id).model_dump() for role in roles] + user_role_data = [] + for role in roles: + role_dict = AddUserRoleParam(user_id=user_id, role_id=role.id).model_dump() + user_role_data.append(inject_tenant_dict(role_dict)) + user_role_stmt = insert(user_role) await db.execute(user_role_stmt, user_role_data) diff --git a/backend/app/admin/model/opera_log.py b/backend/app/admin/model/opera_log.py index d98cdd31..f257c42f 100644 --- a/backend/app/admin/model/opera_log.py +++ b/backend/app/admin/model/opera_log.py @@ -16,14 +16,14 @@ class OperaLog(DataClassBase, TenantMixin): id: Mapped[id_key] = mapped_column(init=False) trace_id: Mapped[str] = mapped_column(sa.String(32), comment='请求跟踪 ID') username: Mapped[str | None] = mapped_column(sa.String(64), comment='用户名') - method: Mapped[str] = mapped_column(sa.String(32), comment='请求类型') + method: Mapped[str] = mapped_column(sa.String(32), comment='请求方法') title: Mapped[str] = mapped_column(sa.String(256), comment='操作模块') path: Mapped[str] = mapped_column(sa.String(512), comment='请求路径') - ip: Mapped[str] = mapped_column(sa.String(64), comment='IP地址') + ip: Mapped[str] = mapped_column(sa.String(64), comment='IP 地址') country: Mapped[str | None] = mapped_column(sa.String(64), comment='国家') region: Mapped[str | None] = mapped_column(sa.String(64), comment='地区') city: Mapped[str | None] = mapped_column(sa.String(64), comment='城市') - user_agent: Mapped[str | None] = mapped_column(sa.String(512), comment='请求头') + user_agent: Mapped[str | None] = mapped_column(sa.String(512), comment='用户代理') os: Mapped[str | None] = mapped_column(sa.String(64), comment='操作系统') browser: Mapped[str | None] = mapped_column(sa.String(64), comment='浏览器') device: Mapped[str | None] = mapped_column(sa.String(64), comment='设备') diff --git a/backend/app/admin/schema/login_log.py b/backend/app/admin/schema/login_log.py index 7b829204..9fbbf25d 100644 --- a/backend/app/admin/schema/login_log.py +++ b/backend/app/admin/schema/login_log.py @@ -3,6 +3,7 @@ from datetime import datetime from pydantic import ConfigDict, Field from backend.common.schema import SchemaBase +from backend.core.conf import settings class LoginLogSchemaBase(SchemaBase): @@ -26,6 +27,9 @@ class LoginLogSchemaBase(SchemaBase): class CreateLoginLogParam(LoginLogSchemaBase): """创建登录日志参数""" + if settings.TENANT_ENABLED: + tenant_id: int = Field(description='租户 ID') + class UpdateLoginLogParam(LoginLogSchemaBase): """更新登录日志参数""" diff --git a/backend/app/admin/schema/opera_log.py b/backend/app/admin/schema/opera_log.py index 7ac1de32..e3989786 100644 --- a/backend/app/admin/schema/opera_log.py +++ b/backend/app/admin/schema/opera_log.py @@ -5,6 +5,7 @@ from pydantic import ConfigDict, Field from backend.common.enums import StatusType from backend.common.schema import SchemaBase +from backend.core.conf import settings class OperaLogSchemaBase(SchemaBase): @@ -34,6 +35,11 @@ class OperaLogSchemaBase(SchemaBase): class CreateOperaLogParam(OperaLogSchemaBase): """创建操作日志参数""" + if settings.TENANT_ENABLED: + tenant_id: int = Field(description='租户 ID') + else: + tenant_id: int = Field(settings.TENANT_DEFAULT_ID, description='租户 ID') + class UpdateOperaLogParam(OperaLogSchemaBase): """更新操作日志参数""" diff --git a/backend/app/admin/schema/user.py b/backend/app/admin/schema/user.py index 23638edf..efe51aa5 100644 --- a/backend/app/admin/schema/user.py +++ b/backend/app/admin/schema/user.py @@ -8,6 +8,7 @@ from backend.app.admin.schema.dept import GetDeptDetail from backend.app.admin.schema.role import GetRoleWithRelationDetail from backend.common.enums import StatusType from backend.common.schema import CustomEmailStr, CustomPhoneNumber, SchemaBase, ser_string +from backend.core.conf import settings class AuthSchemaBase(SchemaBase): @@ -22,7 +23,7 @@ class AuthLoginParam(AuthSchemaBase): uuid: str | None = Field(None, description='验证码 UUID') captcha: str | None = Field(None, description='验证码') - tenant_id: int | None = Field(None, description='租户 ID') + tenant_id: int = Field(settings.TENANT_DEFAULT_ID, description='租户 ID') class AddUserParam(AuthSchemaBase): @@ -90,7 +91,10 @@ class GetUserInfoDetail(UserInfoSchemaBase): join_time: datetime = Field(description='加入时间') last_login_time: datetime | None = Field(None, description='最后登录时间') dept_id: int | None = Field(None, description='部门 ID') - tenant_id: int | None = Field(None, description='租户 ID') + if settings.TENANT_ENABLED: + tenant_id: int = Field(description='租户 ID') + else: + tenant_id: int = Field(settings.TENANT_DEFAULT_ID, description='租户 ID') class GetUserInfoWithRelationDetail(GetUserInfoDetail): diff --git a/backend/app/admin/service/auth_service.py b/backend/app/admin/service/auth_service.py index 1b9b6996..5e32d976 100644 --- a/backend/app/admin/service/auth_service.py +++ b/backend/app/admin/service/auth_service.py @@ -111,6 +111,7 @@ class AuthService: raise errors.CustomError(error=CustomErrorCode.CAPTCHA_ERROR) await redis_client.delete(f'{settings.LOGIN_CAPTCHA_REDIS_PREFIX}:{obj.uuid}') + ctx.tenant_id = obj.tenant_id # 用于操作日志 await check_tenant_status(db, obj.tenant_id) user, days_remaining = await self.user_verify(db, obj.username, obj.password) await user_dao.update_login_time(db, obj.username) @@ -152,6 +153,7 @@ class AuthService: login_time=timezone.now(), status=LoginLogStatusType.fail.value, msg=e.msg, + tenant_id=obj.tenant_id, ) raise errors.RequestError(code=e.code, msg=e.msg, background=task) except Exception as e: @@ -165,6 +167,7 @@ class AuthService: login_time=timezone.now(), status=LoginLogStatusType.success.value, msg=t('success.login.success'), + tenant_id=obj.tenant_id, ) data = GetLoginToken( access_token=access_token_data.access_token, diff --git a/backend/app/admin/service/login_log_service.py b/backend/app/admin/service/login_log_service.py index 5aad1c66..c444b61f 100644 --- a/backend/app/admin/service/login_log_service.py +++ b/backend/app/admin/service/login_log_service.py @@ -8,6 +8,7 @@ from backend.app.admin.schema.login_log import CreateLoginLogParam, DeleteLoginL from backend.common.context import ctx from backend.common.log import log from backend.common.pagination import paging_data +from backend.core.conf import settings from backend.database.db import async_db_session @@ -36,6 +37,7 @@ class LoginLogService: login_time: datetime, status: int, msg: str, + tenant_id: int = settings.TENANT_DEFAULT_ID, ) -> None: """ 创建登录日志 @@ -45,10 +47,12 @@ class LoginLogService: :param login_time: 登录时间 :param status: 状态 :param msg: 消息 + :param tenant_id: 租户 ID :return: """ try: obj = CreateLoginLogParam( + tenant_id=tenant_id, user_uuid=user_uuid, username=username, status=status, diff --git a/backend/cli.py b/backend/cli.py index 511a2f1b..9d561822 100644 --- a/backend/cli.py +++ b/backend/cli.py @@ -43,7 +43,7 @@ from backend.database.db import ( create_database_url, ) from backend.database.redis import RedisCli, redis_client -from backend.plugin.core import get_plugin_destroy_sql, get_plugin_sql, get_plugins +from backend.plugin.core import build_sql_filename, get_plugin_destroy_sql, get_plugin_sql, get_plugins from backend.plugin.installer import install_git_plugin, install_zip_plugin, zip_plugin from backend.plugin.installer import remove_plugin as _remove_plugin from backend.plugin.requirements import uninstall_requirements_async @@ -444,23 +444,22 @@ async def remove_plugin(plugin: str | None, *, no_sql: bool = False) -> None: # async def get_sql_scripts() -> list[str]: """获取所有待执行的 SQL 脚本路径列表""" - sql_scripts = [] + sql_scripts: list[str] = [] db_script_dir = MYSQL_SCRIPT_DIR if DataBaseType.mysql == settings.DATABASE_TYPE else POSTGRESQL_SCRIPT_DIR - main_sql_file = ( - db_script_dir / 'init_test_data.sql' - if PrimaryKeyType.autoincrement == settings.DATABASE_PK_MODE - else db_script_dir / 'init_snowflake_test_data.sql' + main_sql_file = db_script_dir / build_sql_filename( + 'init', + settings.DATABASE_PK_MODE, + suffix='test_data', + tenant=settings.TENANT_ENABLED, ) - main_sql_path = anyio.Path(main_sql_file) - if await main_sql_path.exists(): + if await anyio.Path(main_sql_file).exists(): sql_scripts.append(str(main_sql_file)) - plugins = get_plugins() - for plugin in plugins: + for plugin in get_plugins(): plugin_sql = await get_plugin_sql(plugin, settings.DATABASE_TYPE, settings.DATABASE_PK_MODE) if plugin_sql: - sql_scripts.append(str(plugin_sql)) + sql_scripts.append(plugin_sql) return sql_scripts diff --git a/backend/common/context.py b/backend/common/context.py index 0b85cf9d..b3401b0f 100644 --- a/backend/common/context.py +++ b/backend/common/context.py @@ -22,7 +22,7 @@ class TypedContextProtocol(Protocol): language: str user_id: int | None - tenant_id: int | None + tenant_id: int class TypedContext(TypedContextProtocol, _Context): diff --git a/backend/common/security/jwt.py b/backend/common/security/jwt.py index f71089ae..5c1cfed0 100644 --- a/backend/common/security/jwt.py +++ b/backend/common/security/jwt.py @@ -198,14 +198,17 @@ async def check_tenant_status(db: AsyncSession, tenant_id: int) -> None: :param tenant_id: 租户 ID :return: """ - if not settings.TENANT_ENABLED or tenant_id is None or tenant_id == settings.TENANT_DEFAULT_ID: + if not settings.TENANT_ENABLED: + return + + if tenant_id == settings.TENANT_DEFAULT_ID: return try: from backend.plugin.tenant.crud.crud_package import tenant_package_dao from backend.plugin.tenant.crud.crud_tenant import tenant_dao except ImportError: - raise errors.ServerError(msg='租户插件用法导入失败,请联系系统管理员') + raise errors.ServerError(msg='租户插件方法导入失败,请联系系统管理员') tenant = await tenant_dao.get(db, tenant_id) if not tenant: diff --git a/backend/core/conf.py b/backend/core/conf.py index 674502f7..336d3861 100644 --- a/backend/core/conf.py +++ b/backend/core/conf.py @@ -248,6 +248,7 @@ class Settings(BaseSettings): # 租户 TENANT_ENABLED: bool = False + TENANT_DEFAULT_ID: int = 0 # Plugin 配置 PLUGIN_REQUIRED: list[str] = ['dict'] diff --git a/backend/middleware/opera_log_middleware.py b/backend/middleware/opera_log_middleware.py index d6784305..41dddbcb 100644 --- a/backend/middleware/opera_log_middleware.py +++ b/backend/middleware/opera_log_middleware.py @@ -115,6 +115,10 @@ class OperaLogMiddleware(BaseHTTPMiddleware): log.info(f'{ctx.ip: <15} | {method: <8} | {code!s: <6} | {path} | {elapsed:.3f}ms') if should_log_opera and request.method != 'OPTIONS': + tenant_id = settings.TENANT_DEFAULT_ID + if settings.TENANT_ENABLED: + tenant_id = ctx.tenant_id + opera_log_in = CreateOperaLogParam( trace_id=get_request_trace_id(), username=username, @@ -135,6 +139,7 @@ class OperaLogMiddleware(BaseHTTPMiddleware): msg=msg, cost_time=elapsed, opera_time=ctx.start_time, + tenant_id=tenant_id, ) await self.opera_log_queue.put(opera_log_in) diff --git a/backend/middleware/state_middleware.py b/backend/middleware/state_middleware.py index 852a01f8..0314e3aa 100644 --- a/backend/middleware/state_middleware.py +++ b/backend/middleware/state_middleware.py @@ -2,6 +2,7 @@ from fastapi import Request, Response from starlette.middleware.base import BaseHTTPMiddleware, RequestResponseEndpoint from backend.common.context import ctx +from backend.core.conf import settings from backend.utils.request_parse import parse_ip_info, parse_user_agent_info @@ -28,6 +29,9 @@ class StateMiddleware(BaseHTTPMiddleware): ctx.browser = ua_info.browser ctx.device = ua_info.device + # 为非授权接口设置默认租户 ID + ctx.tenant_id = settings.TENANT_DEFAULT_ID + response = await call_next(request) return response diff --git a/backend/plugin/core.py b/backend/plugin/core.py index f0f86379..4ce4a1af 100644 --- a/backend/plugin/core.py +++ b/backend/plugin/core.py @@ -76,6 +76,23 @@ def get_plugin_models() -> list[object]: return objs +def build_sql_filename( + prefix: str, + pk_type: PrimaryKeyType, + *, + suffix: str | None = None, + tenant: bool = False, +) -> str: + parts = [prefix] + if pk_type == PrimaryKeyType.snowflake: + parts.append('snowflake') + if suffix: + parts.append(suffix) + if tenant: + parts.append('tenant') + return f'{"_".join(parts)}.sql' + + async def get_plugin_sql(plugin: str, db_type: DataBaseType, pk_type: PrimaryKeyType) -> str | None: """ 获取插件 SQL 脚本 @@ -85,24 +102,19 @@ async def get_plugin_sql(plugin: str, db_type: DataBaseType, pk_type: PrimaryKey :param pk_type: 主键类型 :return: """ - if db_type == DataBaseType.mysql: - mysql_dir = PLUGIN_DIR / plugin / 'sql' / 'mysql' - sql_file = ( - mysql_dir / 'init.sql' if pk_type == PrimaryKeyType.autoincrement else mysql_dir / 'init_snowflake.sql' - ) - else: - postgresql_dir = PLUGIN_DIR / plugin / 'sql' / 'postgresql' - sql_file = ( - postgresql_dir / 'init.sql' - if pk_type == PrimaryKeyType.autoincrement - else postgresql_dir / 'init_snowflake.sql' - ) + sql_dir = PLUGIN_DIR / plugin / 'sql' / ('mysql' if db_type == DataBaseType.mysql else 'postgresql') + default_filename = build_sql_filename('init', pk_type) + if not settings.TENANT_ENABLED: + sql_file = sql_dir / default_filename + return str(sql_file) if await anyio.Path(sql_file).exists() else None - path = anyio.Path(sql_file) - if not await path.exists(): - return None + tenant_filename = build_sql_filename('init', pk_type, tenant=True) + tenant_sql_file = sql_dir / tenant_filename + if await anyio.Path(tenant_sql_file).exists(): + return str(tenant_sql_file) - return sql_file + default_sql_file = sql_dir / default_filename + return str(default_sql_file) if await anyio.Path(default_sql_file).exists() else None async def get_plugin_destroy_sql(plugin: str, db_type: DataBaseType, pk_type: PrimaryKeyType) -> str | None: @@ -114,26 +126,9 @@ async def get_plugin_destroy_sql(plugin: str, db_type: DataBaseType, pk_type: Pr :param pk_type: 主键类型 :return: """ - if db_type == DataBaseType.mysql: - mysql_dir = PLUGIN_DIR / plugin / 'sql' / 'mysql' - sql_file = ( - mysql_dir / 'destroy.sql' - if pk_type == PrimaryKeyType.autoincrement - else mysql_dir / 'destroy_snowflake.sql' - ) - else: - postgresql_dir = PLUGIN_DIR / plugin / 'sql' / 'postgresql' - sql_file = ( - postgresql_dir / 'destroy.sql' - if pk_type == PrimaryKeyType.autoincrement - else postgresql_dir / 'destroy_snowflake.sql' - ) - - path = anyio.Path(sql_file) - if not await path.exists(): - return None - - return sql_file + sql_dir = PLUGIN_DIR / plugin / 'sql' / ('mysql' if db_type == DataBaseType.mysql else 'postgresql') + sql_file = sql_dir / build_sql_filename('destroy', pk_type) + return str(sql_file) if await anyio.Path(sql_file).exists() else None def load_plugin_config(plugin: str) -> dict[str, Any]: diff --git a/backend/plugin/notice/sql/mysql/init_snowflake_tenant.sql b/backend/plugin/notice/sql/mysql/init_snowflake_tenant.sql new file mode 100644 index 00000000..7d0d1831 --- /dev/null +++ b/backend/plugin/notice/sql/mysql/init_snowflake_tenant.sql @@ -0,0 +1,27 @@ +insert into sys_menu (id, title, name, path, sort, icon, type, component, perms, status, display, cache, link, remark, parent_id, created_time, updated_time) +values (2049629108257816576, 'notice.menu', 'PluginNotice', '/plugins/notice', 9, 'fe:notice-push', 1, '/plugins/notice/views/index', null, 1, 1, 1, '', null, 2049629108245233667, now(), null); + +insert into sys_menu (id, title, name, path, sort, icon, type, component, perms, status, display, cache, link, remark, parent_id, created_time, updated_time) +values +(2049629108257816577, '新增', 'AddNotice', null, 0, null, 2, null, 'sys:notice:add', 1, 0, 1, '', null, 2049629108257816576, now(), null), +(2049629108257816578, '修改', 'EditNotice', null, 0, null, 2, null, 'sys:notice:edit', 1, 0, 1, '', null, 2049629108257816576, now(), null), +(2049629108257816579, '删除', 'DeleteNotice', null, 0, null, 2, null, 'sys:notice:del', 1, 0, 1, '', null, 2049629108257816576, now(), null); + +insert into sys_notice (id, title, type, status, content, created_time, updated_time) +values (2112248797756129280, 'hahahahahaahahaha', 0, 1, '你好😄 + +``` +print(''fba yyds'') +``` + +⚡⚡⚡ + +| col1 | col2 | col3 | +| ---- | ---- | ---- | +| | | | +| | | | + +* 1 +* 2 +* 3 +', '2025-12-15 15:33:16', null, 0); diff --git a/backend/plugin/notice/sql/mysql/init_tenant.sql b/backend/plugin/notice/sql/mysql/init_tenant.sql new file mode 100644 index 00000000..d9895f0e --- /dev/null +++ b/backend/plugin/notice/sql/mysql/init_tenant.sql @@ -0,0 +1,31 @@ +set @system_menu_id = (select id from sys_menu where name = 'System'); + +insert into sys_menu (title, name, path, sort, icon, type, component, perms, status, display, cache, link, remark, parent_id, created_time, updated_time) +values ('notice.menu', 'PluginNotice', '/plugins/notice', 9, 'fe:notice-push', 1, '/plugins/notice/views/index', null, 1, 1, 1, '', null, @system_menu_id, now(), null); + +set @notice_menu_id = LAST_INSERT_ID(); + +insert into sys_menu (title, name, path, sort, icon, type, component, perms, status, display, cache, link, remark, parent_id, created_time, updated_time) +values +('新增', 'AddNotice', null, 0, null, 2, null, 'sys:notice:add', 1, 0, 1, '', null, @notice_menu_id, now(), null), +('修改', 'EditNotice', null, 0, null, 2, null, 'sys:notice:edit', 1, 0, 1, '', null, @notice_menu_id, now(), null), +('删除', 'DeleteNotice', null, 0, null, 2, null, 'sys:notice:del', 1, 0, 1, '', null, @notice_menu_id, now(), null); + +insert into sys_notice (id, title, type, status, content, created_time, updated_time, tenant_id) +values (1, 'hahahahahaahahaha', 0, 1, '你好😄 + +``` +print(''fba yyds'') +``` + +⚡⚡⚡ + +| col1 | col2 | col3 | +| ---- | ---- | ---- | +| | | | +| | | | + +* 1 +* 2 +* 3 +', '2025-12-15 15:33:16', null, 0); diff --git a/backend/plugin/notice/sql/postgresql/init_snowflake_tenant.sql b/backend/plugin/notice/sql/postgresql/init_snowflake_tenant.sql new file mode 100644 index 00000000..7d0d1831 --- /dev/null +++ b/backend/plugin/notice/sql/postgresql/init_snowflake_tenant.sql @@ -0,0 +1,27 @@ +insert into sys_menu (id, title, name, path, sort, icon, type, component, perms, status, display, cache, link, remark, parent_id, created_time, updated_time) +values (2049629108257816576, 'notice.menu', 'PluginNotice', '/plugins/notice', 9, 'fe:notice-push', 1, '/plugins/notice/views/index', null, 1, 1, 1, '', null, 2049629108245233667, now(), null); + +insert into sys_menu (id, title, name, path, sort, icon, type, component, perms, status, display, cache, link, remark, parent_id, created_time, updated_time) +values +(2049629108257816577, '新增', 'AddNotice', null, 0, null, 2, null, 'sys:notice:add', 1, 0, 1, '', null, 2049629108257816576, now(), null), +(2049629108257816578, '修改', 'EditNotice', null, 0, null, 2, null, 'sys:notice:edit', 1, 0, 1, '', null, 2049629108257816576, now(), null), +(2049629108257816579, '删除', 'DeleteNotice', null, 0, null, 2, null, 'sys:notice:del', 1, 0, 1, '', null, 2049629108257816576, now(), null); + +insert into sys_notice (id, title, type, status, content, created_time, updated_time) +values (2112248797756129280, 'hahahahahaahahaha', 0, 1, '你好😄 + +``` +print(''fba yyds'') +``` + +⚡⚡⚡ + +| col1 | col2 | col3 | +| ---- | ---- | ---- | +| | | | +| | | | + +* 1 +* 2 +* 3 +', '2025-12-15 15:33:16', null, 0); diff --git a/backend/plugin/notice/sql/postgresql/init_tenant.sql b/backend/plugin/notice/sql/postgresql/init_tenant.sql new file mode 100644 index 00000000..b9bf1cea --- /dev/null +++ b/backend/plugin/notice/sql/postgresql/init_tenant.sql @@ -0,0 +1,37 @@ +do $$ +declare + notice_menu_id bigint; +begin + insert into sys_menu (title, name, path, sort, icon, type, component, perms, status, display, cache, link, remark, parent_id, created_time, updated_time) + values ('notice.menu', 'PluginNotice', '/plugins/notice', 9, 'fe:notice-push', 1, '/plugins/notice/views/index', null, 1, 1, 1, '', null, (select id from sys_menu where name = 'System'), now(), null) + returning id into notice_menu_id; + + insert into sys_menu (title, name, path, sort, icon, type, component, perms, status, display, cache, link, remark, parent_id, created_time, updated_time) + values + ('新增', 'AddNotice', null, 0, null, 2, null, 'sys:notice:add', 1, 0, 1, '', null, notice_menu_id, now(), null), + ('修改', 'EditNotice', null, 0, null, 2, null, 'sys:notice:edit', 1, 0, 1, '', null, notice_menu_id, now(), null), + ('删除', 'DeleteNotice', null, 0, null, 2, null, 'sys:notice:del', 1, 0, 1, '', null, notice_menu_id, now(), null); +end $$; + +select setval(pg_get_serial_sequence('sys_menu', 'id'), coalesce(max(id), 0) + 1, true) from sys_menu; + +insert into sys_notice (id, title, type, status, content, created_time, updated_time, tenant_id) +values (1, 'hahahahahaahahaha', 0, 1, '你好😄 + +``` +print(''fba yyds'') +``` + +⚡⚡⚡ + +| col1 | col2 | col3 | +| ---- | ---- | ---- | +| | | | +| | | | + +* 1 +* 2 +* 3 +', '2025-12-15 15:33:16', null, 0); + +select setval(pg_get_serial_sequence('sys_notice', 'id'),coalesce(max(id), 0) + 1, true) from sys_notice; diff --git a/backend/sql/mysql/init_snowflake_test_data_tenant.sql b/backend/sql/mysql/init_snowflake_test_data_tenant.sql new file mode 100644 index 00000000..ee00a8c5 --- /dev/null +++ b/backend/sql/mysql/init_snowflake_test_data_tenant.sql @@ -0,0 +1,109 @@ +insert into sys_dept (id, name, sort, leader, phone, email, status, del_flag, parent_id, created_time, updated_time, tenant_id) +values (2048601258595581952, '测试', 0, null, null, null, 1, false, null, now(), null, 0); + +insert into sys_menu (id, title, name, path, sort, icon, type, component, perms, status, display, cache, link, remark, parent_id, created_time, updated_time) +values +(2049629108245233664, 'page.dashboard.title', 'Dashboard', '/dashboard', 0, 'ant-design:dashboard-outlined', 0, null, null, 1, 1, 1, '', null, null, '2025-06-26 20:29:06', null), +(2049629108245233665, 'page.dashboard.analytics', 'Analytics', '/analytics', 0, 'lucide:area-chart', 1, '/dashboard/analytics/index', null, 1, 1, 1, '', null, 2049629108245233664, '2025-06-26 20:29:06', null), +(2049629108245233666, 'page.dashboard.workspace', 'Workspace', '/workspace', 1, 'carbon:workspace', 1, '/dashboard/workspace/index', null, 1, 1, 1, '', null, 2049629108245233664, '2025-06-26 20:29:06', null), +(2049629108245233667, 'page.menu.system', 'System', '/system', 1, 'eos-icons:admin', 0, null, null, 1, 1, 1, '', null, null, '2025-06-26 20:29:06', null), +(2049629108245233668, 'page.menu.sysDept', 'SysDept', '/system/dept', 1, 'mingcute:department-line', 1, '/system/dept/index', null, 1, 1, 1, '', null, 2049629108245233667, '2025-06-26 20:29:06', null), +(2049629108245233669, '新增', 'AddSysDept', null, 0, null, 2, null, 'sys:dept:add', 1, 0, 1, '', null, 2049629108245233668, '2025-06-26 20:29:06', null), +(2049629108245233670, '修改', 'EditSysDept', null, 0, null, 2, null, 'sys:dept:edit', 1, 0, 1, '', null, 2049629108245233668, '2025-06-26 20:29:06', null), +(2049629108245233671, '删除', 'DeleteSysDept', null, 0, null, 2, null, 'sys:dept:del', 1, 0, 1, '', null, 2049629108245233668, '2025-06-26 20:29:06', null), +(2049629108245233672, 'page.menu.sysUser', 'SysUser', '/system/user', 2, 'ant-design:user-outlined', 1, '/system/user/index', null, 1, 1, 1, '', null, 2049629108245233667, '2025-06-26 20:29:06', null), +(2049629108245233673, '删除', 'DeleteSysUser', null, 0, null, 2, null, 'sys:user:del', 1, 0, 1, '', null, 2049629108245233672, '2025-06-26 20:29:06', null), +(2049629108245233674, 'page.menu.sysRole', 'SysRole', '/system/role', 3, 'carbon:user-role', 1, '/system/role/index', null, 1, 1, 1, '', null, 2049629108245233667, '2025-06-26 20:29:06', null), +(2049629108245233675, '新增', 'AddSysRole', null, 0, null, 2, null, 'sys:role:add', 1, 0, 1, '', null, 2049629108245233674, '2025-06-26 20:29:06', null), +(2049629108245233676, '修改', 'EditSysRole', null, 0, null, 2, null, 'sys:role:edit', 1, 0, 1, '', null, 2049629108245233674, '2025-06-26 20:29:06', null), +(2049629108245233677, '修改角色菜单', 'EditSysRoleMenu', null, 0, null, 2, null, 'sys:role:menu:edit', 1, 0, 1, '', null, 2049629108245233674, '2025-06-26 20:29:06', null), +(2049629108245233678, '修改角色数据范围', 'EditSysRoleScope', null, 0, null, 2, null, 'sys:role:scope:edit', 1, 0, 1, '', null, 2049629108245233674, '2025-06-26 20:29:06', null), +(2049629108245233679, '删除', 'DeleteSysRole', null, 0, null, 2, null, 'sys:role:del', 1, 0, 1, '', null, 2049629108245233674, '2025-06-26 20:29:06', null), +(2049629108245233680, 'page.menu.sysMenu', 'SysMenu', '/system/menu', 4, 'ant-design:menu-outlined', 1, '/system/menu/index', null, 1, 1, 1, '', null, 2049629108245233667, '2025-06-26 20:29:06', null), +(2049629108245233681, '新增', 'AddSysMenu', null, 0, null, 2, null, 'sys:menu:add', 1, 0, 1, '', null, 2049629108245233680, '2025-06-26 20:29:06', null), +(2049629108245233682, '修改', 'EditSysMenu', null, 0, null, 2, null, 'sys:menu:edit', 1, 0, 1, '', null, 2049629108245233680, '2025-06-26 20:29:06', null), +(2049629108249427968, '删除', 'DeleteSysMenu', null, 0, null, 2, null, 'sys:menu:del', 1, 0, 1, '', null, 2049629108245233680, '2025-06-26 20:29:06', null), +(2049629108249427969, 'page.menu.sysDataPermission', 'SysDataPermission', '/system/data-permission', 5, 'icon-park-outline:permissions', 0, null, null, 1, 1, 1, '', null, 2049629108245233667, '2025-06-26 20:29:06', null), +(2049629108249427970, 'page.menu.sysDataScope', 'SysDataScope', '/system/data-scope', 6, 'cuida:scope-outline', 1, '/system/data-permission/scope/index', null, 1, 1, 1, '', null, 2049629108249427969, '2025-06-26 20:29:06', '2025-06-26 20:37:26'), +(2049629108249427971, '新增', 'AddSysDataScope', null, 0, null, 2, null, 'data:scope:add', 1, 0, 1, '', null, 2049629108249427970, '2025-06-26 20:29:06', null), +(2049629108249427972, '修改', 'EditSysDataScope', null, 0, null, 2, null, 'data:scope:edit', 1, 0, 1, '', null, 2049629108249427970, '2025-06-26 20:29:06', null), +(2049629108249427973, '修改数据范围规则', 'EditDataScopeRule', null, 0, null, 2, null, 'data:scope:rule:edit', 1, 0, 1, '', null, 2049629108249427970, '2025-06-26 20:29:06', null), +(2049629108249427974, '删除', 'DeleteSysDataScope', null, 0, null, 2, null, 'data:scope:del', 1, 0, 1, '', null, 2049629108249427970, '2025-06-26 20:29:06', null), +(2049629108249427975, 'page.menu.sysDataRule', 'SysDataRule', '/system/data-rule', 7, 'material-symbols:rule', 1, '/system/data-permission/rule/index', null, 1, 1, 1, '', null, 2049629108249427969, '2025-06-26 20:29:06', '2025-06-26 20:37:40'), +(2049629108249427976, '新增', 'AddSysDataRule', null, 0, null, 2, null, 'data:rule:add', 1, 0, 1, '', null, 2049629108249427975, '2025-06-26 20:29:06', null), +(2049629108249427977, '修改', 'EditSysDataRule', null, 0, null, 2, null, 'data:rule:edit', 1, 0, 1, '', null, 2049629108249427975, '2025-06-26 20:29:06', null), +(2049629108249427978, '删除', 'DeleteSysDataRule', null, 0, null, 2, null, 'data:rule:del', 1, 0, 1, '', null, 2049629108249427975, '2025-06-26 20:29:06', null), +(2049629108249427979, 'page.menu.sysPlugin', 'SysPlugin', '/system/plugin', 8, 'clarity:plugin-line', 1, '/system/plugin/index', null, 1, 1, 1, '', null, 2049629108245233667, '2025-06-26 20:29:06', null), +(2049629108249427980, '安装', 'InstallSysPlugin', null, 0, null, 2, null, 'sys:plugin:install', 1, 0, 1, '', null, 2049629108249427979, '2025-06-26 20:29:06', null), +(2049629108249427981, '卸载', 'UninstallSysPlugin', null, 0, null, 2, null, 'sys:plugin:uninstall', 1, 0, 1, '', null, 2049629108249427979, '2025-06-26 20:29:06', null), +(2049629108249427982, '修改', 'EditSysPlugin', null, 0, null, 2, null, 'sys:plugin:edit', 1, 0, 1, '', null, 2049629108249427979, '2025-06-26 20:29:06', null), +(2049629108249427983, 'page.menu.scheduler', 'Scheduler', '/scheduler', 2, 'material-symbols:automation', 0, null, null, 1, 1, 1, '', null, null, '2025-06-26 20:29:06', null), +(2049629108249427984, 'page.menu.schedulerManage', 'SchedulerManage', '/scheduler/manage', 1, 'ix:scheduler', 1, '/scheduler/manage/index', null, 1, 1, 1, '', null, 2049629108249427983, '2025-06-26 20:29:06', null), +(2049629108249427985, 'page.menu.schedulerRecord', 'SchedulerRecord', '/scheduler/record', 2, 'ix:scheduler', 1, '/scheduler/record/index', null, 1, 1, 1, '', null, 2049629108249427983, '2025-06-26 20:29:06', null), +(2049629108249427986, 'page.menu.log', 'Log', '/log', 3, 'carbon:cloud-logging', 0, null, null, 1, 1, 1, '', null, null, '2025-06-26 20:29:06', null), +(2049629108249427987, 'page.menu.login', 'LoginLog', '/log/login', 1, 'mdi:login', 1, '/log/login/index', null, 1, 1, 1, '', null, 2049629108249427986, '2025-06-26 20:29:06', null), +(2049629108249427988, '删除', 'DeleteLoginLog', null, 0, null, 2, null, 'log:login:del', 1, 0, 1, '', null, 2049629108249427987, '2025-06-26 20:29:06', null), +(2049629108249427989, '清空', 'EmptyLoginLog', null, 0, null, 2, null, 'log:login:clear', 1, 0, 1, '', null, 2049629108249427987, '2025-06-26 20:29:06', null), +(2049629108249427990, 'page.menu.opera', 'OperaLog', '/log/opera', 2, 'carbon:operations-record', 1, '/log/opera/index', null, 1, 1, 1, '', null, 2049629108249427986, '2025-06-26 20:29:06', null), +(2049629108249427991, '删除', 'DeleteOperaLog', null, 0, null, 2, null, 'log:opera:del', 1, 0, 1, '', null, 2049629108249427990, '2025-06-26 20:29:06', null), +(2049629108253622272, '清空', 'EmptyOperaLog', null, 0, null, 2, null, 'log:opera:clear', 1, 0, 1, '', null, 2049629108249427990, '2025-06-26 20:29:06', null), +(2049629108253622273, 'page.menu.monitor', 'Monitor', '/monitor', 4, 'mdi:monitor-eye', 0, null, null, 1, 1, 1, '', null, null, '2025-06-26 20:29:06', null), +(2049629108253622274, 'page.menu.online', 'Online', '/log/online', 1, 'wpf:online', 1, '/monitor/online/index', null, 1, 1, 1, '', null, 2049629108253622273, '2025-06-26 20:29:06', null), +(2049629108253622276, 'page.menu.redis', 'Redis', '/monitor/redis', 2, 'devicon:redis', 1, '/monitor/redis/index', null, 1, 1, 1, '', null, 2049629108253622273, '2025-06-26 20:29:06', null), +(2049629108253622277, 'page.menu.server', 'Server', '/monitor/server', 3, 'mdi:server-outline', 1, '/monitor/server/index', null, 1, 1, 1, '', null, 2049629108253622273, '2025-06-26 20:29:06', null), +(2049629108253622278, '项目', 'Project', '/fba', 5, 'https://wu-clan.github.io/picx-images-hosting/logo/fba.png', 0, null, null, 1, 1, 1, '', null, null, '2025-06-26 20:29:06', null), +(2049629108253622279, '文档', 'Document', '/fba/document', 1, 'lucide:book-open-text', 4, '/_core/fallback/iframe.vue', null, 1, 1, 1, 'https://fastapi-practices.github.io/fastapi_best_architecture_docs', null, 2049629108253622278, '2025-06-26 20:29:06', null), +(2049629108253622280, 'Github', 'Github', '/fba/github', 2, 'ant-design:github-filled', 4, '/_core/fallback/iframe.vue', null, 1, 1, 1, 'https://github.com/fastapi-practices/fastapi-best-architecture', null, 2049629108253622278, '2025-06-26 20:29:06', null), +(2049629108253622281, 'Apifox', 'Apifox', '/fba/apifox', 3, 'simple-icons:apifox', 3, '/_core/fallback/iframe.vue', null, 1, 1, 1, 'https://apifox.com/apidoc/shared-28a93f02-730b-4f33-bb5e-4dad92058cc0', null, 2049629108253622278, '2025-06-26 20:29:06', null), +(2049629108253622282, 'page.menu.profile', 'Profile', '/profile', 6, 'ant-design:profile-outlined', 1, '/_core/profile/index', null, 1, 0, 1, '', null, null, '2025-06-26 20:29:06', null); + +insert into sys_role (id, name, status, is_filter_scopes, remark, created_time, updated_time, tenant_id) +values (2048601263515500544, '测试', 1, true, null, now(), null, 0); + +insert into sys_role_menu (id, role_id, menu_id, tenant_id) +values +(2048601263578415104, 2048601263515500544, 2049629108245233664, 0), +(2048601263641329664, 2048601263515500544, 2049629108245233665, 0), +(2048601263708438528, 2048601263515500544, 2049629108245233666, 0), +(2048601263775547392, 2048601263515500544, 2049629108253622282, 0); + +insert into sys_user (id, uuid, username, nickname, password, salt, email, status, is_superuser, is_staff, is_multi_login, avatar, phone, join_time, last_login_time, last_password_changed_time, dept_id, created_time, updated_time, tenant_id) +values +(2048601263834267648, uuid(), 'admin', '用户88888', '$2b$12$8y2eNucX19VjmZ3tYhBLcOsBwy9w1IjBQE4SSqwMDL5bGQVp2wqS.', unhex('24326224313224387932654E7563583139566A6D5A33745968424C634F'), 'admin@example.com', 1, true, true, true, null, null, now(), now(), now(), 2048601258595581952, now(), null, 0), +(2049946297615646720, uuid(), 'test', '用户66666', '$2b$12$BMiXsNQAgTx7aNc7kVgnwedXGyUxPEHRnJMFbiikbqHgVoT3y14Za', unhex('24326224313224424D6958734E514167547837614E63376B56676E7765'), 'test@example.com', 1, false, false, false, null, null, now(), now(), now(), 2048601258595581952, now(), null, 0); + +insert into sys_user_role (id, user_id, role_id, tenant_id) +values +(2048601263838461952, 2048601263834267648, 2048601263515500544, 0), +(2049946493732913152, 2049946297615646720, 2048601263515500544, 0); + +insert into sys_data_scope (id, name, status, created_time, updated_time) +values +(2048601263901376512, '本部门数据权限', 1, now(), null), +(2048601263968485376, '部门及以下数据权限', 1, now(), null), +(2048601263968485377, '仅本人数据权限', 1, now(), null), +(2048601263968485378, '全模型本部门数据权限', 1, now(), null), +(2048601263968485379, '排除超级管理员数据权限', 1, now(), null); + +insert into sys_data_rule (id, name, model, `column`, operator, expression, `value`, created_time, updated_time) +values +(2048601264035594240, '部门 ID 等于当前用户部门', 'Dept', '__dept_id__', 0, 0, '${dept_id}', now(), null), +(2048601264102703104, '部门名称等于测试', 'Dept', 'name', 1, 0, '测试', now(), null), +(2048601264102703105, '父部门 ID 等于测试部门 ID', 'Dept', 'parent_id', 0, 0, '1', now(), null), +(2048601264102703106, '创建者等于当前用户', '__ALL__', '__created_by__', 0, 0, '${user_id}', now(), null), +(2048601264102703107, '全模型部门 ID 等于当前用户部门', '__ALL__', '__dept_id__', 0, 0, '${dept_id}', now(), null), +(2048601264102703109, '用户非超级管理员', 'User', 'is_superuser', 0, 1, '1', now(), null); + +insert into sys_role_data_scope (id, role_id, data_scope_id, tenant_id) +values +(2048601264169811968, 2048601263515500544, 2048601263901376512, 0), +(2048601264236920832, 2048601263515500544, 2048601263968485376, 0); + +insert into sys_data_scope_rule (id, data_scope_id, data_rule_id) +values +(2048601264169811968, 2048601263901376512, 2048601264035594240), +(2048601264236920832, 2048601263968485376, 2048601264102703104), +(2048601264299835392, 2048601263968485376, 2048601264102703105), +(2048601264299835393, 2048601263968485377, 2048601264102703106), +(2048601264299835394, 2048601263968485378, 2048601264102703107), +(2048601264299835395, 2048601263968485379, 2048601264102703109); diff --git a/backend/sql/mysql/init_test_data_tenant.sql b/backend/sql/mysql/init_test_data_tenant.sql new file mode 100644 index 00000000..a791509f --- /dev/null +++ b/backend/sql/mysql/init_test_data_tenant.sql @@ -0,0 +1,109 @@ +insert into sys_dept (id, name, sort, leader, phone, email, status, del_flag, parent_id, created_time, updated_time, tenant_id) +values (1, '测试', 0, null, null, null, 1, false, null, now(), null, 0); + +insert into sys_menu (id, title, name, path, sort, icon, type, component, perms, status, display, cache, link, remark, parent_id, created_time, updated_time) +values +(1, 'page.dashboard.title', 'Dashboard', '/dashboard', 0, 'ant-design:dashboard-outlined', 0, null, null, 1, 1, 1, '', null, null, '2025-06-26 20:29:06', null), +(2, 'page.dashboard.analytics', 'Analytics', '/analytics', 0, 'lucide:area-chart', 1, '/dashboard/analytics/index', null, 1, 1, 1, '', null, 1, '2025-06-26 20:29:06', null), +(3, 'page.dashboard.workspace', 'Workspace', '/workspace', 1, 'carbon:workspace', 1, '/dashboard/workspace/index', null, 1, 1, 1, '', null, 1, '2025-06-26 20:29:06', null), +(4, 'page.menu.system', 'System', '/system', 1, 'eos-icons:admin', 0, null, null, 1, 1, 1, '', null, null, '2025-06-26 20:29:06', null), +(5, 'page.menu.sysDept', 'SysDept', '/system/dept', 1, 'mingcute:department-line', 1, '/system/dept/index', null, 1, 1, 1, '', null, 4, '2025-06-26 20:29:06', null), +(6, '新增', 'AddSysDept', null, 0, null, 2, null, 'sys:dept:add', 1, 0, 1, '', null, 5, '2025-06-26 20:29:06', null), +(7, '修改', 'EditSysDept', null, 0, null, 2, null, 'sys:dept:edit', 1, 0, 1, '', null, 5, '2025-06-26 20:29:06', null), +(8, '删除', 'DeleteSysDept', null, 0, null, 2, null, 'sys:dept:del', 1, 0, 1, '', null, 5, '2025-06-26 20:29:06', null), +(9, 'page.menu.sysUser', 'SysUser', '/system/user', 2, 'ant-design:user-outlined', 1, '/system/user/index', null, 1, 1, 1, '', null, 4, '2025-06-26 20:29:06', null), +(10, '删除', 'DeleteSysUser', null, 0, null, 2, null, 'sys:user:del', 1, 0, 1, '', null, 9, '2025-06-26 20:29:06', null), +(11, 'page.menu.sysRole', 'SysRole', '/system/role', 3, 'carbon:user-role', 1, '/system/role/index', null, 1, 1, 1, '', null, 4, '2025-06-26 20:29:06', null), +(12, '新增', 'AddSysRole', null, 0, null, 2, null, 'sys:role:add', 1, 0, 1, '', null, 11, '2025-06-26 20:29:06', null), +(13, '修改', 'EditSysRole', null, 0, null, 2, null, 'sys:role:edit', 1, 0, 1, '', null, 11, '2025-06-26 20:29:06', null), +(14, '修改角色菜单', 'EditSysRoleMenu', null, 0, null, 2, null, 'sys:role:menu:edit', 1, 0, 1, '', null, 11, '2025-06-26 20:29:06', null), +(15, '修改角色数据范围', 'EditSysRoleScope', null, 0, null, 2, null, 'sys:role:scope:edit', 1, 0, 1, '', null, 11, '2025-06-26 20:29:06', null), +(16, '删除', 'DeleteSysRole', null, 0, null, 2, null, 'sys:role:del', 1, 0, 1, '', null, 11, '2025-06-26 20:29:06', null), +(17, 'page.menu.sysMenu', 'SysMenu', '/system/menu', 4, 'ant-design:menu-outlined', 1, '/system/menu/index', null, 1, 1, 1, '', null, 4, '2025-06-26 20:29:06', null), +(18, '新增', 'AddSysMenu', null, 0, null, 2, null, 'sys:menu:add', 1, 0, 1, '', null, 17, '2025-06-26 20:29:06', null), +(19, '修改', 'EditSysMenu', null, 0, null, 2, null, 'sys:menu:edit', 1, 0, 1, '', null, 17, '2025-06-26 20:29:06', null), +(20, '删除', 'DeleteSysMenu', null, 0, null, 2, null, 'sys:menu:del', 1, 0, 1, '', null, 17, '2025-06-26 20:29:06', null), +(21, 'page.menu.sysDataPermission', 'SysDataPermission', '/system/data-permission', 5, 'icon-park-outline:permissions', 0, null, null, 1, 1, 1, '', null, 4, '2025-06-26 20:29:06', null), +(22, 'page.menu.sysDataScope', 'SysDataScope', '/system/data-scope', 6, 'cuida:scope-outline', 1, '/system/data-permission/scope/index', null, 1, 1, 1, '', null, 21, '2025-06-26 20:29:06', '2025-06-26 20:37:26'), +(23, '新增', 'AddSysDataScope', null, 0, null, 2, null, 'data:scope:add', 1, 0, 1, '', null, 22, '2025-06-26 20:29:06', null), +(24, '修改', 'EditSysDataScope', null, 0, null, 2, null, 'data:scope:edit', 1, 0, 1, '', null, 22, '2025-06-26 20:29:06', null), +(25, '修改数据范围规则', 'EditDataScopeRule', null, 0, null, 2, null, 'data:scope:rule:edit', 1, 0, 1, '', null, 22, '2025-06-26 20:29:06', null), +(26, '删除', 'DeleteSysDataScope', null, 0, null, 2, null, 'data:scope:del', 1, 0, 1, '', null, 22, '2025-06-26 20:29:06', null), +(27, 'page.menu.sysDataRule', 'SysDataRule', '/system/data-rule', 7, 'material-symbols:rule', 1, '/system/data-permission/rule/index', null, 1, 1, 1, '', null, 21, '2025-06-26 20:29:06', '2025-06-26 20:37:40'), +(28, '新增', 'AddSysDataRule', null, 0, null, 2, null, 'data:rule:add', 1, 0, 1, '', null, 27, '2025-06-26 20:29:06', null), +(29, '修改', 'EditSysDataRule', null, 0, null, 2, null, 'data:rule:edit', 1, 0, 1, '', null, 27, '2025-06-26 20:29:06', null), +(30, '删除', 'DeleteSysDataRule', null, 0, null, 2, null, 'data:rule:del', 1, 0, 1, '', null, 27, '2025-06-26 20:29:06', null), +(31, 'page.menu.sysPlugin', 'SysPlugin', '/system/plugin', 8, 'clarity:plugin-line', 1, '/system/plugin/index', null, 1, 1, 1, '', null, 4, '2025-06-26 20:29:06', null), +(32, '安装', 'InstallSysPlugin', null, 0, null, 2, null, 'sys:plugin:install', 1, 0, 1, '', null, 31, '2025-06-26 20:29:06', null), +(33, '卸载', 'UninstallSysPlugin', null, 0, null, 2, null, 'sys:plugin:uninstall', 1, 0, 1, '', null, 31, '2025-06-26 20:29:06', null), +(34, '修改', 'EditSysPlugin', null, 0, null, 2, null, 'sys:plugin:edit', 1, 0, 1, '', null, 31, '2025-06-26 20:29:06', null), +(35, 'page.menu.scheduler', 'Scheduler', '/scheduler', 2, 'material-symbols:automation', 0, null, null, 1, 1, 1, '', null, null, '2025-06-26 20:29:06', null), +(36, 'page.menu.schedulerManage', 'SchedulerManage', '/scheduler/manage', 1, 'ix:scheduler', 1, '/scheduler/manage/index', null, 1, 1, 1, '', null, 35, '2025-06-26 20:29:06', null), +(37, 'page.menu.schedulerRecord', 'SchedulerRecord', '/scheduler/record', 2, 'ix:scheduler', 1, '/scheduler/record/index', null, 1, 1, 1, '', null, 35, '2025-06-26 20:29:06', null), +(38, 'page.menu.log', 'Log', '/log', 3, 'carbon:cloud-logging', 0, null, null, 1, 1, 1, '', null, null, '2025-06-26 20:29:06', null), +(39, 'page.menu.login', 'LoginLog', '/log/login', 1, 'mdi:login', 1, '/log/login/index', null, 1, 1, 1, '', null, 38, '2025-06-26 20:29:06', null), +(40, '删除', 'DeleteLoginLog', null, 0, null, 2, null, 'log:login:del', 1, 0, 1, '', null, 39, '2025-06-26 20:29:06', null), +(41, '清空', 'EmptyLoginLog', null, 0, null, 2, null, 'log:login:clear', 1, 0, 1, '', null, 39, '2025-06-26 20:29:06', null), +(42, 'page.menu.opera', 'OperaLog', '/log/opera', 2, 'carbon:operations-record', 1, '/log/opera/index', null, 1, 1, 1, '', null, 38, '2025-06-26 20:29:06', null), +(43, '删除', 'DeleteOperaLog', null, 0, null, 2, null, 'log:opera:del', 1, 0, 1, '', null, 42, '2025-06-26 20:29:06', null), +(44, '清空', 'EmptyOperaLog', null, 0, null, 2, null, 'log:opera:clear', 1, 0, 1, '', null, 42, '2025-06-26 20:29:06', null), +(45, 'page.menu.monitor', 'Monitor', '/monitor', 4, 'mdi:monitor-eye', 0, null, null, 1, 1, 1, '', null, null, '2025-06-26 20:29:06', null), +(46, 'page.menu.online', 'Online', '/log/online', 1, 'wpf:online', 1, '/monitor/online/index', null, 1, 1, 1, '', null, 45, '2025-06-26 20:29:06', null), +(47, 'page.menu.redis', 'Redis', '/monitor/redis', 2, 'devicon:redis', 1, '/monitor/redis/index', null, 1, 1, 1, '', null, 45, '2025-06-26 20:29:06', null), +(48, 'page.menu.server', 'Server', '/monitor/server', 3, 'mdi:server-outline', 1, '/monitor/server/index', null, 1, 1, 1, '', null, 45, '2025-06-26 20:29:06', null), +(49, '项目', 'Project', '/fba', 5, 'https://wu-clan.github.io/picx-images-hosting/logo/fba.png', 0, null, null, 1, 1, 1, '', null, null, '2025-06-26 20:29:06', null), +(50, '文档', 'Document', '/fba/document', 1, 'lucide:book-open-text', 4, '/_core/fallback/iframe.vue', null, 1, 1, 1, 'https://fastapi-practices.github.io/fastapi_best_architecture_docs', null, 49, '2025-06-26 20:29:06', null), +(51, 'Github', 'Github', '/fba/github', 2, 'ant-design:github-filled', 4, '/_core/fallback/iframe.vue', null, 1, 1, 1, 'https://github.com/fastapi-practices/fastapi-best-architecture', null, 49, '2025-06-26 20:29:06', null), +(52, 'Apifox', 'Apifox', '/fba/apifox', 3, 'simple-icons:apifox', 3, '/_core/fallback/iframe.vue', null, 1, 1, 1, 'https://apifox.com/apidoc/shared-28a93f02-730b-4f33-bb5e-4dad92058cc0', null, 49, '2025-06-26 20:29:06', null), +(53, 'page.menu.profile', 'Profile', '/profile', 6, 'ant-design:profile-outlined', 1, '/_core/profile/index', null, 1, 0, 1, '', null, null, '2025-06-26 20:29:06', null); + +insert into sys_role (id, name, status, is_filter_scopes, remark, created_time, updated_time, tenant_id) +values (1, '测试', 1, true, null, now(), null, 0); + +insert into sys_role_menu (id, role_id, menu_id, tenant_id) +values +(1, 1, 1, 0), +(2, 1, 2, 0), +(3, 1, 3, 0), +(4, 1, 53, 0); + +insert into sys_user (id, uuid, username, nickname, password, salt, email, status, is_superuser, is_staff, is_multi_login, avatar, phone, join_time, last_login_time, last_password_changed_time, dept_id, created_time, updated_time, tenant_id) +values +(1, uuid(), 'admin', '用户88888', '$2b$12$8y2eNucX19VjmZ3tYhBLcOsBwy9w1IjBQE4SSqwMDL5bGQVp2wqS.', unhex('24326224313224387932654E7563583139566A6D5A33745968424C634F'), 'admin@example.com', 1, true, true, true, null, null, now(), now(), now(), 1, now(), null, 0), +(2, uuid(), 'test', '用户66666', '$2b$12$BMiXsNQAgTx7aNc7kVgnwedXGyUxPEHRnJMFbiikbqHgVoT3y14Za', unhex('24326224313224424D6958734E514167547837614E63376B56676E7765'), 'test@example.com', 1, false, false, false, null, null, now(), now(), now(), 1, now(), null, 0); + +insert into sys_user_role (id, user_id, role_id, tenant_id) +values +(1, 1, 1, 0), +(2, 2, 1, 0); + +insert into sys_data_scope (id, name, status, created_time, updated_time) +values +(1, '本部门数据权限', 1, now(), null), +(2, '部门及以下数据权限', 1, now(), null), +(3, '仅本人数据权限', 1, now(), null), +(4, '全模型本部门数据权限', 1, now(), null), +(5, '排除超级管理员数据权限', 1, now(), null); + +insert into sys_data_rule (id, name, model, `column`, operator, expression, `value`, created_time, updated_time) +values +(1, '部门 ID 等于当前用户部门', 'Dept', '__dept_id__', 0, 0, '${dept_id}', now(), null), +(2, '部门名称等于测试', 'Dept', 'name', 1, 0, '测试', now(), null), +(3, '父部门 ID 等于测试部门 ID', 'Dept', 'parent_id', 0, 0, '1', now(), null), +(4, '创建者等于当前用户', '__ALL__', '__created_by__', 0, 0, '${user_id}', now(), null), +(5, '全模型部门 ID 等于当前用户部门', '__ALL__', '__dept_id__', 0, 0, '${dept_id}', now(), null), +(6, '用户非超级管理员', 'User', 'is_superuser', 0, 1, '1', now(), null); + +insert into sys_role_data_scope (id, role_id, data_scope_id, tenant_id) +values +(1, 1, 1, 0), +(2, 1, 2, 0); + +insert into sys_data_scope_rule (id, data_scope_id, data_rule_id) +values +(1, 1, 1), +(2, 2, 2), +(3, 2, 3), +(4, 3, 4), +(5, 4, 5), +(6, 5, 6); diff --git a/backend/sql/postgresql/init_snowflake_test_data_tenant.sql b/backend/sql/postgresql/init_snowflake_test_data_tenant.sql new file mode 100644 index 00000000..3029d422 --- /dev/null +++ b/backend/sql/postgresql/init_snowflake_test_data_tenant.sql @@ -0,0 +1,109 @@ +insert into sys_dept (id, name, sort, leader, phone, email, status, del_flag, parent_id, created_time, updated_time, tenant_id) +values (2048601264366944256, '测试', 0, null, null, null, 1, false, null, now(), null, 0); + +insert into sys_menu (id, title, name, path, sort, icon, type, component, perms, status, display, cache, link, remark, parent_id, created_time, updated_time) +values +(2049629108245233664, 'page.dashboard.title', 'Dashboard', '/dashboard', 0, 'ant-design:dashboard-outlined', 0, null, null, 1, 1, 1, '', null, null, '2025-06-26 20:29:06', null), +(2049629108245233665, 'page.dashboard.analytics', 'Analytics', '/analytics', 0, 'lucide:area-chart', 1, '/dashboard/analytics/index', null, 1, 1, 1, '', null, 2049629108245233664, '2025-06-26 20:29:06', null), +(2049629108245233666, 'page.dashboard.workspace', 'Workspace', '/workspace', 1, 'carbon:workspace', 1, '/dashboard/workspace/index', null, 1, 1, 1, '', null, 2049629108245233664, '2025-06-26 20:29:06', null), +(2049629108245233667, 'page.menu.system', 'System', '/system', 1, 'eos-icons:admin', 0, null, null, 1, 1, 1, '', null, null, '2025-06-26 20:29:06', null), +(2049629108245233668, 'page.menu.sysDept', 'SysDept', '/system/dept', 1, 'mingcute:department-line', 1, '/system/dept/index', null, 1, 1, 1, '', null, 2049629108245233667, '2025-06-26 20:29:06', null), +(2049629108245233669, '新增', 'AddSysDept', null, 0, null, 2, null, 'sys:dept:add', 1, 0, 1, '', null, 2049629108245233668, '2025-06-26 20:29:06', null), +(2049629108245233670, '修改', 'EditSysDept', null, 0, null, 2, null, 'sys:dept:edit', 1, 0, 1, '', null, 2049629108245233668, '2025-06-26 20:29:06', null), +(2049629108245233671, '删除', 'DeleteSysDept', null, 0, null, 2, null, 'sys:dept:del', 1, 0, 1, '', null, 2049629108245233668, '2025-06-26 20:29:06', null), +(2049629108245233672, 'page.menu.sysUser', 'SysUser', '/system/user', 2, 'ant-design:user-outlined', 1, '/system/user/index', null, 1, 1, 1, '', null, 2049629108245233667, '2025-06-26 20:29:06', null), +(2049629108245233673, '删除', 'DeleteSysUser', null, 0, null, 2, null, 'sys:user:del', 1, 0, 1, '', null, 2049629108245233672, '2025-06-26 20:29:06', null), +(2049629108245233674, 'page.menu.sysRole', 'SysRole', '/system/role', 3, 'carbon:user-role', 1, '/system/role/index', null, 1, 1, 1, '', null, 2049629108245233667, '2025-06-26 20:29:06', null), +(2049629108245233675, '新增', 'AddSysRole', null, 0, null, 2, null, 'sys:role:add', 1, 0, 1, '', null, 2049629108245233674, '2025-06-26 20:29:06', null), +(2049629108245233676, '修改', 'EditSysRole', null, 0, null, 2, null, 'sys:role:edit', 1, 0, 1, '', null, 2049629108245233674, '2025-06-26 20:29:06', null), +(2049629108245233677, '修改角色菜单', 'EditSysRoleMenu', null, 0, null, 2, null, 'sys:role:menu:edit', 1, 0, 1, '', null, 2049629108245233674, '2025-06-26 20:29:06', null), +(2049629108245233678, '修改角色数据范围', 'EditSysRoleScope', null, 0, null, 2, null, 'sys:role:scope:edit', 1, 0, 1, '', null, 2049629108245233674, '2025-06-26 20:29:06', null), +(2049629108245233679, '删除', 'DeleteSysRole', null, 0, null, 2, null, 'sys:role:del', 1, 0, 1, '', null, 2049629108245233674, '2025-06-26 20:29:06', null), +(2049629108245233680, 'page.menu.sysMenu', 'SysMenu', '/system/menu', 4, 'ant-design:menu-outlined', 1, '/system/menu/index', null, 1, 1, 1, '', null, 2049629108245233667, '2025-06-26 20:29:06', null), +(2049629108245233681, '新增', 'AddSysMenu', null, 0, null, 2, null, 'sys:menu:add', 1, 0, 1, '', null, 2049629108245233680, '2025-06-26 20:29:06', null), +(2049629108245233682, '修改', 'EditSysMenu', null, 0, null, 2, null, 'sys:menu:edit', 1, 0, 1, '', null, 2049629108245233680, '2025-06-26 20:29:06', null), +(2049629108249427968, '删除', 'DeleteSysMenu', null, 0, null, 2, null, 'sys:menu:del', 1, 0, 1, '', null, 2049629108245233680, '2025-06-26 20:29:06', null), +(2049629108249427969, 'page.menu.sysDataPermission', 'SysDataPermission', '/system/data-permission', 5, 'icon-park-outline:permissions', 0, null, null, 1, 1, 1, '', null, 2049629108245233667, '2025-06-26 20:29:06', null), +(2049629108249427970, 'page.menu.sysDataScope', 'SysDataScope', '/system/data-scope', 6, 'cuida:scope-outline', 1, '/system/data-permission/scope/index', null, 1, 1, 1, '', null, 2049629108249427969, '2025-06-26 20:29:06', '2025-06-26 20:37:26'), +(2049629108249427971, '新增', 'AddSysDataScope', null, 0, null, 2, null, 'data:scope:add', 1, 0, 1, '', null, 2049629108249427970, '2025-06-26 20:29:06', null), +(2049629108249427972, '修改', 'EditSysDataScope', null, 0, null, 2, null, 'data:scope:edit', 1, 0, 1, '', null, 2049629108249427970, '2025-06-26 20:29:06', null), +(2049629108249427973, '修改数据范围规则', 'EditDataScopeRule', null, 0, null, 2, null, 'data:scope:rule:edit', 1, 0, 1, '', null, 2049629108249427970, '2025-06-26 20:29:06', null), +(2049629108249427974, '删除', 'DeleteSysDataScope', null, 0, null, 2, null, 'data:scope:del', 1, 0, 1, '', null, 2049629108249427970, '2025-06-26 20:29:06', null), +(2049629108249427975, 'page.menu.sysDataRule', 'SysDataRule', '/system/data-rule', 7, 'material-symbols:rule', 1, '/system/data-permission/rule/index', null, 1, 1, 1, '', null, 2049629108249427969, '2025-06-26 20:29:06', '2025-06-26 20:37:40'), +(2049629108249427976, '新增', 'AddSysDataRule', null, 0, null, 2, null, 'data:rule:add', 1, 0, 1, '', null, 2049629108249427975, '2025-06-26 20:29:06', null), +(2049629108249427977, '修改', 'EditSysDataRule', null, 0, null, 2, null, 'data:rule:edit', 1, 0, 1, '', null, 2049629108249427975, '2025-06-26 20:29:06', null), +(2049629108249427978, '删除', 'DeleteSysDataRule', null, 0, null, 2, null, 'data:rule:del', 1, 0, 1, '', null, 2049629108249427975, '2025-06-26 20:29:06', null), +(2049629108249427979, 'page.menu.sysPlugin', 'SysPlugin', '/system/plugin', 8, 'clarity:plugin-line', 1, '/system/plugin/index', null, 1, 1, 1, '', null, 2049629108245233667, '2025-06-26 20:29:06', null), +(2049629108249427980, '安装', 'InstallSysPlugin', null, 0, null, 2, null, 'sys:plugin:install', 1, 0, 1, '', null, 2049629108249427979, '2025-06-26 20:29:06', null), +(2049629108249427981, '卸载', 'UninstallSysPlugin', null, 0, null, 2, null, 'sys:plugin:uninstall', 1, 0, 1, '', null, 2049629108249427979, '2025-06-26 20:29:06', null), +(2049629108249427982, '修改', 'EditSysPlugin', null, 0, null, 2, null, 'sys:plugin:edit', 1, 0, 1, '', null, 2049629108249427979, '2025-06-26 20:29:06', null), +(2049629108249427983, 'page.menu.scheduler', 'Scheduler', '/scheduler', 2, 'material-symbols:automation', 0, null, null, 1, 1, 1, '', null, null, '2025-06-26 20:29:06', null), +(2049629108249427984, 'page.menu.schedulerManage', 'SchedulerManage', '/scheduler/manage', 1, 'ix:scheduler', 1, '/scheduler/manage/index', null, 1, 1, 1, '', null, 2049629108249427983, '2025-06-26 20:29:06', null), +(2049629108249427985, 'page.menu.schedulerRecord', 'SchedulerRecord', '/scheduler/record', 2, 'ix:scheduler', 1, '/scheduler/record/index', null, 1, 1, 1, '', null, 2049629108249427983, '2025-06-26 20:29:06', null), +(2049629108249427986, 'page.menu.log', 'Log', '/log', 3, 'carbon:cloud-logging', 0, null, null, 1, 1, 1, '', null, null, '2025-06-26 20:29:06', null), +(2049629108249427987, 'page.menu.login', 'LoginLog', '/log/login', 1, 'mdi:login', 1, '/log/login/index', null, 1, 1, 1, '', null, 2049629108249427986, '2025-06-26 20:29:06', null), +(2049629108249427988, '删除', 'DeleteLoginLog', null, 0, null, 2, null, 'log:login:del', 1, 0, 1, '', null, 2049629108249427987, '2025-06-26 20:29:06', null), +(2049629108249427989, '清空', 'EmptyLoginLog', null, 0, null, 2, null, 'log:login:clear', 1, 0, 1, '', null, 2049629108249427987, '2025-06-26 20:29:06', null), +(2049629108249427990, 'page.menu.opera', 'OperaLog', '/log/opera', 2, 'carbon:operations-record', 1, '/log/opera/index', null, 1, 1, 1, '', null, 2049629108249427986, '2025-06-26 20:29:06', null), +(2049629108249427991, '删除', 'DeleteOperaLog', null, 0, null, 2, null, 'log:opera:del', 1, 0, 1, '', null, 2049629108249427990, '2025-06-26 20:29:06', null), +(2049629108253622272, '清空', 'EmptyOperaLog', null, 0, null, 2, null, 'log:opera:clear', 1, 0, 1, '', null, 2049629108249427990, '2025-06-26 20:29:06', null), +(2049629108253622273, 'page.menu.monitor', 'Monitor', '/monitor', 4, 'mdi:monitor-eye', 0, null, null, 1, 1, 1, '', null, null, '2025-06-26 20:29:06', null), +(2049629108253622274, 'page.menu.online', 'Online', '/log/online', 1, 'wpf:online', 1, '/monitor/online/index', null, 1, 1, 1, '', null, 2049629108253622273, '2025-06-26 20:29:06', null), +(2049629108253622276, 'page.menu.redis', 'Redis', '/monitor/redis', 2, 'devicon:redis', 1, '/monitor/redis/index', null, 1, 1, 1, '', null, 2049629108253622273, '2025-06-26 20:29:06', null), +(2049629108253622277, 'page.menu.server', 'Server', '/monitor/server', 3, 'mdi:server-outline', 1, '/monitor/server/index', null, 1, 1, 1, '', null, 2049629108253622273, '2025-06-26 20:29:06', null), +(2049629108253622278, '项目', 'Project', '/fba', 5, 'https://wu-clan.github.io/picx-images-hosting/logo/fba.png', 0, null, null, 1, 1, 1, '', null, null, '2025-06-26 20:29:06', null), +(2049629108253622279, '文档', 'Document', '/fba/document', 1, 'lucide:book-open-text', 4, '/_core/fallback/iframe.vue', null, 1, 1, 1, 'https://fastapi-practices.github.io/fastapi_best_architecture_docs', null, 2049629108253622278, '2025-06-26 20:29:06', null), +(2049629108253622280, 'Github', 'Github', '/fba/github', 2, 'ant-design:github-filled', 4, '/_core/fallback/iframe.vue', null, 1, 1, 1, 'https://github.com/fastapi-practices/fastapi-best-architecture', null, 2049629108253622278, '2025-06-26 20:29:06', null), +(2049629108253622281, 'Apifox', 'Apifox', '/fba/apifox', 3, 'simple-icons:apifox', 3, '/_core/fallback/iframe.vue', null, 1, 1, 1, 'https://apifox.com/apidoc/shared-28a93f02-730b-4f33-bb5e-4dad92058cc0', null, 2049629108253622278, '2025-06-26 20:29:06', null), +(2049629108253622282, 'page.menu.profile', 'Profile', '/profile', 6, 'ant-design:profile-outlined', 1, '/_core/profile/index', null, 1, 0, 1, '', null, null, '2025-06-26 20:29:06', null); + +insert into sys_role (id, name, status, is_filter_scopes, remark, created_time, updated_time, tenant_id) +values (2048601269345583104, '测试', 1, true, null, now(), null, 0); + +insert into sys_role_menu (id, role_id, menu_id, tenant_id) +values +(2048601269412691968, 2048601269345583104, 2049629108245233664, 0), +(2048601269479800832, 2048601269345583104, 2049629108245233665, 0), +(2048601269546909696, 2048601269345583104, 2049629108245233666, 0), +(2048601269609824256, 2048601269345583104, 2049629108253622282, 0); + +insert into sys_user (id, uuid, username, nickname, password, salt, email, status, is_superuser, is_staff, is_multi_login, avatar, phone, join_time, last_login_time, last_password_changed_time, dept_id, created_time, updated_time, tenant_id) +values +(2048601269672738816, gen_random_uuid(), 'admin', '用户88888', '$2b$12$8y2eNucX19VjmZ3tYhBLcOsBwy9w1IjBQE4SSqwMDL5bGQVp2wqS.', decode('24326224313224387932654E7563583139566A6D5A33745968424C634F', 'hex'), 'admin@example.com', 1, true, true, true, null, null, now(), now(), now(), 2048601264366944256, now(), null, 0), +(2049946297615646720, gen_random_uuid(), 'test', '用户66666', '$2b$12$BMiXsNQAgTx7aNc7kVgnwedXGyUxPEHRnJMFbiikbqHgVoT3y14Za', decode('24326224313224424D6958734E514167547837614E63376B56676E7765', 'hex'), 'test@example.com', 1, false, false, false, null, null, now(), now(), now(), 2048601264366944256, now(), null, 0); + +insert into sys_user_role (id, user_id, role_id, tenant_id) +values +(2048601269739847680, 2048601269672738816, 2048601269345583104, 0), +(2049946493732913152, 2049946297615646720, 2048601269345583104, 0); + +insert into sys_data_scope (id, name, status, created_time, updated_time) +values +(2048601269806956544, '本部门数据权限', 1, now(), null), +(2048601269869871104, '部门及以下数据权限', 1, now(), null), +(2048601269869871105, '仅本人数据权限', 1, now(), null), +(2048601269869871106, '全模型本部门数据权限', 1, now(), null), +(2048601269869871107, '排除超级管理员数据权限', 1, now(), null); + +insert into sys_data_rule (id, name, model, "column", operator, expression, "value", created_time, updated_time) +values +(2048601269932785664, '部门 ID 等于当前用户部门', 'Dept', '__dept_id__', 0, 0, '${dept_id}', now(), null), +(2048601269999894528, '部门名称等于测试', 'Dept', 'name', 1, 0, '测试', now(), null), +(2048601269999894529, '父部门 ID 等于测试部门 ID', 'Dept', 'parent_id', 0, 0, '1', now(), null), +(2048601269999894530, '创建者等于当前用户', '__ALL__', '__created_by__', 0, 0, '${user_id}', now(), null), +(2048601269999894531, '全模型部门 ID 等于当前用户部门', '__ALL__', '__dept_id__', 0, 0, '${dept_id}', now(), null), +(2048601269999894533, '用户非超级管理员', 'User', 'is_superuser', 0, 1, '1', now(), null); + +insert into sys_role_data_scope (id, role_id, data_scope_id, tenant_id) +values +(2048601270062809088, 2048601269345583104, 2048601269806956544, 0), +(2048601270125723648, 2048601269345583104, 2048601269869871104, 0); + +insert into sys_data_scope_rule (id, data_scope_id, data_rule_id) +values +(2048601270062809088, 2048601269806956544, 2048601269932785664), +(2048601270125723648, 2048601269869871104, 2048601269999894528), +(2048601270192832512, 2048601269869871104, 2048601269999894529), +(2048601270192832513, 2048601269869871105, 2048601269999894530), +(2048601270192832514, 2048601269869871106, 2048601269999894531), +(2048601270192832515, 2048601269869871107, 2048601269999894533); diff --git a/backend/sql/postgresql/init_test_data_tenant.sql b/backend/sql/postgresql/init_test_data_tenant.sql new file mode 100644 index 00000000..22c8ecc9 --- /dev/null +++ b/backend/sql/postgresql/init_test_data_tenant.sql @@ -0,0 +1,120 @@ +insert into sys_dept (id, name, sort, leader, phone, email, status, del_flag, parent_id, created_time, updated_time, tenant_id) +values (1, '测试', 0, null, null, null, 1, false, null, now(), null, 0); + +insert into sys_menu (id, title, name, path, sort, icon, type, component, perms, status, display, cache, link, remark, parent_id, created_time, updated_time) +values +(1, 'page.dashboard.title', 'Dashboard', '/dashboard', 0, 'ant-design:dashboard-outlined', 0, null, null, 1, 1, 1, '', null, null, '2025-06-26 20:29:06', null), +(2, 'page.dashboard.analytics', 'Analytics', '/analytics', 0, 'lucide:area-chart', 1, '/dashboard/analytics/index', null, 1, 1, 1, '', null, 1, '2025-06-26 20:29:06', null), +(3, 'page.dashboard.workspace', 'Workspace', '/workspace', 1, 'carbon:workspace', 1, '/dashboard/workspace/index', null, 1, 1, 1, '', null, 1, '2025-06-26 20:29:06', null), +(4, 'page.menu.system', 'System', '/system', 1, 'eos-icons:admin', 0, null, null, 1, 1, 1, '', null, null, '2025-06-26 20:29:06', null), +(5, 'page.menu.sysDept', 'SysDept', '/system/dept', 1, 'mingcute:department-line', 1, '/system/dept/index', null, 1, 1, 1, '', null, 4, '2025-06-26 20:29:06', null), +(6, '新增', 'AddSysDept', null, 0, null, 2, null, 'sys:dept:add', 1, 0, 1, '', null, 5, '2025-06-26 20:29:06', null), +(7, '修改', 'EditSysDept', null, 0, null, 2, null, 'sys:dept:edit', 1, 0, 1, '', null, 5, '2025-06-26 20:29:06', null), +(8, '删除', 'DeleteSysDept', null, 0, null, 2, null, 'sys:dept:del', 1, 0, 1, '', null, 5, '2025-06-26 20:29:06', null), +(9, 'page.menu.sysUser', 'SysUser', '/system/user', 2, 'ant-design:user-outlined', 1, '/system/user/index', null, 1, 1, 1, '', null, 4, '2025-06-26 20:29:06', null), +(10, '删除', 'DeleteSysUser', null, 0, null, 2, null, 'sys:user:del', 1, 0, 1, '', null, 9, '2025-06-26 20:29:06', null), +(11, 'page.menu.sysRole', 'SysRole', '/system/role', 3, 'carbon:user-role', 1, '/system/role/index', null, 1, 1, 1, '', null, 4, '2025-06-26 20:29:06', null), +(12, '新增', 'AddSysRole', null, 0, null, 2, null, 'sys:role:add', 1, 0, 1, '', null, 11, '2025-06-26 20:29:06', null), +(13, '修改', 'EditSysRole', null, 0, null, 2, null, 'sys:role:edit', 1, 0, 1, '', null, 11, '2025-06-26 20:29:06', null), +(14, '修改角色菜单', 'EditSysRoleMenu', null, 0, null, 2, null, 'sys:role:menu:edit', 1, 0, 1, '', null, 11, '2025-06-26 20:29:06', null), +(15, '修改角色数据范围', 'EditSysRoleScope', null, 0, null, 2, null, 'sys:role:scope:edit', 1, 0, 1, '', null, 11, '2025-06-26 20:29:06', null), +(16, '删除', 'DeleteSysRole', null, 0, null, 2, null, 'sys:role:del', 1, 0, 1, '', null, 11, '2025-06-26 20:29:06', null), +(17, 'page.menu.sysMenu', 'SysMenu', '/system/menu', 4, 'ant-design:menu-outlined', 1, '/system/menu/index', null, 1, 1, 1, '', null, 4, '2025-06-26 20:29:06', null), +(18, '新增', 'AddSysMenu', null, 0, null, 2, null, 'sys:menu:add', 1, 0, 1, '', null, 17, '2025-06-26 20:29:06', null), +(19, '修改', 'EditSysMenu', null, 0, null, 2, null, 'sys:menu:edit', 1, 0, 1, '', null, 17, '2025-06-26 20:29:06', null), +(20, '删除', 'DeleteSysMenu', null, 0, null, 2, null, 'sys:menu:del', 1, 0, 1, '', null, 17, '2025-06-26 20:29:06', null), +(21, 'page.menu.sysDataPermission', 'SysDataPermission', '/system/data-permission', 5, 'icon-park-outline:permissions', 0, null, null, 1, 1, 1, '', null, 4, '2025-06-26 20:29:06', null), +(22, 'page.menu.sysDataScope', 'SysDataScope', '/system/data-scope', 6, 'cuida:scope-outline', 1, '/system/data-permission/scope/index', null, 1, 1, 1, '', null, 21, '2025-06-26 20:29:06', '2025-06-26 20:37:26'), +(23, '新增', 'AddSysDataScope', null, 0, null, 2, null, 'data:scope:add', 1, 0, 1, '', null, 22, '2025-06-26 20:29:06', null), +(24, '修改', 'EditSysDataScope', null, 0, null, 2, null, 'data:scope:edit', 1, 0, 1, '', null, 22, '2025-06-26 20:29:06', null), +(25, '修改数据范围规则', 'EditDataScopeRule', null, 0, null, 2, null, 'data:scope:rule:edit', 1, 0, 1, '', null, 22, '2025-06-26 20:29:06', null), +(26, '删除', 'DeleteSysDataScope', null, 0, null, 2, null, 'data:scope:del', 1, 0, 1, '', null, 22, '2025-06-26 20:29:06', null), +(27, 'page.menu.sysDataRule', 'SysDataRule', '/system/data-rule', 7, 'material-symbols:rule', 1, '/system/data-permission/rule/index', null, 1, 1, 1, '', null, 21, '2025-06-26 20:29:06', '2025-06-26 20:37:40'), +(28, '新增', 'AddSysDataRule', null, 0, null, 2, null, 'data:rule:add', 1, 0, 1, '', null, 27, '2025-06-26 20:29:06', null), +(29, '修改', 'EditSysDataRule', null, 0, null, 2, null, 'data:rule:edit', 1, 0, 1, '', null, 27, '2025-06-26 20:29:06', null), +(30, '删除', 'DeleteSysDataRule', null, 0, null, 2, null, 'data:rule:del', 1, 0, 1, '', null, 27, '2025-06-26 20:29:06', null), +(31, 'page.menu.sysPlugin', 'SysPlugin', '/system/plugin', 8, 'clarity:plugin-line', 1, '/system/plugin/index', null, 1, 1, 1, '', null, 4, '2025-06-26 20:29:06', null), +(32, '安装', 'InstallSysPlugin', null, 0, null, 2, null, 'sys:plugin:install', 1, 0, 1, '', null, 31, '2025-06-26 20:29:06', null), +(33, '卸载', 'UninstallSysPlugin', null, 0, null, 2, null, 'sys:plugin:uninstall', 1, 0, 1, '', null, 31, '2025-06-26 20:29:06', null), +(34, '修改', 'EditSysPlugin', null, 0, null, 2, null, 'sys:plugin:edit', 1, 0, 1, '', null, 31, '2025-06-26 20:29:06', null), +(35, 'page.menu.scheduler', 'Scheduler', '/scheduler', 2, 'material-symbols:automation', 0, null, null, 1, 1, 1, '', null, null, '2025-06-26 20:29:06', null), +(36, 'page.menu.schedulerManage', 'SchedulerManage', '/scheduler/manage', 1, 'ix:scheduler', 1, '/scheduler/manage/index', null, 1, 1, 1, '', null, 35, '2025-06-26 20:29:06', null), +(37, 'page.menu.schedulerRecord', 'SchedulerRecord', '/scheduler/record', 2, 'ix:scheduler', 1, '/scheduler/record/index', null, 1, 1, 1, '', null, 35, '2025-06-26 20:29:06', null), +(38, 'page.menu.log', 'Log', '/log', 3, 'carbon:cloud-logging', 0, null, null, 1, 1, 1, '', null, null, '2025-06-26 20:29:06', null), +(39, 'page.menu.login', 'LoginLog', '/log/login', 1, 'mdi:login', 1, '/log/login/index', null, 1, 1, 1, '', null, 38, '2025-06-26 20:29:06', null), +(40, '删除', 'DeleteLoginLog', null, 0, null, 2, null, 'log:login:del', 1, 0, 1, '', null, 39, '2025-06-26 20:29:06', null), +(41, '清空', 'EmptyLoginLog', null, 0, null, 2, null, 'log:login:clear', 1, 0, 1, '', null, 39, '2025-06-26 20:29:06', null), +(42, 'page.menu.opera', 'OperaLog', '/log/opera', 2, 'carbon:operations-record', 1, '/log/opera/index', null, 1, 1, 1, '', null, 38, '2025-06-26 20:29:06', null), +(43, '删除', 'DeleteOperaLog', null, 0, null, 2, null, 'log:opera:del', 1, 0, 1, '', null, 42, '2025-06-26 20:29:06', null), +(44, '清空', 'EmptyOperaLog', null, 0, null, 2, null, 'log:opera:clear', 1, 0, 1, '', null, 42, '2025-06-26 20:29:06', null), +(45, 'page.menu.monitor', 'Monitor', '/monitor', 4, 'mdi:monitor-eye', 0, null, null, 1, 1, 1, '', null, null, '2025-06-26 20:29:06', null), +(46, 'page.menu.online', 'Online', '/log/online', 1, 'wpf:online', 1, '/monitor/online/index', null, 1, 1, 1, '', null, 45, '2025-06-26 20:29:06', null), +(47, 'page.menu.redis', 'Redis', '/monitor/redis', 2, 'devicon:redis', 1, '/monitor/redis/index', null, 1, 1, 1, '', null, 45, '2025-06-26 20:29:06', null), +(48, 'page.menu.server', 'Server', '/monitor/server', 3, 'mdi:server-outline', 1, '/monitor/server/index', null, 1, 1, 1, '', null, 45, '2025-06-26 20:29:06', null), +(49, '项目', 'Project', '/fba', 5, 'https://wu-clan.github.io/picx-images-hosting/logo/fba.png', 0, null, null, 1, 1, 1, '', null, null, '2025-06-26 20:29:06', null), +(50, '文档', 'Document', '/fba/document', 1, 'lucide:book-open-text', 4, '/_core/fallback/iframe.vue', null, 1, 1, 1, 'https://fastapi-practices.github.io/fastapi_best_architecture_docs', null, 49, '2025-06-26 20:29:06', null), +(51, 'Github', 'Github', '/fba/github', 2, 'ant-design:github-filled', 4, '/_core/fallback/iframe.vue', null, 1, 1, 1, 'https://github.com/fastapi-practices/fastapi-best-architecture', null, 49, '2025-06-26 20:29:06', null), +(52, 'Apifox', 'Apifox', '/fba/apifox', 3, 'simple-icons:apifox', 3, '/_core/fallback/iframe.vue', null, 1, 1, 1, 'https://apifox.com/apidoc/shared-28a93f02-730b-4f33-bb5e-4dad92058cc0', null, 49, '2025-06-26 20:29:06', null), +(53, 'page.menu.profile', 'Profile', '/profile', 6, 'ant-design:profile-outlined', 1, '/_core/profile/index', null, 1, 0, 1, '', null, null, '2025-06-26 20:29:06', null); + +insert into sys_role (id, name, status, is_filter_scopes, remark, created_time, updated_time, tenant_id) +values (1, '测试', 1, true, null, now(), null, 0); + +insert into sys_role_menu (id, role_id, menu_id, tenant_id) +values +(1, 1, 1, 0), +(2, 1, 2, 0), +(3, 1, 3, 0), +(4, 1, 53, 0); + +insert into sys_user (id, uuid, username, nickname, password, salt, email, status, is_superuser, is_staff, is_multi_login, avatar, phone, join_time, last_login_time, last_password_changed_time, dept_id, created_time, updated_time, tenant_id) +values +(1, gen_random_uuid(), 'admin', '用户88888', '$2b$12$8y2eNucX19VjmZ3tYhBLcOsBwy9w1IjBQE4SSqwMDL5bGQVp2wqS.', decode('24326224313224387932654E7563583139566A6D5A33745968424C634F', 'hex'), 'admin@example.com', 1, true, true, true, null, null, now(), now(), now(), 1, now(), null, 0), +(2, gen_random_uuid(), 'test', '用户66666', '$2b$12$BMiXsNQAgTx7aNc7kVgnwedXGyUxPEHRnJMFbiikbqHgVoT3y14Za', decode('24326224313224424D6958734E514167547837614E63376B56676E7765', 'hex'), 'test@example.com', 1, false, false, false, null, null, now(), now(), now(), 1, now(), null, 0); + +insert into sys_user_role (id, user_id, role_id, tenant_id) +values +(1, 1, 1, 0), +(2, 2, 1, 0); + +insert into sys_data_scope (id, name, status, created_time, updated_time) +values +(1, '本部门数据权限', 1, now(), null), +(2, '测试部门及以下数据权限', 1, now(), null), +(3, '仅本人数据权限', 1, now(), null), +(4, '全模型本部门数据权限', 1, now(), null), +(5, '排除超级管理员数据权限', 1, now(), null); + +insert into sys_data_rule (id, name, model, "column", operator, expression, "value", created_time, updated_time) +values +(1, '部门 ID 等于当前用户部门', 'Dept', '__dept_id__', 0, 0, '${dept_id}', now(), null), +(2, '部门名称等于测试', 'Dept', 'name', 1, 0, '测试', now(), null), +(3, '父部门 ID 等于测试部门 ID', 'Dept', 'parent_id', 0, 0, '1', now(), null), +(4, '创建者等于当前用户', '__ALL__', '__created_by__', 0, 0, '${user_id}', now(), null), +(5, '全模型部门 ID 等于当前用户部门', '__ALL__', '__dept_id__', 0, 0, '${dept_id}', now(), null), +(6, '用户非超级管理员', 'User', 'is_superuser', 0, 1, '1', now(), null); + +insert into sys_role_data_scope (id, role_id, data_scope_id, tenant_id) +values +(1, 1, 1, 0), +(2, 1, 2, 0); + +insert into sys_data_scope_rule (id, data_scope_id, data_rule_id) +values +(1, 1, 1), +(2, 2, 2), +(3, 2, 3), +(4, 3, 4), +(5, 4, 5), +(6, 5, 6); + +select setval(pg_get_serial_sequence('sys_dept', 'id'),coalesce(max(id), 0) + 1, true) from sys_dept; +select setval(pg_get_serial_sequence('sys_menu', 'id'),coalesce(max(id), 0) + 1, true) from sys_menu; +select setval(pg_get_serial_sequence('sys_role', 'id'),coalesce(max(id), 0) + 1, true) from sys_role; +select setval(pg_get_serial_sequence('sys_role_menu', 'id'),coalesce(max(id), 0) + 1, true) from sys_role_menu; +select setval(pg_get_serial_sequence('sys_user', 'id'),coalesce(max(id), 0) + 1, true) from sys_user; +select setval(pg_get_serial_sequence('sys_user_role', 'id'),coalesce(max(id), 0) + 1, true) from sys_user_role; +select setval(pg_get_serial_sequence('sys_data_scope', 'id'),coalesce(max(id), 0) + 1, true) from sys_data_scope; +select setval(pg_get_serial_sequence('sys_data_rule', 'id'),coalesce(max(id), 0) + 1, true) from sys_data_rule; +select setval(pg_get_serial_sequence('sys_role_data_scope', 'id'),coalesce(max(id), 0) + 1, true) from sys_role_data_scope; +select setval(pg_get_serial_sequence('sys_data_scope_rule', 'id'),coalesce(max(id), 0) + 1, true) from sys_data_scope_rule;