diff --git a/alembic/versions/d24d89a9d9fa_users_create_type.py b/alembic/versions/d24d89a9d9fa_users_create_type.py new file mode 100644 index 0000000..183812a --- /dev/null +++ b/alembic/versions/d24d89a9d9fa_users_create_type.py @@ -0,0 +1,30 @@ +"""users_create_type + +Revision ID: d24d89a9d9fa +Revises: a41d2f3443c8 +Create Date: 2024-11-13 14:04:54.681837 + +""" + +from alembic import op +import sqlalchemy as sa +import sqlmodel + + +# revision identifiers, used by Alembic. +revision = "d24d89a9d9fa" +down_revision = "a41d2f3443c8" +branch_labels = None +depends_on = None + + +def upgrade() -> None: + # ### commands auto generated by Alembic - please adjust! ### + op.add_column("auth_user", sa.Column("create_type", sa.Integer(), nullable=True)) + # ### end Alembic commands ### + + +def downgrade() -> None: + # ### commands auto generated by Alembic - please adjust! ### + op.drop_column("auth_user", "create_type") + # ### end Alembic commands ### diff --git a/src/frontend/sa-view/user/user-list.html b/src/frontend/sa-view/user/user-list.html index 4cbaf0e..b7ce748 100644 --- a/src/frontend/sa-view/user/user-list.html +++ b/src/frontend/sa-view/user/user-list.html @@ -32,6 +32,19 @@ +
+
+ + +
+
+ + +
+
+ + +
- @@ -41,6 +54,17 @@ 查询

+
+ + + 所有 + 学号注册 + 手机号注册 + 管理员手动添加 + 管理员批量导入 + +
+
@@ -122,6 +146,9 @@ username: '', nickname: '', real_name: '', + email: '', + phone: '', + student_id: '', create_type: 0, sortType: 1, start_time: new Date().getFullYear() + '-' + (new Date().getMonth() + 1) + '-1', // 本月一号 diff --git a/src/route/users.py b/src/route/users.py index c691207..26f3462 100644 --- a/src/route/users.py +++ b/src/route/users.py @@ -16,6 +16,7 @@ from src.services.users.schemas import ( SystemUserEnum, UserLoginOut, UserRoleEnum, + CreateTypeEnum, ) from src.services.users.services import UserServices, UserRoleServices @@ -40,6 +41,7 @@ class UserRoutes(Plugin): if user: return BaseApiOut(status=500, msg="用户名已被注册") role = UserRoleEnum.STUDENT.value + create_type = CreateTypeEnum.STUDENT if not (data.student_id or data.phone): return BaseApiOut(status=500, msg="学号或手机号至少填写一项") if data.student_id: @@ -47,11 +49,13 @@ class UserRoutes(Plugin): if user: return BaseApiOut(status=500, msg="学号已被注册") role = UserRoleEnum.STUDENT.value + create_type = CreateTypeEnum.STUDENT if data.phone: user = await self.user_services.get_user(phone=data.phone) if user: return BaseApiOut(status=500, msg="手机号已被注册") role = UserRoleEnum.OUT.value + create_type = CreateTypeEnum.PHONE # 检查通过,注册用户 try: user = await self.user_services.register_user( @@ -60,6 +64,7 @@ class UserRoutes(Plugin): student_id=data.student_id, phone=data.phone, real_name=data.real_name, + create_type=create_type.value, ) if not await self.user_role_services.is_user_in_role_group( data.username, role diff --git a/src/route/users_admin.py b/src/route/users_admin.py index 7e9b10c..a9a1652 100644 --- a/src/route/users_admin.py +++ b/src/route/users_admin.py @@ -20,6 +20,8 @@ class UserRoutes(Plugin): @handler.post("/list", student=True) async def get_user_list(self, data: UserList): username, nickname, real_name = data.username, data.nickname, data.real_name + email, phone, student_id = data.email, data.phone, data.student_id + create_type = data.create_type.value start_time, end_time = data.start, data.end page_no, page_size = data.pageNo, data.pageSize if page_no < 1: @@ -31,6 +33,10 @@ class UserRoutes(Plugin): username, nickname, real_name, + email, + phone, + student_id, + create_type, start_time, end_time, page_no, diff --git a/src/services/users/models.py b/src/services/users/models.py index e216786..2c8a31e 100644 --- a/src/services/users/models.py +++ b/src/services/users/models.py @@ -11,6 +11,7 @@ __all__ = [ "PhoneMixin", "RealNameMixin", "SexMixin", + "CreateTypeMixin", ] @@ -30,7 +31,28 @@ class SexMixin(SQLModel): sex: Optional[str] = Field("", title="性别", max_length=15) +class CreateTypeMixin(SQLModel): + """ + 1. 学号注册 + 2. 手机号注册 + 3. 管理员手动添加 + 4. 管理员批量导入 + """ + + create_type: Optional[int] = Field( + default=None, + title="create_type", + nullable=True, + ) + + class UserModel( - BaseUser, StudentIdMixin, PhoneMixin, RealNameMixin, SexMixin, table=True + BaseUser, + StudentIdMixin, + PhoneMixin, + RealNameMixin, + SexMixin, + CreateTypeMixin, + table=True, ): __table_args__ = {"extend_existing": True} diff --git a/src/services/users/repositories.py b/src/services/users/repositories.py index 4cad8db..42915a8 100644 --- a/src/services/users/repositories.py +++ b/src/services/users/repositories.py @@ -46,6 +46,7 @@ class UserRepo(AsyncInitializingComponent): student_id: Optional[str], phone: Optional[str], real_name: Optional[str], + create_type: int, ): password = self.AUTH.pwd_context.hash(password.get_secret_value()) values = { @@ -54,6 +55,7 @@ class UserRepo(AsyncInitializingComponent): "student_id": student_id, "phone": phone, "real_name": real_name, + "create_type": create_type, } user = self.user_model.model_validate(values) async with AsyncSession(self.engine) as session: @@ -153,6 +155,10 @@ class UserRepo(AsyncInitializingComponent): username: str, nickname: str, real_name: str, + email: str, + phone: str, + student_id: str, + create_type: int, start_time: datetime, end_time: datetime, page_no: int, @@ -172,6 +178,20 @@ class UserRepo(AsyncInitializingComponent): statement = statement.where( col(self.user_model.real_name).like(f"%{real_name}%") ) + if email: + statement = statement.where( + col(self.user_model.email).like(f"%{email}%") + ) + if phone: + statement = statement.where( + col(self.user_model.phone).like(f"%{phone}%") + ) + if student_id: + statement = statement.where( + col(self.user_model.student_id).like(f"%{student_id}%") + ) + if create_type: + statement = statement.where(self.user_model.create_type == create_type) if start_time: statement = statement.where(self.user_model.create_time >= start_time) if end_time: diff --git a/src/services/users/schemas.py b/src/services/users/schemas.py index 4af67b7..bda355f 100644 --- a/src/services/users/schemas.py +++ b/src/services/users/schemas.py @@ -110,11 +110,23 @@ class UserRoleEnum(str, Enum): OUT = "out" # 校外人员 +class CreateTypeEnum(int, Enum): + ALL = 0 + STUDENT = 1 + PHONE = 2 + ADMIN = 3 + ADMIN_MULT = 4 + + class UserList(BaseModel): username: str = "" nickname: str = "" real_name: str = "" + email: str = "" + phone: str = "" + student_id: str = "" + create_type: CreateTypeEnum = CreateTypeEnum.ALL sortType: int = 1 start_time: str end_time: str diff --git a/src/services/users/services.py b/src/services/users/services.py index 3a9ed53..43fe30c 100644 --- a/src/services/users/services.py +++ b/src/services/users/services.py @@ -26,6 +26,7 @@ class UserServices(AsyncInitializingComponent): student_id: Optional[str], phone: Optional[str], real_name: Optional[str], + create_type: int = 0, ): return await self.repo.register_user( username, @@ -33,6 +34,7 @@ class UserServices(AsyncInitializingComponent): student_id, phone, real_name, + create_type, ) async def login_user(self, user: "UserModel") -> str: @@ -102,13 +104,27 @@ class UserServices(AsyncInitializingComponent): username: str, nickname: str, real_name: str, + email: str, + phone: str, + student_id: str, + create_type: int, start_time: datetime, end_time: datetime, page_no: int, page_size: int, ) -> Tuple[Sequence[UserModel], int]: return await self.repo.get_user_list( - username, nickname, real_name, start_time, end_time, page_no, page_size + username, + nickname, + real_name, + email, + phone, + student_id, + create_type, + start_time, + end_time, + page_no, + page_size, )