Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions backend/app/admin/crud/crud_dept.py
Original file line number Diff line number Diff line change
Expand Up @@ -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:
"""
Expand All @@ -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,
Expand All @@ -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}%'
Expand Down
5 changes: 1 addition & 4 deletions backend/app/admin/model/dept.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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(
Expand Down
5 changes: 2 additions & 3 deletions backend/app/admin/model/login_log.py
Original file line number Diff line number Diff line change
Expand Up @@ -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


Expand All @@ -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,
Expand Down
9 changes: 3 additions & 6 deletions backend/app/admin/model/menu.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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(
Expand Down
5 changes: 2 additions & 3 deletions backend/app/admin/model/opera_log.py
Original file line number Diff line number Diff line change
Expand Up @@ -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


Expand All @@ -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(
Expand Down
9 changes: 3 additions & 6 deletions backend/app/admin/model/role.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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')
Expand Down
18 changes: 5 additions & 13 deletions backend/app/admin/model/user.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -28,28 +26,22 @@ 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='上次登录'
)

# 部门用户一对多
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')

Expand Down
13 changes: 4 additions & 9 deletions backend/app/task/model/scheduler.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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

Expand Down
2 changes: 1 addition & 1 deletion backend/app/task/utils/schedulers.py
Original file line number Diff line number Diff line change
Expand Up @@ -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 = {}
Expand Down
29 changes: 22 additions & 7 deletions backend/common/model.py
Original file line number Diff line number Diff line change
@@ -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

Expand Down Expand Up @@ -41,16 +43,21 @@
]


# Mixin: 一种面向对象编程概念, 使结构变得更加清晰, `Wiki <https://en.wikipedia.org/wiki/Mixin/>`__
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
Expand All @@ -71,6 +78,14 @@ def process_result_value(self, value: datetime | None, dialect) -> datetime | No
return value


# Mixin: 一种面向对象编程概念, 使结构变得更加清晰, `Wiki <https://en.wikipedia.org/wiki/Mixin/>`__
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 数据类"""

Expand Down
5 changes: 2 additions & 3 deletions backend/plugin/code_generator/model/business.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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')
7 changes: 2 additions & 5 deletions backend/plugin/code_generator/model/column.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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='是否主键')
Expand Down
11 changes: 4 additions & 7 deletions backend/plugin/config/model/config.py
Original file line number Diff line number Diff line change
@@ -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):
Expand All @@ -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='备注')
12 changes: 6 additions & 6 deletions backend/plugin/config/sql/mysql/init.sql
Original file line number Diff line number Diff line change
@@ -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', '[email protected]', 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', '[email protected]', false, null, now(), null),
(5, '邮箱密码', 'EMAIL', 'EMAIL_PASSWORD', '', false, null, now(), null),
(6, 'SSL 加密', 'EMAIL', 'EMAIL_SSL', '1', false, null, now(), null);
12 changes: 6 additions & 6 deletions backend/plugin/config/sql/mysql/init_snowflake.sql
Original file line number Diff line number Diff line change
@@ -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', '[email protected]', 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', '[email protected]', false, null, now(), null),
(2069061886627938308, '邮箱密码', 'EMAIL', 'EMAIL_PASSWORD', '', false, null, now(), null),
(2069061886627938309, 'SSL 加密', 'EMAIL', 'EMAIL_SSL', '1', false, null, now(), null);
Loading