diff --git a/backend/app/admin/crud/crud_dept.py b/backend/app/admin/crud/crud_dept.py index 3e1da08b5..54caded7c 100644 --- a/backend/app/admin/crud/crud_dept.py +++ b/backend/app/admin/crud/crud_dept.py @@ -20,7 +20,7 @@ async def get(self, db: AsyncSession, dept_id: int) -> Dept | None: :param dept_id: 部门 ID :return: """ - return await self.select_model_by_column(db, id=dept_id, del_flag=0) + return await self.select_model_by_column(db, id=dept_id, del_flag=False) async def get_by_name(self, db: AsyncSession, name: str) -> Dept | None: """ @@ -30,7 +30,7 @@ async def get_by_name(self, db: AsyncSession, name: str) -> Dept | None: :param name: 部门名称 :return: """ - return await self.select_model_by_column(db, name=name, del_flag=0) + return await self.select_model_by_column(db, name=name, del_flag=False) async def get_all( self, @@ -52,7 +52,7 @@ async def get_all( :param status: 部门状态 :return: """ - filters = {'del_flag': 0} + filters = {'del_flag': False} if name is not None: filters['name__like'] = f'%{name}%' diff --git a/backend/app/admin/model/dept.py b/backend/app/admin/model/dept.py index 6d70cd6bc..139f8e5c4 100644 --- a/backend/app/admin/model/dept.py +++ b/backend/app/admin/model/dept.py @@ -4,7 +4,6 @@ import sqlalchemy as sa -from sqlalchemy.dialects.mysql import TINYINT from sqlalchemy.orm import Mapped, mapped_column, relationship from backend.common.model import Base, id_key @@ -25,9 +24,7 @@ class Dept(Base): phone: Mapped[str | None] = mapped_column(sa.String(11), default=None, comment='手机') email: Mapped[str | None] = mapped_column(sa.String(50), default=None, comment='邮箱') status: Mapped[int] = mapped_column(default=1, comment='部门状态(0停用 1正常)') - del_flag: Mapped[bool] = mapped_column( - sa.INTEGER().with_variant(TINYINT, 'mysql'), default=False, comment='删除标志(0删除 1存在)' - ) + del_flag: Mapped[bool] = mapped_column(default=False, comment='删除标志(0删除 1存在)') # 父级部门一对多 parent_id: Mapped[int | None] = mapped_column( diff --git a/backend/app/admin/model/login_log.py b/backend/app/admin/model/login_log.py index 048e7d821..a378c2108 100644 --- a/backend/app/admin/model/login_log.py +++ b/backend/app/admin/model/login_log.py @@ -2,10 +2,9 @@ import sqlalchemy as sa -from sqlalchemy.dialects.mysql import LONGTEXT from sqlalchemy.orm import Mapped, mapped_column -from backend.common.model import DataClassBase, TimeZone, id_key +from backend.common.model import DataClassBase, TimeZone, UniversalText, id_key from backend.utils.timezone import timezone @@ -26,7 +25,7 @@ class LoginLog(DataClassBase): os: Mapped[str | None] = mapped_column(sa.String(50), comment='操作系统') browser: Mapped[str | None] = mapped_column(sa.String(50), comment='浏览器') device: Mapped[str | None] = mapped_column(sa.String(50), comment='设备') - msg: Mapped[str] = mapped_column(sa.TEXT().with_variant(LONGTEXT, 'mysql'), comment='提示消息') + msg: Mapped[str] = mapped_column(UniversalText, comment='提示消息') login_time: Mapped[datetime] = mapped_column(TimeZone, comment='登录时间') created_time: Mapped[datetime] = mapped_column( TimeZone, diff --git a/backend/app/admin/model/menu.py b/backend/app/admin/model/menu.py index 8f0166fe4..d203419a5 100644 --- a/backend/app/admin/model/menu.py +++ b/backend/app/admin/model/menu.py @@ -4,11 +4,10 @@ import sqlalchemy as sa -from sqlalchemy.dialects.mysql import LONGTEXT from sqlalchemy.orm import Mapped, mapped_column, relationship from backend.app.admin.model.m2m import sys_role_menu -from backend.common.model import Base, id_key +from backend.common.model import Base, UniversalText, id_key if TYPE_CHECKING: from backend.app.admin.model import Role @@ -31,10 +30,8 @@ class Menu(Base): status: Mapped[int] = mapped_column(default=1, comment='菜单状态(0停用 1正常)') display: Mapped[int] = mapped_column(default=1, comment='是否显示(0否 1是)') cache: Mapped[int] = mapped_column(default=1, comment='是否缓存(0否 1是)') - link: Mapped[str | None] = mapped_column( - sa.TEXT().with_variant(LONGTEXT, 'mysql'), default=None, comment='外链地址' - ) - remark: Mapped[str | None] = mapped_column(sa.TEXT().with_variant(LONGTEXT, 'mysql'), default=None, comment='备注') + link: Mapped[str | None] = mapped_column(UniversalText, default=None, comment='外链地址') + remark: Mapped[str | None] = mapped_column(UniversalText, default=None, comment='备注') # 父级菜单一对多 parent_id: Mapped[int | None] = mapped_column( diff --git a/backend/app/admin/model/opera_log.py b/backend/app/admin/model/opera_log.py index ec0e39fde..1cc16c0ff 100644 --- a/backend/app/admin/model/opera_log.py +++ b/backend/app/admin/model/opera_log.py @@ -2,10 +2,9 @@ import sqlalchemy as sa -from sqlalchemy.dialects.mysql import LONGTEXT from sqlalchemy.orm import Mapped, mapped_column -from backend.common.model import DataClassBase, TimeZone, id_key +from backend.common.model import DataClassBase, TimeZone, UniversalText, id_key from backend.utils.timezone import timezone @@ -31,7 +30,7 @@ class OperaLog(DataClassBase): args: Mapped[str | None] = mapped_column(sa.JSON(), comment='请求参数') status: Mapped[int] = mapped_column(comment='操作状态(0异常 1正常)') code: Mapped[str] = mapped_column(sa.String(20), insert_default='200', comment='操作状态码') - msg: Mapped[str | None] = mapped_column(sa.TEXT().with_variant(LONGTEXT, 'mysql'), comment='提示消息') + msg: Mapped[str | None] = mapped_column(UniversalText, comment='提示消息') cost_time: Mapped[float] = mapped_column(insert_default=0.0, comment='请求耗时(ms)') opera_time: Mapped[datetime] = mapped_column(TimeZone, comment='操作时间') created_time: Mapped[datetime] = mapped_column( diff --git a/backend/app/admin/model/role.py b/backend/app/admin/model/role.py index 7937a271f..cd690bb52 100644 --- a/backend/app/admin/model/role.py +++ b/backend/app/admin/model/role.py @@ -4,11 +4,10 @@ import sqlalchemy as sa -from sqlalchemy.dialects.mysql import LONGTEXT, TINYINT from sqlalchemy.orm import Mapped, mapped_column, relationship from backend.app.admin.model.m2m import sys_role_data_scope, sys_role_menu, sys_user_role -from backend.common.model import Base, id_key +from backend.common.model import Base, UniversalText, id_key if TYPE_CHECKING: from backend.app.admin.model import DataScope, Menu, User @@ -22,10 +21,8 @@ class Role(Base): id: Mapped[id_key] = mapped_column(init=False) name: Mapped[str] = mapped_column(sa.String(20), unique=True, comment='角色名称') status: Mapped[int] = mapped_column(default=1, comment='角色状态(0停用 1正常)') - is_filter_scopes: Mapped[bool] = mapped_column( - sa.INTEGER().with_variant(TINYINT, 'mysql'), default=True, comment='过滤数据权限(0否 1是)' - ) - remark: Mapped[str | None] = mapped_column(sa.TEXT().with_variant(LONGTEXT, 'mysql'), default=None, comment='备注') + is_filter_scopes: Mapped[bool] = mapped_column(default=True, comment='过滤数据权限(0否 1是)') + remark: Mapped[str | None] = mapped_column(UniversalText, default=None, comment='备注') # 角色用户多对多 users: Mapped[list[User]] = relationship(init=False, secondary=sys_user_role, back_populates='roles') diff --git a/backend/app/admin/model/user.py b/backend/app/admin/model/user.py index 2719ba993..b388722ee 100644 --- a/backend/app/admin/model/user.py +++ b/backend/app/admin/model/user.py @@ -5,8 +5,6 @@ import sqlalchemy as sa -from sqlalchemy.dialects.mysql import TINYINT -from sqlalchemy.dialects.postgresql import BYTEA from sqlalchemy.orm import Mapped, mapped_column, relationship from backend.app.admin.model.m2m import sys_user_role @@ -28,20 +26,14 @@ class User(Base): username: Mapped[str] = mapped_column(sa.String(20), unique=True, index=True, comment='用户名') nickname: Mapped[str] = mapped_column(sa.String(20), comment='昵称') password: Mapped[str | None] = mapped_column(sa.String(255), comment='密码') - salt: Mapped[bytes | None] = mapped_column(BYTEA(255).with_variant(sa.VARBINARY, 'mysql'), comment='加密盐') + salt: Mapped[bytes | None] = mapped_column(sa.LargeBinary(255), comment='加密盐') email: Mapped[str | None] = mapped_column(sa.String(50), default=None, unique=True, index=True, comment='邮箱') phone: Mapped[str | None] = mapped_column(sa.String(11), default=None, comment='手机号') avatar: Mapped[str | None] = mapped_column(sa.String(255), default=None, comment='头像') status: Mapped[int] = mapped_column(default=1, index=True, comment='用户账号状态(0停用 1正常)') - is_superuser: Mapped[bool] = mapped_column( - sa.INTEGER().with_variant(TINYINT, 'mysql'), default=False, comment='超级权限(0否 1是)' - ) - is_staff: Mapped[bool] = mapped_column( - sa.INTEGER().with_variant(TINYINT, 'mysql'), default=False, comment='后台管理登陆(0否 1是)' - ) - is_multi_login: Mapped[bool] = mapped_column( - sa.INTEGER().with_variant(TINYINT, 'mysql'), default=False, comment='是否重复登陆(0否 1是)' - ) + is_superuser: Mapped[bool] = mapped_column(default=False, comment='超级权限(0否 1是)') + is_staff: Mapped[bool] = mapped_column(default=False, comment='后台管理登陆(0否 1是)') + is_multi_login: Mapped[bool] = mapped_column(default=False, comment='是否重复登陆(0否 1是)') join_time: Mapped[datetime] = mapped_column(TimeZone, init=False, default_factory=timezone.now, comment='注册时间') last_login_time: Mapped[datetime | None] = mapped_column( TimeZone, init=False, onupdate=timezone.now, comment='上次登录' @@ -49,7 +41,7 @@ class User(Base): # 部门用户一对多 dept_id: Mapped[int | None] = mapped_column( - sa.ForeignKey('sys_dept.id', ondelete='SET NULL'), default=None, comment='部门关联ID' + sa.BigInteger, sa.ForeignKey('sys_dept.id', ondelete='SET NULL'), default=None, comment='部门关联ID' ) dept: Mapped[Dept | None] = relationship(init=False, back_populates='users') diff --git a/backend/app/task/model/scheduler.py b/backend/app/task/model/scheduler.py index c36d59cef..27da77bfc 100644 --- a/backend/app/task/model/scheduler.py +++ b/backend/app/task/model/scheduler.py @@ -5,11 +5,10 @@ import sqlalchemy as sa from sqlalchemy import event -from sqlalchemy.dialects.mysql import LONGTEXT, TINYINT from sqlalchemy.orm import Mapped, mapped_column from backend.common.exception import errors -from backend.common.model import Base, TimeZone, id_key +from backend.common.model import Base, TimeZone, UniversalText, id_key from backend.core.conf import settings from backend.database.redis import redis_client from backend.utils.timezone import timezone @@ -35,15 +34,11 @@ class TaskScheduler(Base): interval_every: Mapped[int | None] = mapped_column(comment='任务再次运行前的间隔周期数') interval_period: Mapped[str | None] = mapped_column(sa.String(255), comment='任务运行之间的周期类型') crontab: Mapped[str | None] = mapped_column(sa.String(50), default='* * * * *', comment='任务运行的 Crontab 计划') - one_off: Mapped[bool] = mapped_column( - sa.INTEGER().with_variant(TINYINT, 'mysql'), default=False, comment='是否仅运行一次' - ) - enabled: Mapped[bool] = mapped_column( - sa.INTEGER().with_variant(TINYINT, 'mysql'), default=True, comment='是否启用任务' - ) + one_off: Mapped[bool] = mapped_column(default=False, comment='是否仅运行一次') + enabled: Mapped[bool] = mapped_column(default=True, comment='是否启用任务') total_run_count: Mapped[int] = mapped_column(default=0, comment='任务触发的总次数') last_run_time: Mapped[datetime | None] = mapped_column(TimeZone, default=None, comment='任务最后触发的时间') - remark: Mapped[str | None] = mapped_column(sa.TEXT().with_variant(LONGTEXT, 'mysql'), default=None, comment='备注') + remark: Mapped[str | None] = mapped_column(UniversalText, default=None, comment='备注') no_changes: bool = False diff --git a/backend/app/task/utils/schedulers.py b/backend/app/task/utils/schedulers.py index 49151c303..577518372 100644 --- a/backend/app/task/utils/schedulers.py +++ b/backend/app/task/utils/schedulers.py @@ -399,7 +399,7 @@ async def get_all_task_schedulers(self) -> dict: """获取所有任务调度""" async with async_db_session() as db: logger.debug('DatabaseScheduler: Fetching database schedule') - stmt = select(TaskScheduler).where(TaskScheduler.enabled == 1) + stmt = select(TaskScheduler).where(TaskScheduler.enabled == True) # noqa: E712 query = await db.execute(stmt) schedulers = query.scalars().all() s = {} diff --git a/backend/common/model.py b/backend/common/model.py index ff4e68a91..4f8b799fe 100644 --- a/backend/common/model.py +++ b/backend/common/model.py @@ -1,10 +1,12 @@ from datetime import datetime from typing import Annotated -from sqlalchemy import BigInteger, DateTime, TypeDecorator +from sqlalchemy import BigInteger, DateTime, Text, TypeDecorator +from sqlalchemy.dialects.mysql import LONGTEXT from sqlalchemy.ext.asyncio import AsyncAttrs from sqlalchemy.orm import DeclarativeBase, Mapped, MappedAsDataclass, declared_attr, mapped_column +from backend.core.conf import settings from backend.utils.snowflake import snowflake from backend.utils.timezone import timezone @@ -41,16 +43,21 @@ ] -# Mixin: 一种面向对象编程概念, 使结构变得更加清晰, `Wiki `__ -class UserMixin(MappedAsDataclass): - """用户 Mixin 数据类""" +class UniversalText(TypeDecorator[str]): + """PostgreSQL、MySQL 兼容性(长)文本类型""" - created_by: Mapped[int] = mapped_column(sort_order=998, comment='创建者') - updated_by: Mapped[int | None] = mapped_column(init=False, default=None, sort_order=998, comment='修改者') + impl = LONGTEXT if settings.DATABASE_TYPE == 'mysql' else Text + cache_ok = True + + def process_bind_param(self, value: str | None, dialect) -> str | None: # noqa: ANN001 + return value + + def process_result_value(self, value: str | None, dialect) -> str | None: # noqa: ANN001 + return value class TimeZone(TypeDecorator[datetime]): - """时区感知 DateTime""" + """PostgreSQL、MySQL 兼容性时区感知类型""" impl = DateTime(timezone=True) cache_ok = True @@ -71,6 +78,14 @@ def process_result_value(self, value: datetime | None, dialect) -> datetime | No return value +# Mixin: 一种面向对象编程概念, 使结构变得更加清晰, `Wiki `__ +class UserMixin(MappedAsDataclass): + """用户 Mixin 数据类""" + + created_by: Mapped[int] = mapped_column(sort_order=998, comment='创建者') + updated_by: Mapped[int | None] = mapped_column(init=False, default=None, sort_order=998, comment='修改者') + + class DateTimeMixin(MappedAsDataclass): """日期时间 Mixin 数据类""" diff --git a/backend/plugin/code_generator/model/business.py b/backend/plugin/code_generator/model/business.py index 01db2d33e..102cbb160 100644 --- a/backend/plugin/code_generator/model/business.py +++ b/backend/plugin/code_generator/model/business.py @@ -4,10 +4,9 @@ import sqlalchemy as sa -from sqlalchemy.dialects.mysql import LONGTEXT from sqlalchemy.orm import Mapped, mapped_column, relationship -from backend.common.model import Base, id_key +from backend.common.model import Base, UniversalText, id_key if TYPE_CHECKING: from backend.plugin.code_generator.model import GenColumn @@ -34,6 +33,6 @@ class GenBusiness(Base): gen_path: Mapped[str | None] = mapped_column( sa.String(255), default=None, comment='代码生成路径(默认为 app 根路径)' ) - remark: Mapped[str | None] = mapped_column(sa.TEXT().with_variant(LONGTEXT, 'mysql'), default=None, comment='备注') + remark: Mapped[str | None] = mapped_column(UniversalText, default=None, comment='备注') # 代码生成业务模型列一对多 gen_column: Mapped[list[GenColumn]] = relationship(init=False, back_populates='gen_business') diff --git a/backend/plugin/code_generator/model/column.py b/backend/plugin/code_generator/model/column.py index e997b7dda..d45e28798 100644 --- a/backend/plugin/code_generator/model/column.py +++ b/backend/plugin/code_generator/model/column.py @@ -4,10 +4,9 @@ import sqlalchemy as sa -from sqlalchemy.dialects.mysql import LONGTEXT from sqlalchemy.orm import Mapped, mapped_column, relationship -from backend.common.model import DataClassBase, id_key +from backend.common.model import DataClassBase, UniversalText, id_key if TYPE_CHECKING: from backend.plugin.code_generator.model import GenBusiness @@ -23,9 +22,7 @@ class GenColumn(DataClassBase): comment: Mapped[str | None] = mapped_column(sa.String(255), default=None, comment='列描述') type: Mapped[str] = mapped_column(sa.String(20), default='String', comment='SQLA 模型列类型') pd_type: Mapped[str] = mapped_column(sa.String(20), default='str', comment='列类型对应的 pydantic 类型') - default: Mapped[str | None] = mapped_column( - sa.TEXT().with_variant(LONGTEXT, 'mysql'), default=None, comment='列默认值' - ) + default: Mapped[str | None] = mapped_column(UniversalText, default=None, comment='列默认值') sort: Mapped[int | None] = mapped_column(default=1, comment='列排序') length: Mapped[int] = mapped_column(default=0, comment='列长度') is_pk: Mapped[bool] = mapped_column(default=False, comment='是否主键') diff --git a/backend/plugin/config/model/config.py b/backend/plugin/config/model/config.py index 4aea40b4c..7047b1048 100644 --- a/backend/plugin/config/model/config.py +++ b/backend/plugin/config/model/config.py @@ -1,9 +1,8 @@ import sqlalchemy as sa -from sqlalchemy.dialects.mysql import LONGTEXT, TINYINT from sqlalchemy.orm import Mapped, mapped_column -from backend.common.model import Base, id_key +from backend.common.model import Base, UniversalText, id_key class Config(Base): @@ -15,8 +14,6 @@ class Config(Base): name: Mapped[str] = mapped_column(sa.String(20), comment='名称') type: Mapped[str | None] = mapped_column(sa.String(20), server_default=None, comment='类型') key: Mapped[str] = mapped_column(sa.String(50), unique=True, comment='键名') - value: Mapped[str] = mapped_column(sa.TEXT().with_variant(LONGTEXT, 'mysql'), comment='键值') - is_frontend: Mapped[bool] = mapped_column( - sa.INTEGER().with_variant(TINYINT, 'mysql'), default=False, comment='是否前端' - ) - remark: Mapped[str | None] = mapped_column(sa.TEXT().with_variant(LONGTEXT, 'mysql'), default=None, comment='备注') + value: Mapped[str] = mapped_column(UniversalText, comment='键值') + is_frontend: Mapped[bool] = mapped_column(default=False, comment='是否前端') + remark: Mapped[str | None] = mapped_column(UniversalText, default=None, comment='备注') diff --git a/backend/plugin/config/sql/mysql/init.sql b/backend/plugin/config/sql/mysql/init.sql index c23560e64..bd77d1dbd 100644 --- a/backend/plugin/config/sql/mysql/init.sql +++ b/backend/plugin/config/sql/mysql/init.sql @@ -1,8 +1,8 @@ insert into sys_config (id, name, type, `key`, value, is_frontend, remark, created_time, updated_time) values -(1, '状态', 'EMAIL', 'EMAIL_STATUS', '1', 0, null, now(), null), -(2, '服务器地址', 'EMAIL', 'EMAIL_HOST', 'smtp.qq.com', 0, null, now(), null), -(3, '服务器端口', 'EMAIL', 'EMAIL_PORT', '465', 0, null, now(), null), -(4, '邮箱账号', 'EMAIL', 'EMAIL_USERNAME', 'fba@qq.com', 0, null, now(), null), -(5, '邮箱密码', 'EMAIL', 'EMAIL_PASSWORD', '', 0, null, now(), null), -(6, 'SSL 加密', 'EMAIL', 'EMAIL_SSL', '1', 0, null, now(), null); +(1, '状态', 'EMAIL', 'EMAIL_STATUS', '1', false, null, now(), null), +(2, '服务器地址', 'EMAIL', 'EMAIL_HOST', 'smtp.qq.com', false, null, now(), null), +(3, '服务器端口', 'EMAIL', 'EMAIL_PORT', '465', false, null, now(), null), +(4, '邮箱账号', 'EMAIL', 'EMAIL_USERNAME', 'fba@qq.com', false, null, now(), null), +(5, '邮箱密码', 'EMAIL', 'EMAIL_PASSWORD', '', false, null, now(), null), +(6, 'SSL 加密', 'EMAIL', 'EMAIL_SSL', '1', false, null, now(), null); diff --git a/backend/plugin/config/sql/mysql/init_snowflake.sql b/backend/plugin/config/sql/mysql/init_snowflake.sql index 9ad793a43..36b762fae 100644 --- a/backend/plugin/config/sql/mysql/init_snowflake.sql +++ b/backend/plugin/config/sql/mysql/init_snowflake.sql @@ -1,8 +1,8 @@ insert into sys_config (id, name, type, `key`, value, is_frontend, remark, created_time, updated_time) values -(2069061886627938304, '状态', 'EMAIL', 'EMAIL_STATUS', '1', 0, null, now(), null), -(2069061886627938305, '服务器地址', 'EMAIL', 'EMAIL_HOST', 'smtp.qq.com', 0, null, now(), null), -(2069061886627938306, '服务器端口', 'EMAIL', 'EMAIL_PORT', '465', 0, null, now(), null), -(2069061886627938307, '邮箱账号', 'EMAIL', 'EMAIL_USERNAME', 'fba@qq.com', 0, null, now(), null), -(2069061886627938308, '邮箱密码', 'EMAIL', 'EMAIL_PASSWORD', '', 0, null, now(), null), -(2069061886627938309, 'SSL 加密', 'EMAIL', 'EMAIL_SSL', '1', 0, null, now(), null); +(2069061886627938304, '状态', 'EMAIL', 'EMAIL_STATUS', '1', false, null, now(), null), +(2069061886627938305, '服务器地址', 'EMAIL', 'EMAIL_HOST', 'smtp.qq.com', false, null, now(), null), +(2069061886627938306, '服务器端口', 'EMAIL', 'EMAIL_PORT', '465', false, null, now(), null), +(2069061886627938307, '邮箱账号', 'EMAIL', 'EMAIL_USERNAME', 'fba@qq.com', false, null, now(), null), +(2069061886627938308, '邮箱密码', 'EMAIL', 'EMAIL_PASSWORD', '', false, null, now(), null), +(2069061886627938309, 'SSL 加密', 'EMAIL', 'EMAIL_SSL', '1', false, null, now(), null); diff --git a/backend/plugin/config/sql/postgresql/init.sql b/backend/plugin/config/sql/postgresql/init.sql index 880b57324..cf76501ea 100644 --- a/backend/plugin/config/sql/postgresql/init.sql +++ b/backend/plugin/config/sql/postgresql/init.sql @@ -1,11 +1,10 @@ insert into sys_config (id, name, type, "key", value, is_frontend, remark, created_time, updated_time) values -(1, '状态', 'EMAIL', 'EMAIL_STATUS', '1', 0, null, now(), null), -(2, '服务器地址', 'EMAIL', 'EMAIL_HOST', 'smtp.qq.com', 0, null, now(), null), -(3, '服务器端口', 'EMAIL', 'EMAIL_PORT', '465', 0, null, now(), null), -(4, '邮箱账号', 'EMAIL', 'EMAIL_USERNAME', 'fba@qq.com', 0, null, now(), null), -(5, '邮箱密码', 'EMAIL', 'EMAIL_PASSWORD', '', 0, null, now(), null), -(6, 'SSL 加密', 'EMAIL', 'EMAIL_SSL', '1', 0, null, now(), null); +(1, '状态', 'EMAIL', 'EMAIL_STATUS', '1', false, null, now(), null), +(2, '服务器地址', 'EMAIL', 'EMAIL_HOST', 'smtp.qq.com', false, null, now(), null), +(3, '服务器端口', 'EMAIL', 'EMAIL_PORT', '465', false, null, now(), null), +(4, '邮箱账号', 'EMAIL', 'EMAIL_USERNAME', 'fba@qq.com', false, null, now(), null), +(5, '邮箱密码', 'EMAIL', 'EMAIL_PASSWORD', '', false, null, now(), null), +(6, 'SSL 加密', 'EMAIL', 'EMAIL_SSL', '1', false, null, now(), null); --- reset auto-increment values for each table based on max id select setval(pg_get_serial_sequence('sys_config', 'id'),coalesce(max(id), 0) + 1, true) from sys_config; diff --git a/backend/plugin/config/sql/postgresql/init_snowflake.sql b/backend/plugin/config/sql/postgresql/init_snowflake.sql index bee97464b..472865faa 100644 --- a/backend/plugin/config/sql/postgresql/init_snowflake.sql +++ b/backend/plugin/config/sql/postgresql/init_snowflake.sql @@ -1,8 +1,8 @@ insert into sys_config (id, name, type, "key", value, is_frontend, remark, created_time, updated_time) values -(2069061886627938304, '状态', 'EMAIL', 'EMAIL_STATUS', '1', 0, null, now(), null), -(2069061886627938305, '服务器地址', 'EMAIL', 'EMAIL_HOST', 'smtp.qq.com', 0, null, now(), null), -(2069061886627938306, '服务器端口', 'EMAIL', 'EMAIL_PORT', '465', 0, null, now(), null), -(2069061886627938307, '邮箱账号', 'EMAIL', 'EMAIL_USERNAME', 'fba@qq.com', 0, null, now(), null), -(2069061886627938308, '邮箱密码', 'EMAIL', 'EMAIL_PASSWORD', '', 0, null, now(), null), -(2069061886627938309, 'SSL 加密', 'EMAIL', 'EMAIL_SSL', '1', 0, null, now(), null); +(2069061886627938304, '状态', 'EMAIL', 'EMAIL_STATUS', '1', false, null, now(), null), +(2069061886627938305, '服务器地址', 'EMAIL', 'EMAIL_HOST', 'smtp.qq.com', false, null, now(), null), +(2069061886627938306, '服务器端口', 'EMAIL', 'EMAIL_PORT', '465', false, null, now(), null), +(2069061886627938307, '邮箱账号', 'EMAIL', 'EMAIL_USERNAME', 'fba@qq.com', false, null, now(), null), +(2069061886627938308, '邮箱密码', 'EMAIL', 'EMAIL_PASSWORD', '', false, null, now(), null), +(2069061886627938309, 'SSL 加密', 'EMAIL', 'EMAIL_SSL', '1', false, null, now(), null); diff --git a/backend/plugin/dict/model/dict_data.py b/backend/plugin/dict/model/dict_data.py index e0b7e4a5a..22bda4521 100644 --- a/backend/plugin/dict/model/dict_data.py +++ b/backend/plugin/dict/model/dict_data.py @@ -4,10 +4,9 @@ import sqlalchemy as sa -from sqlalchemy.dialects.mysql import LONGTEXT from sqlalchemy.orm import Mapped, mapped_column, relationship -from backend.common.model import Base, id_key +from backend.common.model import Base, UniversalText, id_key if TYPE_CHECKING: from backend.plugin.dict.model import DictType @@ -25,7 +24,7 @@ class DictData(Base): color: Mapped[str | None] = mapped_column(sa.String(32), default=None, comment='标签颜色') sort: Mapped[int] = mapped_column(default=0, comment='排序') status: Mapped[int] = mapped_column(default=1, comment='状态(0停用 1正常)') - remark: Mapped[str | None] = mapped_column(sa.TEXT().with_variant(LONGTEXT, 'mysql'), default=None, comment='备注') + remark: Mapped[str | None] = mapped_column(UniversalText, default=None, comment='备注') # 字典类型一对多 type_id: Mapped[int] = mapped_column( diff --git a/backend/plugin/dict/model/dict_type.py b/backend/plugin/dict/model/dict_type.py index 7a1444bbf..8fb2c4cce 100644 --- a/backend/plugin/dict/model/dict_type.py +++ b/backend/plugin/dict/model/dict_type.py @@ -4,10 +4,9 @@ import sqlalchemy as sa -from sqlalchemy.dialects.mysql import LONGTEXT from sqlalchemy.orm import Mapped, mapped_column, relationship -from backend.common.model import Base, id_key +from backend.common.model import Base, UniversalText, id_key if TYPE_CHECKING: from backend.plugin.dict.model import DictData @@ -21,7 +20,7 @@ class DictType(Base): id: Mapped[id_key] = mapped_column(init=False) name: Mapped[str] = mapped_column(sa.String(32), comment='字典类型名称') code: Mapped[str] = mapped_column(sa.String(32), unique=True, comment='字典类型编码') - remark: Mapped[str | None] = mapped_column(sa.TEXT().with_variant(LONGTEXT, 'mysql'), default=None, comment='备注') + remark: Mapped[str | None] = mapped_column(UniversalText, default=None, comment='备注') # 字典类型一对多 datas: Mapped[list[DictData]] = relationship(init=False, back_populates='type') diff --git a/backend/plugin/dict/sql/postgresql/init.sql b/backend/plugin/dict/sql/postgresql/init.sql index b9e456c50..dffee573a 100644 --- a/backend/plugin/dict/sql/postgresql/init.sql +++ b/backend/plugin/dict/sql/postgresql/init.sql @@ -52,6 +52,5 @@ values (35, 'sys_plugin_type', '压缩包', '0', 'gold', 1, 1, '插件类型-压缩包', 12, now(), null), (36, 'sys_plugin_type', 'GIT', '1', 'processing', 2, 1, '插件类型-GIT', 12, now(), null); --- reset auto-increment values for each table based on max id select setval(pg_get_serial_sequence('sys_dict_type', 'id'),coalesce(max(id), 0) + 1, true) from sys_dict_type; select setval(pg_get_serial_sequence('sys_dict_data', 'id'),coalesce(max(id), 0) + 1, true) from sys_dict_data; diff --git a/backend/plugin/notice/model/notice.py b/backend/plugin/notice/model/notice.py index 3ccea51bc..91a0e30aa 100644 --- a/backend/plugin/notice/model/notice.py +++ b/backend/plugin/notice/model/notice.py @@ -1,9 +1,8 @@ import sqlalchemy as sa -from sqlalchemy.dialects.mysql import LONGTEXT from sqlalchemy.orm import Mapped, mapped_column -from backend.common.model import Base, id_key +from backend.common.model import Base, UniversalText, id_key class Notice(Base): @@ -15,4 +14,4 @@ class Notice(Base): title: Mapped[str] = mapped_column(sa.String(50), comment='标题') type: Mapped[int] = mapped_column(comment='类型(0:通知、1:公告)') status: Mapped[int] = mapped_column(comment='状态(0:隐藏、1:显示)') - content: Mapped[str] = mapped_column(sa.TEXT().with_variant(LONGTEXT, 'mysql'), comment='内容') + content: Mapped[str] = mapped_column(UniversalText, comment='内容') diff --git a/backend/sql/mysql/init_snowflake_test_data.sql b/backend/sql/mysql/init_snowflake_test_data.sql index ff9546758..cba01f897 100644 --- a/backend/sql/mysql/init_snowflake_test_data.sql +++ b/backend/sql/mysql/init_snowflake_test_data.sql @@ -1,5 +1,5 @@ insert into sys_dept (id, name, sort, leader, phone, email, status, del_flag, parent_id, created_time, updated_time) -values (2048601258595581952, '测试', 0, null, null, null, 1, 0, null, now(), null); +values (2048601258595581952, '测试', 0, null, null, null, 1, false, null, 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 @@ -82,7 +82,7 @@ values (2049629108257816588, '写入', 'WriteGenCode', null, 0, null, 2, null, 'codegen:local:write', 1, 0, 1, '', null, 2049629108257816580, '2025-06-26 20:29:06', null); insert into sys_role (id, name, status, is_filter_scopes, remark, created_time, updated_time) -values (2048601263515500544, '测试', 1, 1, null, now(), null); +values (2048601263515500544, '测试', 1, true, null, now(), null); insert into sys_role_menu (id, role_id, menu_id) values @@ -91,10 +91,10 @@ values (2048601263708438528, 2048601263515500544, 2049629108245233666), (2048601263775547392, 2048601263515500544, 2049629108253622282); -insert into sys_user (id, uuid, username, nickname, password, salt, email, is_superuser, is_staff, status, is_multi_login, avatar, phone, join_time, last_login_time, dept_id, created_time, updated_time) +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, dept_id, created_time, updated_time) values -(2048601263834267648, uuid(), 'admin', '用户88888', '$2b$12$8y2eNucX19VjmZ3tYhBLcOsBwy9w1IjBQE4SSqwMDL5bGQVp2wqS.', unhex('24326224313224387932654E7563583139566A6D5A33745968424C634F'), 'admin@example.com', 1, 1, 1, 1, null, null, now(), now(), 2048601258595581952, now(), null), -(2049946297615646720, uuid(), 'test', '用户66666', '$2b$12$BMiXsNQAgTx7aNc7kVgnwedXGyUxPEHRnJMFbiikbqHgVoT3y14Za', unhex('24326224313224424D6958734E514167547837614E63376B56676E7765'), 'test@example.com', 0, 0, 1, 0, null, null, now(), now(), 2048601258595581952, now(), null); +(2048601263834267648, uuid(), 'admin', '用户88888', '$2b$12$8y2eNucX19VjmZ3tYhBLcOsBwy9w1IjBQE4SSqwMDL5bGQVp2wqS.', unhex('24326224313224387932654E7563583139566A6D5A33745968424C634F'), 'admin@example.com', 1, true, true, true, null, null, now(), now(), 2048601258595581952, now(), null), +(2049946297615646720, uuid(), 'test', '用户66666', '$2b$12$BMiXsNQAgTx7aNc7kVgnwedXGyUxPEHRnJMFbiikbqHgVoT3y14Za', unhex('24326224313224424D6958734E514167547837614E63376B56676E7765'), 'test@example.com', 1, false, false, false, null, null, now(), now(), 2048601258595581952, now(), null); insert into sys_user_role (id, user_id, role_id) values diff --git a/backend/sql/mysql/init_test_data.sql b/backend/sql/mysql/init_test_data.sql index 81779a6af..1ef86a0bb 100644 --- a/backend/sql/mysql/init_test_data.sql +++ b/backend/sql/mysql/init_test_data.sql @@ -1,5 +1,5 @@ insert into sys_dept (id, name, sort, leader, phone, email, status, del_flag, parent_id, created_time, updated_time) -values (1, '测试', 0, null, null, null, 1, 0, null, now(), null); +values (1, '测试', 0, null, null, null, 1, false, null, 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 @@ -82,7 +82,7 @@ values (77, '写入', 'WriteGenCode', null, 0, null, 2, null, 'codegen:local:write', 1, 0, 1, '', null, 69, '2025-06-26 20:29:06', null); insert into sys_role (id, name, status, is_filter_scopes, remark, created_time, updated_time) -values (1, '测试', 1, 1, null, now(), null); +values (1, '测试', 1, true, null, now(), null); insert into sys_role_menu (id, role_id, menu_id) values @@ -91,10 +91,10 @@ values (3, 1, 3), (4, 1, 53); -insert into sys_user (id, uuid, username, nickname, password, salt, email, is_superuser, is_staff, status, is_multi_login, avatar, phone, join_time, last_login_time, dept_id, created_time, updated_time) +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, dept_id, created_time, updated_time) values -(1, uuid(), 'admin', '用户88888', '$2b$12$8y2eNucX19VjmZ3tYhBLcOsBwy9w1IjBQE4SSqwMDL5bGQVp2wqS.', unhex('24326224313224387932654E7563583139566A6D5A33745968424C634F'), 'admin@example.com', 1, 1, 1, 1, null, null, now(), now(), 1, now(), null), -(2, uuid(), 'test', '用户66666', '$2b$12$BMiXsNQAgTx7aNc7kVgnwedXGyUxPEHRnJMFbiikbqHgVoT3y14Za', unhex('24326224313224424D6958734E514167547837614E63376B56676E7765'), 'test@example.com', 0, 0, 1, 0, null, null, now(), now(), 1, now(), null); +(1, uuid(), 'admin', '用户88888', '$2b$12$8y2eNucX19VjmZ3tYhBLcOsBwy9w1IjBQE4SSqwMDL5bGQVp2wqS.', unhex('24326224313224387932654E7563583139566A6D5A33745968424C634F'), 'admin@example.com', 1, true, true, true, null, null, now(), now(), 1, now(), null), +(2, uuid(), 'test', '用户66666', '$2b$12$BMiXsNQAgTx7aNc7kVgnwedXGyUxPEHRnJMFbiikbqHgVoT3y14Za', unhex('24326224313224424D6958734E514167547837614E63376B56676E7765'), 'test@example.com', 1, false, false, false, null, null, now(), now(), 1, now(), null); insert into sys_user_role (id, user_id, role_id) values diff --git a/backend/sql/postgresql/init_snowflake_test_data.sql b/backend/sql/postgresql/init_snowflake_test_data.sql index d4f29081c..7bd20a92b 100644 --- a/backend/sql/postgresql/init_snowflake_test_data.sql +++ b/backend/sql/postgresql/init_snowflake_test_data.sql @@ -1,5 +1,5 @@ insert into sys_dept (id, name, sort, leader, phone, email, status, del_flag, parent_id, created_time, updated_time) -values (2048601264366944256, '测试', 0, null, null, null, 1, 0, null, now(), null); +values (2048601264366944256, '测试', 0, null, null, null, 1, false, null, 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 @@ -82,7 +82,7 @@ values (2049629108257816588, '写入', 'WriteGenCode', null, 0, null, 2, null, 'codegen:local:write', 1, 0, 1, '', null, 2049629108257816580, '2025-06-26 20:29:06', null); insert into sys_role (id, name, status, is_filter_scopes, remark, created_time, updated_time) -values (2048601269345583104, '测试', 1, 1, null, now(), null); +values (2048601269345583104, '测试', 1, true, null, now(), null); insert into sys_role_menu (id, role_id, menu_id) values @@ -91,10 +91,10 @@ values (2048601269546909696, 2048601269345583104, 2049629108245233666), (2048601269609824256, 2048601269345583104, 2049629108253622282); -insert into sys_user (id, uuid, username, nickname, password, salt, email, is_superuser, is_staff, status, is_multi_login, avatar, phone, join_time, last_login_time, dept_id, created_time, updated_time) +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, dept_id, created_time, updated_time) values -(2048601269672738816, gen_random_uuid(), 'admin', '用户88888', '$2b$12$8y2eNucX19VjmZ3tYhBLcOsBwy9w1IjBQE4SSqwMDL5bGQVp2wqS.', decode('24326224313224387932654E7563583139566A6D5A33745968424C634F', 'hex'), 'admin@example.com', 1, 1, 1, 1, null, null, now(), now(), 2048601264366944256, now(), null), -(2049946297615646720, gen_random_uuid(), 'test', '用户66666', '$2b$12$BMiXsNQAgTx7aNc7kVgnwedXGyUxPEHRnJMFbiikbqHgVoT3y14Za', decode('24326224313224424D6958734E514167547837614E63376B56676E7765', 'hex'), 'test@example.com', 0, 0, 1, 0, null, null, now(), now(), 2048601264366944256, now(), null); +(2048601269672738816, gen_random_uuid(), 'admin', '用户88888', '$2b$12$8y2eNucX19VjmZ3tYhBLcOsBwy9w1IjBQE4SSqwMDL5bGQVp2wqS.', decode('24326224313224387932654E7563583139566A6D5A33745968424C634F', 'hex'), 'admin@example.com', 1, true, true, true, null, null, now(), now(), 2048601264366944256, now(), null), +(2049946297615646720, gen_random_uuid(), 'test', '用户66666', '$2b$12$BMiXsNQAgTx7aNc7kVgnwedXGyUxPEHRnJMFbiikbqHgVoT3y14Za', decode('24326224313224424D6958734E514167547837614E63376B56676E7765', 'hex'), 'test@example.com', 1, false, false, false, null, null, now(), now(), 2048601264366944256, now(), null); insert into sys_user_role (id, user_id, role_id) values diff --git a/backend/sql/postgresql/init_test_data.sql b/backend/sql/postgresql/init_test_data.sql index 352b5a3c4..add2bfccf 100644 --- a/backend/sql/postgresql/init_test_data.sql +++ b/backend/sql/postgresql/init_test_data.sql @@ -1,5 +1,5 @@ insert into sys_dept (id, name, sort, leader, phone, email, status, del_flag, parent_id, created_time, updated_time) -values (1, '测试', 0, null, null, null, 1, 0, null, now(), null); +values (1, '测试', 0, null, null, null, 1, false, null, 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 @@ -82,7 +82,7 @@ values (77, '写入', 'WriteGenCode', null, 0, null, 2, null, 'codegen:local:write', 1, 0, 1, '', null, 69, '2025-06-26 20:29:06', null); insert into sys_role (id, name, status, is_filter_scopes, remark, created_time, updated_time) -values (1, '测试', 1, 1, null, now(), null); +values (1, '测试', 1, true, null, now(), null); insert into sys_role_menu (id, role_id, menu_id) values @@ -91,10 +91,10 @@ values (3, 1, 3), (4, 1, 53); -insert into sys_user (id, uuid, username, nickname, password, salt, email, is_superuser, is_staff, status, is_multi_login, avatar, phone, join_time, last_login_time, dept_id, created_time, updated_time) +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, dept_id, created_time, updated_time) values -(1, gen_random_uuid(), 'admin', '用户88888', '$2b$12$8y2eNucX19VjmZ3tYhBLcOsBwy9w1IjBQE4SSqwMDL5bGQVp2wqS.', decode('24326224313224387932654E7563583139566A6D5A33745968424C634F', 'hex'), 'admin@example.com', 1, 1, 1, 1, null, null, now(), now(), 1, now(), null), -(2, gen_random_uuid(), 'test', '用户66666', '$2b$12$BMiXsNQAgTx7aNc7kVgnwedXGyUxPEHRnJMFbiikbqHgVoT3y14Za', decode('24326224313224424D6958734E514167547837614E63376B56676E7765', 'hex'), 'test@example.com', 0, 0, 1, 0, null, null, now(), now(), 1, now(), null); +(1, gen_random_uuid(), 'admin', '用户88888', '$2b$12$8y2eNucX19VjmZ3tYhBLcOsBwy9w1IjBQE4SSqwMDL5bGQVp2wqS.', decode('24326224313224387932654E7563583139566A6D5A33745968424C634F', 'hex'), 'admin@example.com', 1, true, true, true, null, null, now(), now(), 1, now(), null), +(2, gen_random_uuid(), 'test', '用户66666', '$2b$12$BMiXsNQAgTx7aNc7kVgnwedXGyUxPEHRnJMFbiikbqHgVoT3y14Za', decode('24326224313224424D6958734E514167547837614E63376B56676E7765', 'hex'), 'test@example.com', 1, false, false, false, null, null, now(), now(), 1, now(), null); insert into sys_user_role (id, user_id, role_id) values @@ -117,7 +117,6 @@ values (2, 2, 1), (3, 2, 2); --- reset auto-increment values for each table based on max id 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;