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
8 changes: 4 additions & 4 deletions backend/app/admin/model/login_log.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@
# -*- coding: utf-8 -*-
from datetime import datetime

from sqlalchemy import DateTime, String
from sqlalchemy import String
from sqlalchemy.dialects.mysql import LONGTEXT
from sqlalchemy.dialects.postgresql import TEXT
from sqlalchemy.orm import Mapped, mapped_column

from backend.common.model import DataClassBase, id_key
from backend.common.model import DataClassBase, TimeZone, id_key
from backend.utils.timezone import timezone


Expand All @@ -29,7 +29,7 @@ class LoginLog(DataClassBase):
browser: Mapped[str | None] = mapped_column(String(50), comment='浏览器')
device: Mapped[str | None] = mapped_column(String(50), comment='设备')
msg: Mapped[str] = mapped_column(LONGTEXT().with_variant(TEXT, 'postgresql'), comment='提示消息')
login_time: Mapped[datetime] = mapped_column(DateTime(timezone=True), comment='登录时间')
login_time: Mapped[datetime] = mapped_column(TimeZone, comment='登录时间')
created_time: Mapped[datetime] = mapped_column(
DateTime(timezone=True), init=False, default_factory=timezone.now, comment='创建时间'
TimeZone, init=False, default_factory=timezone.now, comment='创建时间'
)
8 changes: 4 additions & 4 deletions backend/app/admin/model/opera_log.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@
# -*- coding: utf-8 -*-
from datetime import datetime

from sqlalchemy import DateTime, String
from sqlalchemy import String
from sqlalchemy.dialects.mysql import JSON, LONGTEXT
from sqlalchemy.dialects.postgresql import TEXT
from sqlalchemy.orm import Mapped, mapped_column

from backend.common.model import DataClassBase, id_key
from backend.common.model import DataClassBase, TimeZone, id_key
from backend.utils.timezone import timezone


Expand Down Expand Up @@ -35,7 +35,7 @@ class OperaLog(DataClassBase):
code: Mapped[str] = mapped_column(String(20), insert_default='200', comment='操作状态码')
msg: Mapped[str | None] = mapped_column(LONGTEXT().with_variant(TEXT, 'postgresql'), comment='提示消息')
cost_time: Mapped[float] = mapped_column(insert_default=0.0, comment='请求耗时(ms)')
opera_time: Mapped[datetime] = mapped_column(DateTime(timezone=True), comment='操作时间')
opera_time: Mapped[datetime] = mapped_column(TimeZone, comment='操作时间')
created_time: Mapped[datetime] = mapped_column(
DateTime(timezone=True), init=False, default_factory=timezone.now, comment='创建时间'
TimeZone, init=False, default_factory=timezone.now, comment='创建时间'
)
10 changes: 4 additions & 6 deletions backend/app/admin/model/user.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@
from datetime import datetime
from typing import TYPE_CHECKING

from sqlalchemy import VARBINARY, Boolean, DateTime, ForeignKey, String
from sqlalchemy import VARBINARY, Boolean, ForeignKey, String
from sqlalchemy.dialects.postgresql import BYTEA, INTEGER
from sqlalchemy.orm import Mapped, mapped_column, relationship

from backend.app.admin.model.m2m import sys_user_role
from backend.common.model import Base, id_key
from backend.common.model import Base, TimeZone, id_key
from backend.database.db import uuid4_str
from backend.utils.timezone import timezone

Expand Down Expand Up @@ -42,11 +42,9 @@ class User(Base):
is_multi_login: Mapped[bool] = mapped_column(
Boolean().with_variant(INTEGER, 'postgresql'), default=False, comment='是否重复登陆(0否 1是)'
)
join_time: Mapped[datetime] = mapped_column(
DateTime(timezone=True), init=False, default_factory=timezone.now, comment='注册时间'
)
join_time: Mapped[datetime] = mapped_column(TimeZone, init=False, default_factory=timezone.now, comment='注册时间')
last_login_time: Mapped[datetime | None] = mapped_column(
DateTime(timezone=True), init=False, onupdate=timezone.now, comment='上次登录'
TimeZone, init=False, onupdate=timezone.now, comment='上次登录'
)

# 部门用户一对多
Expand Down
11 changes: 4 additions & 7 deletions backend/app/task/model/scheduler.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
from sqlalchemy import (
JSON,
Boolean,
DateTime,
String,
event,
)
Expand All @@ -16,7 +15,7 @@
from sqlalchemy.orm import Mapped, mapped_column

from backend.common.exception import errors
from backend.common.model import Base, id_key
from backend.common.model import Base, TimeZone, id_key
from backend.core.conf import settings
from backend.database.redis import redis_client
from backend.utils.timezone import timezone
Expand All @@ -35,8 +34,8 @@ class TaskScheduler(Base):
queue: Mapped[str | None] = mapped_column(String(255), comment='CELERY_TASK_QUEUES 中定义的队列')
exchange: Mapped[str | None] = mapped_column(String(255), comment='低级别 AMQP 路由的交换机')
routing_key: Mapped[str | None] = mapped_column(String(255), comment='低级别 AMQP 路由的路由密钥')
start_time: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), comment='任务开始触发的时间')
expire_time: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), comment='任务不再触发的截止时间')
start_time: Mapped[datetime | None] = mapped_column(TimeZone, comment='任务开始触发的时间')
expire_time: Mapped[datetime | None] = mapped_column(TimeZone, comment='任务不再触发的截止时间')
expire_seconds: Mapped[int | None] = mapped_column(comment='任务不再触发的秒数时间差')
type: Mapped[int] = mapped_column(comment='调度类型(0间隔 1定时)')
interval_every: Mapped[int | None] = mapped_column(comment='任务再次运行前的间隔周期数')
Expand All @@ -49,9 +48,7 @@ class TaskScheduler(Base):
Boolean().with_variant(INTEGER, 'postgresql'), default=True, comment='是否启用任务'
)
total_run_count: Mapped[int] = mapped_column(default=0, comment='任务触发的总次数')
last_run_time: Mapped[datetime | None] = mapped_column(
DateTime(timezone=True), default=None, comment='任务最后触发的时间'
)
last_run_time: Mapped[datetime | None] = mapped_column(TimeZone, default=None, comment='任务最后触发的时间')
remark: Mapped[str | None] = mapped_column(
LONGTEXT().with_variant(TEXT, 'postgresql'), default=None, comment='备注'
)
Expand Down
29 changes: 26 additions & 3 deletions backend/common/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from datetime import datetime
from typing import Annotated

from sqlalchemy import BigInteger, DateTime
from sqlalchemy import BigInteger, DateTime, TypeDecorator
from sqlalchemy.ext.asyncio import AsyncAttrs
from sqlalchemy.orm import DeclarativeBase, Mapped, MappedAsDataclass, declared_attr, mapped_column

Expand Down Expand Up @@ -51,14 +51,37 @@ class UserMixin(MappedAsDataclass):
updated_by: Mapped[int | None] = mapped_column(init=False, default=None, sort_order=998, comment='修改者')


class TimeZone(TypeDecorator[datetime]):
"""时区感知 DateTime"""

impl = DateTime(timezone=True)
cache_ok = True

@property
def python_type(self) -> type[datetime]:
return datetime

def process_bind_param(self, value: datetime | None, dialect) -> datetime | None:
if value is not None:
if value.tzinfo != timezone.tz_info:
value = timezone.from_datetime(value)
return value

def process_result_value(self, value: datetime | None, dialect) -> datetime | None:
if value is not None:
if value.tzinfo is None:
value = value.replace(tzinfo=timezone.tz_info)
return value


class DateTimeMixin(MappedAsDataclass):
"""日期时间 Mixin 数据类"""

created_time: Mapped[datetime] = mapped_column(
DateTime(timezone=True), init=False, default_factory=timezone.now, sort_order=999, comment='创建时间'
TimeZone, init=False, default_factory=timezone.now, sort_order=999, comment='创建时间'
)
updated_time: Mapped[datetime | None] = mapped_column(
DateTime(timezone=True), init=False, onupdate=timezone.now, sort_order=999, comment='更新时间'
TimeZone, init=False, onupdate=timezone.now, sort_order=999, comment='更新时间'
)


Expand Down
2 changes: 1 addition & 1 deletion backend/common/schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ class SchemaBase(BaseModel):
use_enum_values=True,
json_encoders={
datetime: lambda x: timezone.to_str(timezone.from_datetime(x))
if x.tzinfo is not None
if x.tzinfo is not None and x.tzinfo != timezone.tz_info
else timezone.to_str(x)
},
)