mirror of
https://github.com/fastapiadmin/FastapiAdmin.git
synced 2026-09-21 04:46:26 +00:00
refactor: 大规模代码重构与项目配置优化
- 调整前端路由前缀为 /web 并新增配置项 - 重构环境变量配置,替换旧环境文件为 dev/prod/test 版本 - 优化后端接口路由与参数校验,替换 dataclass 查询参数为 Pydantic 模型 - 整理后端导入顺序,延迟加载循环依赖模块 - 统一前端 API 调用命名,重构模块命名 - 新增多种响应类型支持,优化代码模板 - 简化后端路由装饰器写法,合并配置参数
This commit is contained in:
@@ -2,14 +2,14 @@ import json
|
||||
import secrets
|
||||
from typing import Annotated
|
||||
|
||||
from fastapi import APIRouter, BackgroundTasks, Body, Depends, Form, Path, Query, Request
|
||||
from fastapi import APIRouter, BackgroundTasks, Body, Depends, Path, Query, Request
|
||||
from fastapi.responses import JSONResponse, RedirectResponse
|
||||
from fastapi_cache import FastAPICache
|
||||
from fastapi_cache.decorator import cache
|
||||
from redis.asyncio.client import Redis
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from app.common.response import ErrorResponse, ResponseSchema, SuccessResponse
|
||||
from app.common.response import ErrorResponse, RedirectContentResponse, ResponseSchema, SuccessResponse
|
||||
from app.config.setting import settings
|
||||
from app.core.base_schema import (
|
||||
AuthSchema,
|
||||
@@ -56,17 +56,13 @@ AuthRouter = APIRouter(route_class=OperationLogRoute, prefix="/auth", tags=["认
|
||||
_AUTH_TENANTS_NS = "auth_tenants"
|
||||
|
||||
|
||||
@AuthRouter.post(
|
||||
"/login",
|
||||
summary="登录",
|
||||
response_model=LoginWithTenantsSchema,
|
||||
)
|
||||
@AuthRouter.post("/login", summary="登录", response_model=LoginWithTenantsSchema)
|
||||
async def login_for_access_token_controller(
|
||||
request: Request,
|
||||
background_tasks: BackgroundTasks,
|
||||
redis: Annotated[Redis, Depends(redis_getter)],
|
||||
db: Annotated[AsyncSession, Depends(db_getter)],
|
||||
login_form: Annotated[CustomOAuth2PasswordRequestForm, Form(description="登录表单")],
|
||||
login_form: Annotated[CustomOAuth2PasswordRequestForm, Depends()],
|
||||
) -> JSONResponse | dict:
|
||||
login_result = await LoginService.authenticate_user(
|
||||
request=request, redis=redis, login_form=login_form, db=db, background_tasks=background_tasks
|
||||
@@ -79,11 +75,7 @@ async def login_for_access_token_controller(
|
||||
return SuccessResponse(data=login_result, msg="登录成功")
|
||||
|
||||
|
||||
@AuthRouter.post(
|
||||
"/token/refresh",
|
||||
summary="刷新token",
|
||||
response_model=ResponseSchema[JWTOutSchema],
|
||||
)
|
||||
@AuthRouter.post("/token/refresh", summary="刷新token", response_model=ResponseSchema[JWTOutSchema])
|
||||
async def get_new_token_controller(
|
||||
db: Annotated[AsyncSession, Depends(db_getter)],
|
||||
redis: Annotated[Redis, Depends(redis_getter)],
|
||||
@@ -93,11 +85,7 @@ async def get_new_token_controller(
|
||||
return SuccessResponse(data=new_token, msg="刷新成功")
|
||||
|
||||
|
||||
@AuthRouter.get(
|
||||
"/captcha/get",
|
||||
summary="获取验证码",
|
||||
response_model=ResponseSchema[CaptchaOutSchema],
|
||||
)
|
||||
@AuthRouter.get("/captcha/get", summary="获取验证码", response_model=ResponseSchema[CaptchaOutSchema])
|
||||
async def get_captcha_for_login_controller(
|
||||
redis: Annotated[Redis, Depends(redis_getter)],
|
||||
) -> JSONResponse:
|
||||
@@ -105,12 +93,7 @@ async def get_captcha_for_login_controller(
|
||||
return SuccessResponse(data=captcha, msg="获取验证码成功")
|
||||
|
||||
|
||||
@AuthRouter.post(
|
||||
"/logout",
|
||||
summary="退出登录",
|
||||
dependencies=[Depends(get_current_user)],
|
||||
response_model=ResponseSchema[None],
|
||||
)
|
||||
@AuthRouter.post("/logout", summary="退出登录", response_model=ResponseSchema[None], dependencies=[Depends(get_current_user)])
|
||||
async def logout_controller(
|
||||
redis: Annotated[Redis, Depends(redis_getter)],
|
||||
payload: Annotated[LogoutPayloadSchema, Body(description="退出登录参数")],
|
||||
@@ -121,11 +104,7 @@ async def logout_controller(
|
||||
return ErrorResponse(msg="退出失败")
|
||||
|
||||
|
||||
@AuthRouter.get(
|
||||
"/auto-login/users",
|
||||
summary="获取免登录用户列表",
|
||||
response_model=ResponseSchema[list[AutoLoginUserSchema]],
|
||||
)
|
||||
@AuthRouter.get("/auto-login/users", summary="获取免登录用户列表", response_model=ResponseSchema[list[AutoLoginUserSchema]])
|
||||
async def get_auto_login_users_controller(
|
||||
auth: Annotated[AuthSchema, Depends(get_current_user)],
|
||||
db: Annotated[AsyncSession, Depends(db_getter)],
|
||||
@@ -135,11 +114,7 @@ async def get_auto_login_users_controller(
|
||||
return SuccessResponse(data=users, msg="获取成功")
|
||||
|
||||
|
||||
@AuthRouter.post(
|
||||
"/auto-login/token",
|
||||
summary="获取免登录Token",
|
||||
response_model=ResponseSchema[AutoLoginTokenSchema],
|
||||
)
|
||||
@AuthRouter.post("/auto-login/token", summary="获取免登录Token", response_model=ResponseSchema[AutoLoginTokenSchema])
|
||||
async def get_auto_login_token_controller(
|
||||
auth: Annotated[AuthSchema, Depends(get_current_user)],
|
||||
redis: Annotated[Redis, Depends(redis_getter)],
|
||||
@@ -151,11 +126,7 @@ async def get_auto_login_token_controller(
|
||||
return SuccessResponse(data=result, msg="获取成功")
|
||||
|
||||
|
||||
@AuthRouter.post(
|
||||
"/auto-login",
|
||||
summary="免登录",
|
||||
response_model=ResponseSchema[JWTOutSchema],
|
||||
)
|
||||
@AuthRouter.post("/auto-login", summary="免登录", response_model=ResponseSchema[JWTOutSchema])
|
||||
async def auto_login_controller(
|
||||
request: Request,
|
||||
redis: Annotated[Redis, Depends(redis_getter)],
|
||||
@@ -167,12 +138,7 @@ async def auto_login_controller(
|
||||
return SuccessResponse(data=login_token, msg="登录成功")
|
||||
|
||||
|
||||
@AuthRouter.post(
|
||||
"/select-tenant",
|
||||
summary="选择租户",
|
||||
response_model=ResponseSchema[SelectTenantOutSchema],
|
||||
dependencies=[Depends(get_current_user)],
|
||||
)
|
||||
@AuthRouter.post("/select-tenant", summary="选择租户", response_model=ResponseSchema[SelectTenantOutSchema], dependencies=[Depends(get_current_user)])
|
||||
async def select_tenant_controller(
|
||||
request: Request,
|
||||
auth: Annotated[AuthSchema, Depends(get_current_user)],
|
||||
@@ -184,12 +150,7 @@ async def select_tenant_controller(
|
||||
return SuccessResponse(data=result, msg="租户切换成功")
|
||||
|
||||
|
||||
@AuthRouter.get(
|
||||
"/tenants",
|
||||
summary="获取可选租户列表",
|
||||
response_model=ResponseSchema[list[TenantOptionSchema]],
|
||||
dependencies=[Depends(get_current_user)],
|
||||
)
|
||||
@AuthRouter.get("/tenants", summary="获取可选租户列表", response_model=ResponseSchema[list[TenantOptionSchema]], dependencies=[Depends(get_current_user)])
|
||||
@cache(expire=120, namespace=_AUTH_TENANTS_NS)
|
||||
async def get_user_tenants_controller(
|
||||
auth: Annotated[AuthSchema, Depends(get_current_user)],
|
||||
@@ -199,10 +160,7 @@ async def get_user_tenants_controller(
|
||||
return SuccessResponse(data=tenants, msg="获取租户列表成功")
|
||||
|
||||
|
||||
@AuthRouter.get(
|
||||
"/oauth/{provider}/login",
|
||||
summary="第三方OAuth跳转",
|
||||
)
|
||||
@AuthRouter.get("/oauth/{provider}/login", summary="第三方OAuth跳转", response_model=RedirectContentResponse[None])
|
||||
async def oauth_login_redirect_controller(
|
||||
request: Request,
|
||||
redis: Annotated[Redis, Depends(redis_getter)],
|
||||
@@ -212,12 +170,12 @@ async def oauth_login_redirect_controller(
|
||||
allowed = {"wechat", "qq", "github", "gitee"}
|
||||
fe = redirect_uri or settings.OAUTH_FRONTEND_FALLBACK
|
||||
if provider not in allowed:
|
||||
return RedirectResponse(
|
||||
return RedirectContentResponse(
|
||||
url=oauth_service_error_redirect(fe, "不支持的 OAuth 渠道"),
|
||||
status_code=302,
|
||||
)
|
||||
if not redirect_uri:
|
||||
return RedirectResponse(
|
||||
return RedirectContentResponse(
|
||||
url=oauth_service_error_redirect(fe, "缺少 redirect_uri 参数"),
|
||||
status_code=302,
|
||||
)
|
||||
@@ -231,19 +189,15 @@ async def oauth_login_redirect_controller(
|
||||
)
|
||||
cb = _callback_url(request, provider)
|
||||
url = build_authorize_url(provider=provider, callback_url=cb, state=state)
|
||||
return RedirectResponse(url=url, status_code=302)
|
||||
return RedirectContentResponse(url=url, status_code=302)
|
||||
except CustomException as e:
|
||||
return RedirectResponse(
|
||||
return RedirectContentResponse(
|
||||
url=oauth_service_error_redirect(redirect_uri, e.msg),
|
||||
status_code=302,
|
||||
)
|
||||
|
||||
|
||||
@AuthRouter.get(
|
||||
"/oauth/{provider}/callback",
|
||||
summary="第三方OAuth回调",
|
||||
include_in_schema=False,
|
||||
)
|
||||
@AuthRouter.get("/oauth/{provider}/callback", summary="第三方OAuth回调", include_in_schema=False, response_model=RedirectContentResponse[None])
|
||||
async def oauth_callback_controller(
|
||||
request: Request,
|
||||
redis: Annotated[Redis, Depends(redis_getter)],
|
||||
@@ -270,10 +224,10 @@ async def oauth_callback_controller(
|
||||
|
||||
if provider not in {"wechat", "qq", "github", "gitee"}:
|
||||
url = oauth_service_error_redirect(await resolve_frontend(), "不支持的 OAuth 渠道")
|
||||
return RedirectResponse(url=url, status_code=302)
|
||||
return RedirectContentResponse(url=url, status_code=302)
|
||||
if not code or not state:
|
||||
url = oauth_service_error_redirect(await resolve_frontend(), "授权被取消或参数不完整")
|
||||
return RedirectResponse(url=url, status_code=302)
|
||||
return RedirectContentResponse(url=url, status_code=302)
|
||||
try:
|
||||
token, fe = await complete_oauth_login(
|
||||
request=request,
|
||||
@@ -284,17 +238,13 @@ async def oauth_callback_controller(
|
||||
state=state,
|
||||
)
|
||||
success_url = oauth_service_frontend_redirect_from_token(fe, token)
|
||||
return RedirectResponse(url=success_url, status_code=302)
|
||||
return RedirectContentResponse(url=success_url, status_code=302)
|
||||
except CustomException as e:
|
||||
fe = await resolve_frontend()
|
||||
return RedirectResponse(url=oauth_service_error_redirect(fe, e.msg), status_code=302)
|
||||
return RedirectContentResponse(url=oauth_service_error_redirect(fe, e.msg), status_code=302)
|
||||
|
||||
|
||||
@AuthRouter.post(
|
||||
"/tenant/register",
|
||||
summary="租户自助注册",
|
||||
response_model=ResponseSchema[TenantRegisterOutSchema],
|
||||
)
|
||||
@AuthRouter.post("/tenant/register", summary="租户自助注册", response_model=ResponseSchema[TenantRegisterOutSchema])
|
||||
async def tenant_register_controller(
|
||||
db: Annotated[AsyncSession, Depends(db_getter)],
|
||||
data: Annotated[TenantRegisterSchema, Body(description="租户注册参数")],
|
||||
@@ -308,6 +258,3 @@ async def tenant_register_controller(
|
||||
)
|
||||
logger.info(f"新租户注册: username={data.username} tenant={result.tenant_name}")
|
||||
return SuccessResponse(data=result, msg=result.message)
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -17,11 +17,7 @@ DeptRouter = APIRouter(route_class=OperationLogRoute, prefix="/dept", tags=["部
|
||||
|
||||
_DEPT_NS = "dept"
|
||||
|
||||
@DeptRouter.get(
|
||||
"/tree",
|
||||
summary="查询部门树",
|
||||
response_model=ResponseSchema[list[DeptOutSchema]],
|
||||
)
|
||||
@DeptRouter.get("/tree", summary="查询部门树", response_model=ResponseSchema[list[DeptOutSchema]])
|
||||
@cache(expire=300, namespace=_DEPT_NS)
|
||||
async def get_dept_tree_controller(
|
||||
auth: Annotated[AuthSchema, Depends(AuthPermission(["module_system:dept:query"]))],
|
||||
@@ -31,11 +27,7 @@ async def get_dept_tree_controller(
|
||||
result_dict_tree = await DeptService(auth).tree(search=search, order_by=order_by)
|
||||
return SuccessResponse(data=result_dict_tree, msg="查询部门树成功")
|
||||
|
||||
@DeptRouter.get(
|
||||
"/detail/{id}",
|
||||
summary="查询部门详情",
|
||||
response_model=ResponseSchema[DeptOutSchema],
|
||||
)
|
||||
@DeptRouter.get("/detail/{id}", summary="查询部门详情", response_model=ResponseSchema[DeptOutSchema])
|
||||
async def get_obj_detail_controller(
|
||||
auth: Annotated[AuthSchema, Depends(AuthPermission(["module_system:dept:detail"]))],
|
||||
id: Annotated[int, Path(description="部门ID")],
|
||||
@@ -43,11 +35,7 @@ async def get_obj_detail_controller(
|
||||
result_dict = await DeptService(auth).detail(id=id)
|
||||
return SuccessResponse(data=result_dict, msg="查询部门详情成功")
|
||||
|
||||
@DeptRouter.post(
|
||||
"/create",
|
||||
summary="创建部门",
|
||||
response_model=ResponseSchema[DeptOutSchema],
|
||||
)
|
||||
@DeptRouter.post("/create", summary="创建部门", response_model=ResponseSchema[DeptOutSchema])
|
||||
async def create_obj_controller(
|
||||
auth: Annotated[AuthSchema, Depends(AuthPermission(["module_system:dept:create"]))],
|
||||
data: Annotated[DeptCreateSchema, Body(description="部门创建参数")],
|
||||
@@ -56,11 +44,7 @@ async def create_obj_controller(
|
||||
await FastAPICache.clear(namespace=_DEPT_NS)
|
||||
return SuccessResponse(data=result_dict, msg="创建部门成功")
|
||||
|
||||
@DeptRouter.put(
|
||||
"/update/{id}",
|
||||
summary="修改部门",
|
||||
response_model=ResponseSchema[DeptOutSchema],
|
||||
)
|
||||
@DeptRouter.put("/update/{id}", summary="修改部门", response_model=ResponseSchema[DeptOutSchema])
|
||||
async def update_obj_controller(
|
||||
auth: Annotated[AuthSchema, Depends(AuthPermission(["module_system:dept:update"]))],
|
||||
id: Annotated[int, Path(description="部门ID")],
|
||||
@@ -70,11 +54,7 @@ async def update_obj_controller(
|
||||
await FastAPICache.clear(namespace=_DEPT_NS)
|
||||
return SuccessResponse(data=result_dict, msg="修改部门成功")
|
||||
|
||||
@DeptRouter.delete(
|
||||
"/delete",
|
||||
summary="删除部门",
|
||||
response_model=ResponseSchema[None],
|
||||
)
|
||||
@DeptRouter.delete("/delete", summary="删除部门", response_model=ResponseSchema[None])
|
||||
async def delete_obj_controller(
|
||||
auth: Annotated[AuthSchema, Depends(AuthPermission(["module_system:dept:delete"]))],
|
||||
ids: Annotated[list[int], Body(description="ID列表")],
|
||||
@@ -83,11 +63,7 @@ async def delete_obj_controller(
|
||||
await FastAPICache.clear(namespace=_DEPT_NS)
|
||||
return SuccessResponse(msg="删除部门成功")
|
||||
|
||||
@DeptRouter.patch(
|
||||
"/status/batch",
|
||||
summary="批量修改部门状态",
|
||||
response_model=ResponseSchema[None],
|
||||
)
|
||||
@DeptRouter.patch("/status/batch", summary="批量修改部门状态", response_model=ResponseSchema[None])
|
||||
async def batch_set_available_obj_controller(
|
||||
auth: Annotated[AuthSchema, Depends(AuthPermission(["module_system:dept:patch"]))],
|
||||
data: Annotated[BatchSetAvailable, Body(description="状态设置")],
|
||||
|
||||
@@ -1,11 +1,7 @@
|
||||
from dataclasses import dataclass
|
||||
|
||||
from fastapi import Query
|
||||
from pydantic import BaseModel, ConfigDict, Field, field_validator
|
||||
from pydantic import BaseModel, ConfigDict, Field, field_validator, model_validator
|
||||
|
||||
from app.common.enums import QueueEnum
|
||||
from app.core.base_params import BaseQueryParam, TenantByQueryParam, UserByQueryParam
|
||||
from app.core.base_schema import BaseSchema, TenantBySchema, UserBySchema
|
||||
from app.core.base_schema import BaseQueryParam, BaseSchema, TenantByQueryParam, TenantBySchema, UserByQueryParam, UserBySchema
|
||||
from app.core.validator import validate_required_code
|
||||
|
||||
|
||||
@@ -63,14 +59,16 @@ class DeptTreeOutSchema(DeptOutSchema):
|
||||
children: list["DeptTreeOutSchema"] | None = Field(default=None, description="子部门列表")
|
||||
|
||||
|
||||
@dataclass
|
||||
class DeptQueryParam(BaseQueryParam, UserByQueryParam, TenantByQueryParam):
|
||||
"""部门管理查询参数"""
|
||||
|
||||
name: str | None = Query(None, description="部门名称")
|
||||
status: int | None = Query(None, ge=0, le=1, description="状态(0:启动 1:停用)")
|
||||
name: str | None = Field(None, description="部门名称")
|
||||
status: int | None = Field(None, ge=0, le=1, description="状态(0:启动 1:停用)")
|
||||
|
||||
def __post_init__(self) -> None:
|
||||
self.name = (QueueEnum.like.value, self.name)
|
||||
@model_validator(mode="after")
|
||||
def validate_query_params(self) -> "DeptQueryParam":
|
||||
if self.name:
|
||||
self.name = (QueueEnum.like.value, self.name)
|
||||
if isinstance(self.status, int):
|
||||
self.status = (QueueEnum.eq.value, self.status)
|
||||
return self
|
||||
|
||||
@@ -7,8 +7,7 @@ from fastapi_cache.decorator import cache
|
||||
from redis.asyncio.client import Redis
|
||||
|
||||
from app.common.response import ResponseSchema, StreamResponse, SuccessResponse
|
||||
from app.core.base_params import PaginationQueryParam
|
||||
from app.core.base_schema import AuthSchema, BatchSetAvailable, PageResultSchema
|
||||
from app.core.base_schema import AuthSchema, BatchSetAvailable, PageResultSchema, PaginationQueryParam
|
||||
from app.core.dependencies import AuthPermission, redis_getter
|
||||
from app.core.router_class import OperationLogRoute
|
||||
from app.utils.common_util import bytes2file_response
|
||||
@@ -29,11 +28,7 @@ DictRouter = APIRouter(route_class=OperationLogRoute, prefix="/dict", tags=["字
|
||||
|
||||
_DICT_TYPE_NS = "dict_type"
|
||||
|
||||
@DictRouter.get(
|
||||
"/type/detail/{id}",
|
||||
summary="获取字典类型详情",
|
||||
response_model=ResponseSchema[DictTypeOutSchema],
|
||||
)
|
||||
@DictRouter.get("/type/detail/{id}", summary="获取字典类型详情", response_model=ResponseSchema[DictTypeOutSchema])
|
||||
async def get_type_detail_controller(
|
||||
auth: Annotated[AuthSchema, Depends(AuthPermission(["module_system:dict_type:detail"]))],
|
||||
id: Annotated[int, Path(description="字典类型ID", ge=1)],
|
||||
@@ -41,11 +36,7 @@ async def get_type_detail_controller(
|
||||
result_dict = await DictTypeService(auth).detail(id=id)
|
||||
return SuccessResponse(data=result_dict, msg="获取字典类型详情成功")
|
||||
|
||||
@DictRouter.get(
|
||||
"/type/list",
|
||||
summary="查询字典类型",
|
||||
response_model=ResponseSchema[PageResultSchema[DictTypeOutSchema]],
|
||||
)
|
||||
@DictRouter.get("/type/list", summary="查询字典类型", response_model=ResponseSchema[PageResultSchema[DictTypeOutSchema]])
|
||||
async def get_type_list_controller(
|
||||
auth: Annotated[AuthSchema, Depends(AuthPermission(["module_system:dict_type:query"]))],
|
||||
page: Annotated[PaginationQueryParam, Query(description="分页查询参数")],
|
||||
@@ -59,11 +50,7 @@ async def get_type_list_controller(
|
||||
)
|
||||
return SuccessResponse(data=result_dict, msg="查询字典类型列表成功")
|
||||
|
||||
@DictRouter.get(
|
||||
"/type/optionselect",
|
||||
summary="获取全部字典类型",
|
||||
response_model=ResponseSchema[list[DictTypeOutSchema]],
|
||||
)
|
||||
@DictRouter.get("/type/optionselect", summary="获取全部字典类型", response_model=ResponseSchema[list[DictTypeOutSchema]])
|
||||
@cache(expire=300, namespace=_DICT_TYPE_NS)
|
||||
async def get_type_optionselect_controller(
|
||||
auth: Annotated[AuthSchema, Depends(AuthPermission(["module_system:dict_type:query"]))],
|
||||
@@ -71,11 +58,7 @@ async def get_type_optionselect_controller(
|
||||
result_dict_list = await DictTypeService(auth).get_list()
|
||||
return SuccessResponse(data=result_dict_list, msg="获取字典类型列表成功")
|
||||
|
||||
@DictRouter.post(
|
||||
"/type/create",
|
||||
summary="创建字典类型",
|
||||
response_model=ResponseSchema[DictTypeOutSchema],
|
||||
)
|
||||
@DictRouter.post("/type/create", summary="创建字典类型", response_model=ResponseSchema[DictTypeOutSchema])
|
||||
async def create_type_controller(
|
||||
redis: Annotated[Redis, Depends(redis_getter)],
|
||||
auth: Annotated[AuthSchema, Depends(AuthPermission(["module_system:dict_type:create"]))],
|
||||
@@ -85,11 +68,7 @@ async def create_type_controller(
|
||||
await FastAPICache.clear(namespace=_DICT_TYPE_NS)
|
||||
return SuccessResponse(data=result_dict, msg="创建字典类型成功")
|
||||
|
||||
@DictRouter.put(
|
||||
"/type/update/{id}",
|
||||
summary="修改字典类型",
|
||||
response_model=ResponseSchema[DictTypeOutSchema],
|
||||
)
|
||||
@DictRouter.put("/type/update/{id}", summary="修改字典类型", response_model=ResponseSchema[DictTypeOutSchema])
|
||||
async def update_type_controller(
|
||||
redis: Annotated[Redis, Depends(redis_getter)],
|
||||
auth: Annotated[AuthSchema, Depends(AuthPermission(["module_system:dict_type:update"]))],
|
||||
@@ -100,11 +79,7 @@ async def update_type_controller(
|
||||
await FastAPICache.clear(namespace=_DICT_TYPE_NS)
|
||||
return SuccessResponse(data=result_dict, msg="修改字典类型成功")
|
||||
|
||||
@DictRouter.delete(
|
||||
"/type/delete",
|
||||
summary="删除字典类型",
|
||||
response_model=ResponseSchema[None],
|
||||
)
|
||||
@DictRouter.delete("/type/delete", summary="删除字典类型", response_model=ResponseSchema[None])
|
||||
async def delete_type_controller(
|
||||
redis: Annotated[Redis, Depends(redis_getter)],
|
||||
auth: Annotated[AuthSchema, Depends(AuthPermission(["module_system:dict_type:delete"]))],
|
||||
@@ -114,11 +89,7 @@ async def delete_type_controller(
|
||||
await FastAPICache.clear(namespace=_DICT_TYPE_NS)
|
||||
return SuccessResponse(msg="删除字典类型成功")
|
||||
|
||||
@DictRouter.patch(
|
||||
"/type/status/batch",
|
||||
summary="批量修改字典类型状态",
|
||||
response_model=ResponseSchema[None],
|
||||
)
|
||||
@DictRouter.patch("/type/status/batch", summary="批量修改字典类型状态", response_model=ResponseSchema[None])
|
||||
async def batch_set_available_dict_type_controller(
|
||||
auth: Annotated[AuthSchema, Depends(AuthPermission(["module_system:dict_type:patch"]))],
|
||||
data: Annotated[BatchSetAvailable, Body(description="状态设置")],
|
||||
@@ -127,15 +98,11 @@ async def batch_set_available_dict_type_controller(
|
||||
await FastAPICache.clear(namespace=_DICT_TYPE_NS)
|
||||
return SuccessResponse(msg="批量修改字典类型状态成功")
|
||||
|
||||
@DictRouter.post(
|
||||
"/type/export",
|
||||
summary="导出字典类型",
|
||||
response_model=ResponseSchema[None],
|
||||
)
|
||||
@DictRouter.post("/type/export", summary="导出字典类型")
|
||||
async def export_type_list_controller(
|
||||
auth: Annotated[AuthSchema, Depends(AuthPermission(["module_system:dict_type:export"]))],
|
||||
search: Annotated[DictTypeQueryParam, Query(description="字典类型查询参数")],
|
||||
) -> StreamingResponse:
|
||||
) -> StreamingResponse[bytes]:
|
||||
# 获取全量数据并转为dict列表
|
||||
result_dict_list = await DictTypeService(auth).get_list(search=search)
|
||||
export_data = [item.model_dump() for item in result_dict_list]
|
||||
@@ -147,11 +114,7 @@ async def export_type_list_controller(
|
||||
headers={"Content-Disposition": "attachment; filename=dict_type.xlsx"},
|
||||
)
|
||||
|
||||
@DictRouter.get(
|
||||
"/data/detail/{id}",
|
||||
summary="获取字典数据详情",
|
||||
response_model=ResponseSchema[DictDataOutSchema],
|
||||
)
|
||||
@DictRouter.get("/data/detail/{id}", summary="获取字典数据详情", response_model=ResponseSchema[DictDataOutSchema])
|
||||
async def get_data_detail_controller(
|
||||
auth: Annotated[AuthSchema, Depends(AuthPermission(["module_system:dict_data:detail"]))],
|
||||
id: Annotated[int, Path(description="字典数据ID", ge=1)],
|
||||
@@ -159,11 +122,7 @@ async def get_data_detail_controller(
|
||||
result_dict = await DictDataService(auth).detail(id=id)
|
||||
return SuccessResponse(data=result_dict, msg="获取字典数据详情成功")
|
||||
|
||||
@DictRouter.get(
|
||||
"/data/list",
|
||||
summary="查询字典数据",
|
||||
response_model=ResponseSchema[PageResultSchema[DictDataOutSchema]],
|
||||
)
|
||||
@DictRouter.get("/data/list", summary="查询字典数据", response_model=ResponseSchema[PageResultSchema[DictDataOutSchema]])
|
||||
async def get_data_list_controller(
|
||||
auth: Annotated[AuthSchema, Depends(AuthPermission(["module_system:dict_data:query"]))],
|
||||
page: Annotated[PaginationQueryParam, Query(description="分页参数")],
|
||||
@@ -180,11 +139,7 @@ async def get_data_list_controller(
|
||||
)
|
||||
return SuccessResponse(data=result_dict, msg="查询字典数据列表成功")
|
||||
|
||||
@DictRouter.post(
|
||||
"/data/create",
|
||||
summary="创建字典数据",
|
||||
response_model=ResponseSchema[DictDataOutSchema],
|
||||
)
|
||||
@DictRouter.post("/data/create", summary="创建字典数据", response_model=ResponseSchema[DictDataOutSchema])
|
||||
async def create_data_controller(
|
||||
redis: Annotated[Redis, Depends(redis_getter)],
|
||||
auth: Annotated[AuthSchema, Depends(AuthPermission(["module_system:dict_data:create"]))],
|
||||
@@ -193,11 +148,7 @@ async def create_data_controller(
|
||||
result_dict = await DictDataService(auth).create(redis=redis, data=data)
|
||||
return SuccessResponse(data=result_dict, msg="创建字典数据成功")
|
||||
|
||||
@DictRouter.put(
|
||||
"/data/update/{id}",
|
||||
summary="修改字典数据",
|
||||
response_model=ResponseSchema[DictDataOutSchema],
|
||||
)
|
||||
@DictRouter.put("/data/update/{id}", summary="修改字典数据", response_model=ResponseSchema[DictDataOutSchema])
|
||||
async def update_data_controller(
|
||||
redis: Annotated[Redis, Depends(redis_getter)],
|
||||
auth: Annotated[AuthSchema, Depends(AuthPermission(["module_system:dict_data:update"]))],
|
||||
@@ -207,11 +158,7 @@ async def update_data_controller(
|
||||
result_dict = await DictDataService(auth).update(redis=redis, id=id, data=data)
|
||||
return SuccessResponse(data=result_dict, msg="修改字典数据成功")
|
||||
|
||||
@DictRouter.delete(
|
||||
"/data/delete",
|
||||
summary="删除字典数据",
|
||||
response_model=ResponseSchema[None],
|
||||
)
|
||||
@DictRouter.delete("/data/delete", summary="删除字典数据", response_model=ResponseSchema[None])
|
||||
async def delete_data_controller(
|
||||
redis: Annotated[Redis, Depends(redis_getter)],
|
||||
auth: Annotated[AuthSchema, Depends(AuthPermission(["module_system:dict_data:delete"]))],
|
||||
@@ -220,11 +167,7 @@ async def delete_data_controller(
|
||||
await DictDataService(auth).delete(redis=redis, ids=ids)
|
||||
return SuccessResponse(msg="删除字典数据成功")
|
||||
|
||||
@DictRouter.patch(
|
||||
"/data/status/batch",
|
||||
summary="批量修改字典数据状态",
|
||||
response_model=ResponseSchema[None],
|
||||
)
|
||||
@DictRouter.patch("/data/status/batch", summary="批量修改字典数据状态", response_model=ResponseSchema[None])
|
||||
async def batch_set_available_dict_data_controller(
|
||||
auth: Annotated[AuthSchema, Depends(AuthPermission(["module_system:dict_data:patch"]))],
|
||||
data: Annotated[BatchSetAvailable, Body(description="状态设置")],
|
||||
@@ -232,16 +175,12 @@ async def batch_set_available_dict_data_controller(
|
||||
await DictDataService(auth).set_available(data=data)
|
||||
return SuccessResponse(msg="批量修改字典数据状态成功")
|
||||
|
||||
@DictRouter.post(
|
||||
"/data/export",
|
||||
summary="导出字典数据",
|
||||
response_model=ResponseSchema[None],
|
||||
)
|
||||
@DictRouter.post("/data/export", summary="导出字典数据", response_model=StreamResponse[bytes])
|
||||
async def export_data_list_controller(
|
||||
auth: Annotated[AuthSchema, Depends(AuthPermission(["module_system:dict_data:export"]))],
|
||||
page: Annotated[PaginationQueryParam, Query(description="分页参数")],
|
||||
search: Annotated[DictDataQueryParam, Query(description="字典数据查询参数")],
|
||||
) -> StreamingResponse:
|
||||
) -> StreamingResponse[bytes]:
|
||||
result_dict_list = await DictDataService(auth).get_list(search=search, order_by=page.order_by)
|
||||
export_data = [item.model_dump() for item in result_dict_list]
|
||||
export_result = DictDataService.export(data_list=export_data)
|
||||
@@ -252,11 +191,7 @@ async def export_data_list_controller(
|
||||
headers={"Content-Disposition": "attachment; filename=dice_data.xlsx"},
|
||||
)
|
||||
|
||||
@DictRouter.get(
|
||||
"/data/info/{dict_type}",
|
||||
summary="根据字典类型获取数据",
|
||||
response_model=ResponseSchema[list[DictDataOutSchema]],
|
||||
)
|
||||
@DictRouter.get("/data/info/{dict_type}", summary="根据字典类型获取数据", response_model=ResponseSchema[list[DictDataOutSchema]])
|
||||
async def get_init_dict_data_controller(
|
||||
redis: Annotated[Redis, Depends(redis_getter)],
|
||||
dict_type: Annotated[str, Path(description="字典类型")],
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
import re
|
||||
from dataclasses import dataclass
|
||||
|
||||
from fastapi import Query
|
||||
from pydantic import (
|
||||
BaseModel,
|
||||
ConfigDict,
|
||||
@@ -11,8 +9,7 @@ from pydantic import (
|
||||
)
|
||||
|
||||
from app.common.enums import QueueEnum
|
||||
from app.core.base_params import BaseQueryParam, TenantByQueryParam, UserByQueryParam
|
||||
from app.core.base_schema import BaseSchema, TenantBySchema, UserBySchema
|
||||
from app.core.base_schema import BaseQueryParam, BaseSchema, TenantByQueryParam, TenantBySchema, UserByQueryParam, UserBySchema
|
||||
|
||||
|
||||
class DictTypeCreateSchema(BaseModel):
|
||||
@@ -84,21 +81,22 @@ class DictTypeOutSchema(DictTypeCreateSchema, BaseSchema, UserBySchema, TenantBy
|
||||
model_config = ConfigDict(from_attributes=True)
|
||||
|
||||
|
||||
@dataclass
|
||||
class DictTypeQueryParam(BaseQueryParam, UserByQueryParam, TenantByQueryParam):
|
||||
"""字典类型查询参数"""
|
||||
|
||||
dict_name: str | None = Query(default=None, description="字典名称", max_length=100)
|
||||
dict_type: str | None = Query(default=None, description="字典类型", max_length=100)
|
||||
status: int | None = Query(default=None, ge=0, le=1, description="状态(0:启动 1:停用)")
|
||||
dict_name: str | None = Field(default=None, description="字典名称", max_length=100)
|
||||
dict_type: str | None = Field(default=None, description="字典类型", max_length=100)
|
||||
status: int | None = Field(default=None, ge=0, le=1, description="状态(0:启动 1:停用)")
|
||||
|
||||
def __post_init__(self) -> None:
|
||||
@model_validator(mode="after")
|
||||
def validate_query_params(self) -> "DictTypeQueryParam":
|
||||
if self.dict_name:
|
||||
self.dict_name = (QueueEnum.like.value, self.dict_name)
|
||||
if self.dict_type:
|
||||
self.dict_type = (QueueEnum.eq.value, self.dict_type)
|
||||
if isinstance(self.status, int):
|
||||
self.status = (QueueEnum.eq.value, self.status)
|
||||
return self
|
||||
|
||||
|
||||
class DictDataCreateSchema(BaseModel):
|
||||
@@ -162,16 +160,16 @@ class DictDataOutSchema(DictDataCreateSchema, BaseSchema, UserBySchema, TenantBy
|
||||
model_config = ConfigDict(from_attributes=True)
|
||||
|
||||
|
||||
@dataclass
|
||||
class DictDataQueryParam(BaseQueryParam, UserByQueryParam, TenantByQueryParam):
|
||||
"""字典数据查询参数"""
|
||||
|
||||
dict_label: str | None = Query(default=None, description="字典标签", max_length=100)
|
||||
dict_type: str | None = Query(default=None, description="字典类型", max_length=100)
|
||||
dict_type_id: int | None = Query(default=None, description="字典类型ID")
|
||||
status: int | None = Query(default=None, ge=0, le=1, description="状态(0:启动 1:停用)")
|
||||
dict_label: str | None = Field(default=None, description="字典标签", max_length=100)
|
||||
dict_type: str | None = Field(default=None, description="字典类型", max_length=100)
|
||||
dict_type_id: int | None = Field(default=None, description="字典类型ID")
|
||||
status: int | None = Field(default=None, ge=0, le=1, description="状态(0:启动 1:停用)")
|
||||
|
||||
def __post_init__(self) -> None:
|
||||
@model_validator(mode="after")
|
||||
def validate_query_params(self) -> "DictDataQueryParam":
|
||||
if self.dict_label:
|
||||
self.dict_label = (QueueEnum.like.value, self.dict_label)
|
||||
if self.dict_type:
|
||||
@@ -180,3 +178,4 @@ class DictDataQueryParam(BaseQueryParam, UserByQueryParam, TenantByQueryParam):
|
||||
self.status = (QueueEnum.eq.value, self.status)
|
||||
if self.dict_type_id is not None:
|
||||
self.dict_type_id = (QueueEnum.eq.value, self.dict_type_id)
|
||||
return self
|
||||
|
||||
@@ -4,8 +4,7 @@ from fastapi import APIRouter, Body, Depends, Path, Query
|
||||
from fastapi.responses import JSONResponse
|
||||
|
||||
from app.common.response import ResponseSchema, SuccessResponse
|
||||
from app.core.base_params import PaginationQueryParam
|
||||
from app.core.base_schema import AuthSchema, PageResultSchema
|
||||
from app.core.base_schema import AuthSchema, PageResultSchema, PaginationQueryParam
|
||||
from app.core.dependencies import AuthPermission, get_current_user
|
||||
from app.core.router_class import OperationLogRoute
|
||||
|
||||
@@ -24,11 +23,7 @@ from .service import LoginLogService, OperationLogService
|
||||
LogRouter = APIRouter(route_class=OperationLogRoute, prefix="/log", tags=["日志管理"])
|
||||
|
||||
|
||||
@LogRouter.get(
|
||||
"/login/detail/{id}",
|
||||
summary="获取登录日志详情",
|
||||
response_model=ResponseSchema[LoginLogDetailOutSchema],
|
||||
)
|
||||
@LogRouter.get("/login/detail/{id}", summary="获取登录日志详情", response_model=ResponseSchema[LoginLogDetailOutSchema])
|
||||
async def get_log_detail_controller(
|
||||
auth: Annotated[AuthSchema, Depends(AuthPermission(["module_system:login_log:query"]))],
|
||||
id: Annotated[int, Path(description="登录日志ID")],
|
||||
@@ -37,11 +32,7 @@ async def get_log_detail_controller(
|
||||
return SuccessResponse(data=result_dict, msg="获取登录日志详情成功")
|
||||
|
||||
|
||||
@LogRouter.get(
|
||||
"/login/list",
|
||||
summary="查询登录日志列表",
|
||||
response_model=ResponseSchema[PageResultSchema[LoginLogOutSchema]],
|
||||
)
|
||||
@LogRouter.get("/login/list", summary="查询登录日志列表", response_model=ResponseSchema[PageResultSchema[LoginLogOutSchema]])
|
||||
async def get_log_list_controller(
|
||||
auth: Annotated[AuthSchema, Depends(AuthPermission(["module_system:login_log:query"]))],
|
||||
page: Annotated[PaginationQueryParam, Query(description="分页参数")],
|
||||
@@ -56,11 +47,7 @@ async def get_log_list_controller(
|
||||
return SuccessResponse(data=result_dict, msg="查询登录日志列表成功")
|
||||
|
||||
|
||||
@LogRouter.post(
|
||||
"/login/create",
|
||||
summary="创建登录日志",
|
||||
response_model=ResponseSchema[LoginLogDetailOutSchema],
|
||||
)
|
||||
@LogRouter.post("/login/create", summary="创建登录日志", response_model=ResponseSchema[LoginLogDetailOutSchema])
|
||||
async def create_log_controller(
|
||||
auth: Annotated[AuthSchema, Depends(get_current_user)],
|
||||
data: Annotated[LoginLogCreateSchema, Body(description="登录日志创建参数")],
|
||||
@@ -69,11 +56,7 @@ async def create_log_controller(
|
||||
return SuccessResponse(data=result_dict, msg="创建登录日志成功")
|
||||
|
||||
|
||||
@LogRouter.delete(
|
||||
"/login/delete",
|
||||
summary="删除登录日志",
|
||||
response_model=ResponseSchema,
|
||||
)
|
||||
@LogRouter.delete("/login/delete", summary="删除登录日志", response_model=ResponseSchema)
|
||||
async def delete_log_controller(
|
||||
auth: Annotated[AuthSchema, Depends(AuthPermission(["module_system:login_log:delete"]))],
|
||||
ids: Annotated[list[int], Body(description="ID列表")],
|
||||
@@ -82,31 +65,21 @@ async def delete_log_controller(
|
||||
return SuccessResponse(msg="删除登录日志成功")
|
||||
|
||||
|
||||
@LogRouter.get(
|
||||
"/operation/detail/{id}",
|
||||
summary="获取操作日志详情",
|
||||
response_model=ResponseSchema[OperationLogDetailOutSchema],
|
||||
dependencies=[Depends(AuthPermission(["module_system:log:query"]))],
|
||||
)
|
||||
@LogRouter.get("/operation/detail/{id}", summary="获取操作日志详情", response_model=ResponseSchema[OperationLogDetailOutSchema], dependencies=[Depends(AuthPermission(["module_system:log:query"]))])
|
||||
async def get_operation_log_detail_controller(
|
||||
auth: Annotated[AuthSchema, Depends(get_current_user)],
|
||||
id: Annotated[int, Path(description="操作日志ID", gt=0)],
|
||||
):
|
||||
) -> JSONResponse:
|
||||
result_dict = await OperationLogService(auth).detail(id=id)
|
||||
return SuccessResponse(data=result_dict, msg="获取操作日志详情成功")
|
||||
|
||||
|
||||
@LogRouter.get(
|
||||
"/operation/list",
|
||||
summary="获取操作日志列表",
|
||||
response_model=ResponseSchema[PageResultSchema[OperationLogOutSchema]],
|
||||
dependencies=[Depends(AuthPermission(["module_system:log:query"]))],
|
||||
)
|
||||
@LogRouter.get("/operation/list", summary="获取操作日志列表", response_model=ResponseSchema[PageResultSchema[OperationLogOutSchema]], dependencies=[Depends(AuthPermission(["module_system:log:query"]))])
|
||||
async def get_operation_log_list_controller(
|
||||
auth: Annotated[AuthSchema, Depends(get_current_user)],
|
||||
page: Annotated[PaginationQueryParam, Query(description="分页参数")],
|
||||
search: Annotated[OperationLogQueryParam, Query(description="操作日志查询参数")],
|
||||
):
|
||||
) -> JSONResponse:
|
||||
result_dict = await OperationLogService(auth).page(
|
||||
page_no=page.page_no,
|
||||
page_size=page.page_size,
|
||||
@@ -116,28 +89,19 @@ async def get_operation_log_list_controller(
|
||||
return SuccessResponse(data=result_dict, msg="查询操作日志列表成功")
|
||||
|
||||
|
||||
@LogRouter.post(
|
||||
"/operation/create",
|
||||
summary="创建操作日志",
|
||||
response_model=ResponseSchema[OperationLogDetailOutSchema],
|
||||
)
|
||||
@LogRouter.post("/operation/create", summary="创建操作日志", response_model=ResponseSchema[OperationLogDetailOutSchema])
|
||||
async def create_operation_log_controller(
|
||||
auth: Annotated[AuthSchema, Depends(get_current_user)],
|
||||
data: Annotated[OperationLogCreateSchema, Body(description="操作日志创建参数")],
|
||||
):
|
||||
) -> JSONResponse:
|
||||
result_dict = await OperationLogService(auth).create(data=data)
|
||||
return SuccessResponse(data=result_dict, msg="创建操作日志成功")
|
||||
|
||||
|
||||
@LogRouter.delete(
|
||||
"/operation/delete",
|
||||
summary="删除操作日志",
|
||||
response_model=ResponseSchema,
|
||||
dependencies=[Depends(AuthPermission(["module_system:log:delete"]))],
|
||||
)
|
||||
async def delete(
|
||||
@LogRouter.delete("/operation/delete", summary="删除操作日志", response_model=ResponseSchema, dependencies=[Depends(AuthPermission(["module_system:log:delete"]))])
|
||||
async def delete_operation_log_controller(
|
||||
auth: Annotated[AuthSchema, Depends(get_current_user)],
|
||||
ids: Annotated[list[int], Body(description="ID列表")],
|
||||
):
|
||||
) -> JSONResponse:
|
||||
await OperationLogService(auth).delete(ids=ids)
|
||||
return SuccessResponse(msg="删除操作日志成功")
|
||||
|
||||
@@ -1,11 +1,7 @@
|
||||
from dataclasses import dataclass
|
||||
|
||||
from fastapi import Query
|
||||
from pydantic import BaseModel, ConfigDict, Field, field_validator
|
||||
from pydantic import BaseModel, ConfigDict, Field, field_validator, model_validator
|
||||
|
||||
from app.common.enums import QueueEnum
|
||||
from app.core.base_params import BaseQueryParam, TenantByQueryParam, UserByQueryParam
|
||||
from app.core.base_schema import BaseSchema, TenantBySchema, UserBySchema
|
||||
from app.core.base_schema import BaseQueryParam, BaseSchema, TenantByQueryParam, TenantBySchema, UserByQueryParam, UserBySchema
|
||||
|
||||
ALLOWED_REQUEST_METHODS = ["GET", "POST", "PUT", "DELETE", "PATCH", "OPTIONS", "HEAD"]
|
||||
|
||||
@@ -49,30 +45,31 @@ class LoginLogDetailOutSchema(LoginLogOutSchema):
|
||||
"""登录日志详情响应"""
|
||||
|
||||
|
||||
@dataclass
|
||||
class LoginLogQueryParam(BaseQueryParam, UserByQueryParam, TenantByQueryParam):
|
||||
"""登录日志查询参数"""
|
||||
|
||||
username: str | None = Query(None, max_length=64, description="用户名")
|
||||
status: int | None = Query(None, description="登录状态(1:成功 2:失败)")
|
||||
username: str | None = Field(None, max_length=64, description="用户名")
|
||||
status: int | None = Field(None, description="登录状态(1:成功 2:失败)")
|
||||
|
||||
def __post_init__(self) -> None:
|
||||
@model_validator(mode="after")
|
||||
def validate_query_params(self) -> "LoginLogQueryParam":
|
||||
if self.username:
|
||||
self.username = (QueueEnum.like.value, self.username)
|
||||
if isinstance(self.status, int):
|
||||
self.status = (QueueEnum.eq.value, self.status)
|
||||
return self
|
||||
|
||||
|
||||
@dataclass
|
||||
class OperationLogQueryParam(BaseQueryParam, UserByQueryParam, TenantByQueryParam):
|
||||
"""操作日志查询参数"""
|
||||
|
||||
request_path: str | None = Query(None, description="请求路径")
|
||||
request_method: str | None = Query(None, description="请求方式")
|
||||
username: str | None = Query(None, description="用户名")
|
||||
status: int | None = Query(None, ge=0, le=1, description="状态(0:成功 1:失败)")
|
||||
request_path: str | None = Field(None, description="请求路径")
|
||||
request_method: str | None = Field(None, description="请求方式")
|
||||
username: str | None = Field(None, description="用户名")
|
||||
status: int | None = Field(None, ge=0, le=1, description="状态(0:成功 1:失败)")
|
||||
|
||||
def __post_init__(self) -> None:
|
||||
@model_validator(mode="after")
|
||||
def validate_query_params(self) -> "OperationLogQueryParam":
|
||||
if self.request_path:
|
||||
self.request_path = (QueueEnum.like.value, self.request_path)
|
||||
if self.request_method:
|
||||
@@ -81,6 +78,7 @@ class OperationLogQueryParam(BaseQueryParam, UserByQueryParam, TenantByQueryPara
|
||||
self.username = (QueueEnum.like.value, self.username)
|
||||
if isinstance(self.status, int):
|
||||
self.status = (QueueEnum.eq.value, self.status)
|
||||
return self
|
||||
|
||||
|
||||
class OperationLogOutSchema(BaseSchema, UserBySchema, TenantBySchema):
|
||||
|
||||
@@ -6,31 +6,20 @@ from fastapi_cache import FastAPICache
|
||||
from fastapi_cache.decorator import cache
|
||||
|
||||
from app.common.response import ResponseSchema, StreamResponse, SuccessResponse
|
||||
from app.core.base_params import PaginationQueryParam
|
||||
from app.core.base_schema import AuthSchema, BatchSetAvailable, PageResultSchema
|
||||
from app.core.base_schema import AuthSchema, BatchSetAvailable, PageResultSchema, PaginationQueryParam
|
||||
from app.core.dependencies import AuthPermission, get_current_user
|
||||
from app.core.logger import logger
|
||||
from app.core.router_class import OperationLogRoute
|
||||
from app.utils.common_util import bytes2file_response
|
||||
|
||||
from .schema import (
|
||||
NoticeCreateSchema,
|
||||
NoticeOutSchema,
|
||||
NoticeQueryParam,
|
||||
NoticeUpdateSchema,
|
||||
PanelDataOut,
|
||||
)
|
||||
from .schema import NoticeCreateSchema, NoticeOutSchema, NoticeQueryParam, NoticeUpdateSchema, PanelDataOut
|
||||
from .service import NoticeService
|
||||
|
||||
NoticeRouter = APIRouter(route_class=OperationLogRoute, prefix="/notice", tags=["公告通知"])
|
||||
|
||||
_NOTICE_NS = "notice"
|
||||
|
||||
@NoticeRouter.get(
|
||||
"/detail/{id}",
|
||||
summary="获取公告详情",
|
||||
response_model=ResponseSchema[NoticeOutSchema],
|
||||
)
|
||||
@NoticeRouter.get("/detail/{id}", summary="获取公告详情", response_model=ResponseSchema[NoticeOutSchema])
|
||||
async def get_notice_detail_controller(
|
||||
auth: Annotated[AuthSchema, Depends(AuthPermission(["module_system:notice:detail"]))],
|
||||
id: Annotated[int, Path(description="公告ID")],
|
||||
@@ -38,11 +27,7 @@ async def get_notice_detail_controller(
|
||||
result_dict = await NoticeService(auth).detail(id=id)
|
||||
return SuccessResponse(data=result_dict, msg="获取公告详情成功")
|
||||
|
||||
@NoticeRouter.get(
|
||||
"/list",
|
||||
summary="查询公告",
|
||||
response_model=ResponseSchema[PageResultSchema[NoticeOutSchema]],
|
||||
)
|
||||
@NoticeRouter.get("/list", summary="查询公告", response_model=ResponseSchema[PageResultSchema[NoticeOutSchema]])
|
||||
async def get_notice_list_controller(
|
||||
auth: Annotated[AuthSchema, Depends(AuthPermission(["module_system:notice:query"]))],
|
||||
page: Annotated[PaginationQueryParam, Query(description="分页参数")],
|
||||
@@ -56,11 +41,7 @@ async def get_notice_list_controller(
|
||||
)
|
||||
return SuccessResponse(data=result_dict, msg="查询公告列表成功")
|
||||
|
||||
@NoticeRouter.post(
|
||||
"/create",
|
||||
summary="创建公告",
|
||||
response_model=ResponseSchema[NoticeOutSchema],
|
||||
)
|
||||
@NoticeRouter.post("/create", summary="创建公告", response_model=ResponseSchema[NoticeOutSchema])
|
||||
async def create_notice_controller(
|
||||
auth: Annotated[AuthSchema, Depends(AuthPermission(["module_system:notice:create"]))],
|
||||
data: Annotated[NoticeCreateSchema, Body(description="公告创建参数")],
|
||||
@@ -69,11 +50,7 @@ async def create_notice_controller(
|
||||
await FastAPICache.clear(namespace=_NOTICE_NS)
|
||||
return SuccessResponse(data=result_dict, msg="创建公告成功")
|
||||
|
||||
@NoticeRouter.put(
|
||||
"/update/{id}",
|
||||
summary="修改公告",
|
||||
response_model=ResponseSchema[NoticeOutSchema],
|
||||
)
|
||||
@NoticeRouter.put("/update/{id}", summary="修改公告", response_model=ResponseSchema[NoticeOutSchema])
|
||||
async def update_notice_controller(
|
||||
auth: Annotated[AuthSchema, Depends(AuthPermission(["module_system:notice:update"]))],
|
||||
id: Annotated[int, Path(description="公告ID")],
|
||||
@@ -83,11 +60,7 @@ async def update_notice_controller(
|
||||
await FastAPICache.clear(namespace=_NOTICE_NS)
|
||||
return SuccessResponse(data=result_dict, msg="修改公告成功")
|
||||
|
||||
@NoticeRouter.delete(
|
||||
"/delete",
|
||||
summary="删除公告",
|
||||
response_model=ResponseSchema[None],
|
||||
)
|
||||
@NoticeRouter.delete("/delete", summary="删除公告", response_model=ResponseSchema[None])
|
||||
async def delete_notice_controller(
|
||||
auth: Annotated[AuthSchema, Depends(AuthPermission(["module_system:notice:delete"]))],
|
||||
ids: Annotated[list[int], Body(description="ID列表")],
|
||||
@@ -96,11 +69,7 @@ async def delete_notice_controller(
|
||||
await FastAPICache.clear(namespace=_NOTICE_NS)
|
||||
return SuccessResponse(msg="删除公告成功")
|
||||
|
||||
@NoticeRouter.patch(
|
||||
"/status/batch",
|
||||
summary="批量修改公告状态",
|
||||
response_model=ResponseSchema[None],
|
||||
)
|
||||
@NoticeRouter.patch("/status/batch", summary="批量修改公告状态", response_model=ResponseSchema[None])
|
||||
async def batch_set_available_notice_controller(
|
||||
auth: Annotated[AuthSchema, Depends(AuthPermission(["module_system:notice:patch"]))],
|
||||
data: Annotated[BatchSetAvailable, Body(description="状态设置")],
|
||||
@@ -109,14 +78,11 @@ async def batch_set_available_notice_controller(
|
||||
await FastAPICache.clear(namespace=_NOTICE_NS)
|
||||
return SuccessResponse(msg="批量修改公告状态成功")
|
||||
|
||||
@NoticeRouter.post(
|
||||
"/export",
|
||||
summary="导出公告",
|
||||
)
|
||||
@NoticeRouter.post("/export", summary="导出公告")
|
||||
async def export_notice_list_controller(
|
||||
auth: Annotated[AuthSchema, Depends(AuthPermission(["module_system:notice:export"]))],
|
||||
search: Annotated[NoticeQueryParam, Query(description="公告查询参数")],
|
||||
) -> StreamingResponse:
|
||||
) -> StreamingResponse[bytes]:
|
||||
result_dict_list = await NoticeService(auth).get_list(search=search)
|
||||
export_data = [item.model_dump() for item in result_dict_list]
|
||||
export_result = NoticeService.export(notice_list=export_data)
|
||||
@@ -127,11 +93,7 @@ async def export_notice_list_controller(
|
||||
headers={"Content-Disposition": "attachment; filename=notice.xlsx"},
|
||||
)
|
||||
|
||||
@NoticeRouter.get(
|
||||
"/available",
|
||||
summary="获取全局启用公告",
|
||||
response_model=ResponseSchema[list[NoticeOutSchema]],
|
||||
)
|
||||
@NoticeRouter.get("/available", summary="获取全局启用公告", response_model=ResponseSchema[list[NoticeOutSchema]])
|
||||
@cache(expire=120, namespace=_NOTICE_NS)
|
||||
async def get_notice_list_available_controller(
|
||||
auth: Annotated[AuthSchema, Depends(get_current_user)],
|
||||
@@ -139,11 +101,7 @@ async def get_notice_list_available_controller(
|
||||
result_dict = await NoticeService(auth).available_page()
|
||||
return SuccessResponse(data=result_dict, msg="查询已启用公告列表成功")
|
||||
|
||||
@NoticeRouter.get(
|
||||
"/panel",
|
||||
summary="通知面板数据(铃铛)",
|
||||
response_model=ResponseSchema[PanelDataOut],
|
||||
)
|
||||
@NoticeRouter.get("/panel", summary="通知面板数据(铃铛)", response_model=ResponseSchema[PanelDataOut])
|
||||
@cache(expire=30, namespace=_NOTICE_NS)
|
||||
async def get_notification_panel_controller(
|
||||
auth: Annotated[AuthSchema, Depends(get_current_user)],
|
||||
@@ -152,11 +110,7 @@ async def get_notification_panel_controller(
|
||||
result = await NoticeService(auth).panel_data()
|
||||
return SuccessResponse(data=result, msg="获取面板数据成功")
|
||||
|
||||
@NoticeRouter.post(
|
||||
"/read/{id}",
|
||||
summary="标记已读",
|
||||
response_model=ResponseSchema[None],
|
||||
)
|
||||
@NoticeRouter.post("/read/{id}", summary="标记已读", response_model=ResponseSchema[None])
|
||||
async def mark_read_controller(
|
||||
auth: Annotated[AuthSchema, Depends(get_current_user)],
|
||||
id: Annotated[int, Path(description="通知ID")],
|
||||
@@ -167,11 +121,7 @@ async def mark_read_controller(
|
||||
logger.info(f"用户[{auth.user.id}]标记通知[{id}]已读")
|
||||
return SuccessResponse(msg="标记已读成功")
|
||||
|
||||
@NoticeRouter.post(
|
||||
"/read-all",
|
||||
summary="全部已读",
|
||||
response_model=ResponseSchema[int],
|
||||
)
|
||||
@NoticeRouter.post("/read-all", summary="全部已读", response_model=ResponseSchema[int])
|
||||
async def mark_all_read_controller(
|
||||
auth: Annotated[AuthSchema, Depends(get_current_user)],
|
||||
) -> JSONResponse:
|
||||
@@ -181,11 +131,7 @@ async def mark_all_read_controller(
|
||||
logger.info(f"用户[{auth.user.id}]全部已读, 数量={count}")
|
||||
return SuccessResponse(data=count, msg=f"全部标记已读成功,共标记 {count} 条")
|
||||
|
||||
@NoticeRouter.get(
|
||||
"/unread-count",
|
||||
summary="获取未读数量",
|
||||
response_model=ResponseSchema[int],
|
||||
)
|
||||
@NoticeRouter.get("/unread-count", summary="获取未读数量", response_model=ResponseSchema[int])
|
||||
@cache(expire=15, namespace=_NOTICE_NS)
|
||||
async def get_unread_count_controller(
|
||||
auth: Annotated[AuthSchema, Depends(get_current_user)],
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
from dataclasses import dataclass
|
||||
|
||||
from fastapi import Query
|
||||
from pydantic import (
|
||||
BaseModel,
|
||||
ConfigDict,
|
||||
@@ -10,8 +7,7 @@ from pydantic import (
|
||||
)
|
||||
|
||||
from app.common.enums import QueueEnum
|
||||
from app.core.base_params import BaseQueryParam, TenantByQueryParam, UserByQueryParam
|
||||
from app.core.base_schema import BaseSchema, TenantBySchema, UserBySchema
|
||||
from app.core.base_schema import BaseQueryParam, BaseSchema, TenantByQueryParam, TenantBySchema, UserByQueryParam, UserBySchema
|
||||
from app.utils.xss_util import sanitize_html
|
||||
|
||||
|
||||
@@ -64,21 +60,22 @@ class NoticeOutSchema(NoticeCreateSchema, BaseSchema, UserBySchema, TenantBySche
|
||||
model_config = ConfigDict(from_attributes=True)
|
||||
|
||||
|
||||
@dataclass
|
||||
class NoticeQueryParam(BaseQueryParam, UserByQueryParam, TenantByQueryParam):
|
||||
"""公告通知查询参数"""
|
||||
|
||||
notice_title: str | None = Query(None, description="公告标题")
|
||||
notice_type: str | None = Query(None, description="公告类型")
|
||||
status: int | None = Query(None, ge=0, le=1, description="状态(0:启动 1:停用)")
|
||||
notice_title: str | None = Field(None, description="公告标题")
|
||||
notice_type: str | None = Field(None, description="公告类型")
|
||||
status: int | None = Field(None, ge=0, le=1, description="状态(0:启动 1:停用)")
|
||||
|
||||
def __post_init__(self) -> None:
|
||||
@model_validator(mode="after")
|
||||
def validate_query_params(self) -> "NoticeQueryParam":
|
||||
if self.notice_title:
|
||||
self.notice_title = (QueueEnum.like.value, self.notice_title)
|
||||
if self.notice_type:
|
||||
self.notice_type = (QueueEnum.eq.value, self.notice_type)
|
||||
if isinstance(self.status, int):
|
||||
self.status = (QueueEnum.eq.value, self.status)
|
||||
return self
|
||||
|
||||
|
||||
class PanelMessageItem(BaseModel):
|
||||
|
||||
@@ -5,8 +5,7 @@ from fastapi.responses import JSONResponse, StreamingResponse
|
||||
from redis.asyncio.client import Redis
|
||||
|
||||
from app.common.response import ResponseSchema, StreamResponse, SuccessResponse
|
||||
from app.core.base_params import PaginationQueryParam
|
||||
from app.core.base_schema import AuthSchema, BatchSetAvailable, PageResultSchema
|
||||
from app.core.base_schema import AuthSchema, BatchSetAvailable, PageResultSchema, PaginationQueryParam
|
||||
from app.core.dependencies import AuthPermission, redis_getter
|
||||
from app.core.router_class import OperationLogRoute
|
||||
from app.utils.common_util import bytes2file_response
|
||||
@@ -16,11 +15,8 @@ from .service import ParamsService
|
||||
|
||||
ParamsRouter = APIRouter(route_class=OperationLogRoute, prefix="/param", tags=["参数管理"])
|
||||
|
||||
@ParamsRouter.get(
|
||||
"/detail/{id}",
|
||||
summary="获取参数详情",
|
||||
response_model=ResponseSchema[ParamsOutSchema],
|
||||
)
|
||||
|
||||
@ParamsRouter.get("/detail/{id}", summary="获取参数详情", response_model=ResponseSchema[ParamsOutSchema])
|
||||
async def get_param_detail_controller(
|
||||
auth: Annotated[AuthSchema, Depends(AuthPermission(["module_system:param:detail"]))],
|
||||
id: Annotated[int, Path(description="参数ID")],
|
||||
@@ -28,11 +24,7 @@ async def get_param_detail_controller(
|
||||
result_dict = await ParamsService(auth).detail(id=id)
|
||||
return SuccessResponse(data=result_dict, msg="获取参数详情成功")
|
||||
|
||||
@ParamsRouter.get(
|
||||
"/key/{config_key}",
|
||||
summary="根据配置键获取参数详情",
|
||||
response_model=ResponseSchema[ParamsOutSchema],
|
||||
)
|
||||
@ParamsRouter.get("/key/{config_key}", summary="根据配置键获取参数详情", response_model=ResponseSchema[ParamsOutSchema])
|
||||
async def get_param_by_key_controller(
|
||||
auth: Annotated[AuthSchema, Depends(AuthPermission(["module_system:param:query"]))],
|
||||
config_key: Annotated[str, Path(description="配置键")],
|
||||
@@ -40,11 +32,7 @@ async def get_param_by_key_controller(
|
||||
result_dict = await ParamsService(auth).get_by_key(config_key=config_key)
|
||||
return SuccessResponse(data=result_dict, msg="根据配置键获取参数详情成功")
|
||||
|
||||
@ParamsRouter.get(
|
||||
"/value/{config_key}",
|
||||
summary="根据配置键获取参数值",
|
||||
response_model=ResponseSchema[ParamsOutSchema],
|
||||
)
|
||||
@ParamsRouter.get("/value/{config_key}", summary="根据配置键获取参数值", response_model=ResponseSchema[ParamsOutSchema])
|
||||
async def get_config_value_by_key_controller(
|
||||
auth: Annotated[AuthSchema, Depends(AuthPermission(["module_system:param:query"]))],
|
||||
config_key: Annotated[str, Path(description="配置键")],
|
||||
@@ -52,11 +40,7 @@ async def get_config_value_by_key_controller(
|
||||
result_value = await ParamsService(auth).get_config_value_by_key(config_key=config_key)
|
||||
return SuccessResponse(data=result_value, msg="根据配置键获取参数值成功")
|
||||
|
||||
@ParamsRouter.get(
|
||||
"/list",
|
||||
summary="获取参数列表",
|
||||
response_model=ResponseSchema[PageResultSchema[ParamsOutSchema]],
|
||||
)
|
||||
@ParamsRouter.get("/list", summary="获取参数列表", response_model=ResponseSchema[PageResultSchema[ParamsOutSchema]])
|
||||
async def get_param_list_controller(
|
||||
auth: Annotated[AuthSchema, Depends(AuthPermission(["module_system:param:query"]))],
|
||||
page: Annotated[PaginationQueryParam, Query(description="分页参数")],
|
||||
@@ -70,11 +54,7 @@ async def get_param_list_controller(
|
||||
)
|
||||
return SuccessResponse(data=result_dict, msg="查询参数列表成功")
|
||||
|
||||
@ParamsRouter.post(
|
||||
"/create",
|
||||
summary="创建参数",
|
||||
response_model=ResponseSchema[ParamsOutSchema],
|
||||
)
|
||||
@ParamsRouter.post("/create", summary="创建参数", response_model=ResponseSchema[ParamsOutSchema])
|
||||
async def create_param_controller(
|
||||
redis: Annotated[Redis, Depends(redis_getter)],
|
||||
auth: Annotated[AuthSchema, Depends(AuthPermission(["module_system:param:create"]))],
|
||||
@@ -83,11 +63,7 @@ async def create_param_controller(
|
||||
result_dict = await ParamsService(auth).create(redis=redis, data=data)
|
||||
return SuccessResponse(data=result_dict, msg="创建参数成功")
|
||||
|
||||
@ParamsRouter.put(
|
||||
"/update/{id}",
|
||||
summary="修改参数",
|
||||
response_model=ResponseSchema[ParamsOutSchema],
|
||||
)
|
||||
@ParamsRouter.put("/update/{id}", summary="修改参数", response_model=ResponseSchema[ParamsOutSchema])
|
||||
async def update_param_controller(
|
||||
redis: Annotated[Redis, Depends(redis_getter)],
|
||||
auth: Annotated[AuthSchema, Depends(AuthPermission(["module_system:param:update"]))],
|
||||
@@ -97,11 +73,7 @@ async def update_param_controller(
|
||||
result_dict = await ParamsService(auth).update(redis=redis, id=id, data=data)
|
||||
return SuccessResponse(data=result_dict, msg="更新参数成功")
|
||||
|
||||
@ParamsRouter.delete(
|
||||
"/delete",
|
||||
summary="删除参数",
|
||||
response_model=ResponseSchema[ParamsOutSchema],
|
||||
)
|
||||
@ParamsRouter.delete("/delete", summary="删除参数", response_model=ResponseSchema[ParamsOutSchema])
|
||||
async def delete_param_controller(
|
||||
redis: Annotated[Redis, Depends(redis_getter)],
|
||||
auth: Annotated[AuthSchema, Depends(AuthPermission(["module_system:param:delete"]))],
|
||||
@@ -110,11 +82,7 @@ async def delete_param_controller(
|
||||
await ParamsService(auth).delete(redis=redis, ids=ids)
|
||||
return SuccessResponse(msg="删除参数成功")
|
||||
|
||||
@ParamsRouter.patch(
|
||||
"/status/batch",
|
||||
summary="批量设置参数状态",
|
||||
response_model=ResponseSchema,
|
||||
)
|
||||
@ParamsRouter.patch("/status/batch", summary="批量设置参数状态", response_model=ResponseSchema)
|
||||
async def batch_set_status_controller(
|
||||
auth: Annotated[AuthSchema, Depends(AuthPermission(["module_system:param:patch"]))],
|
||||
data: Annotated[BatchSetAvailable, Body(description="状态设置")],
|
||||
@@ -122,15 +90,11 @@ async def batch_set_status_controller(
|
||||
await ParamsService(auth).batch_set_status(ids=data.ids, status=data.status)
|
||||
return SuccessResponse(msg="批量设置参数状态成功")
|
||||
|
||||
@ParamsRouter.get(
|
||||
"/export",
|
||||
summary="导出参数",
|
||||
response_model=ResponseSchema[None],
|
||||
)
|
||||
@ParamsRouter.get("/export", summary="导出参数")
|
||||
async def export_param_list_controller(
|
||||
auth: Annotated[AuthSchema, Depends(AuthPermission(["module_system:param:export"]))],
|
||||
search: Annotated[ParamsQueryParam, Query(description="参数查询参数")],
|
||||
) -> StreamingResponse:
|
||||
) -> StreamingResponse[bytes]:
|
||||
result_dict_list = await ParamsService(auth).get_list(search=search)
|
||||
export_data = [item.model_dump() for item in result_dict_list]
|
||||
export_result = ParamsService.export(data_list=export_data)
|
||||
@@ -141,11 +105,7 @@ async def export_param_list_controller(
|
||||
headers={"Content-Disposition": "attachment; filename=params.xlsx"},
|
||||
)
|
||||
|
||||
@ParamsRouter.get(
|
||||
"/info",
|
||||
summary="获取初始化缓存参数",
|
||||
response_model=ResponseSchema[list[ParamsOutSchema]],
|
||||
)
|
||||
@ParamsRouter.get( "/info", summary="获取初始化缓存参数", response_model=ResponseSchema[list[ParamsOutSchema]])
|
||||
async def get_init_config_controller(
|
||||
redis: Annotated[Redis, Depends(redis_getter)],
|
||||
) -> JSONResponse:
|
||||
|
||||
@@ -1,12 +1,9 @@
|
||||
import re
|
||||
from dataclasses import dataclass
|
||||
|
||||
from fastapi import Query
|
||||
from pydantic import BaseModel, ConfigDict, Field, field_validator
|
||||
from pydantic import BaseModel, ConfigDict, Field, field_validator, model_validator
|
||||
|
||||
from app.common.enums import QueueEnum
|
||||
from app.core.base_params import BaseQueryParam, TenantByQueryParam, UserByQueryParam
|
||||
from app.core.base_schema import BaseSchema, TenantBySchema, UserBySchema
|
||||
from app.core.base_schema import BaseQueryParam, BaseSchema, TenantByQueryParam, TenantBySchema, UserByQueryParam, UserBySchema
|
||||
|
||||
|
||||
class ParamsCreateSchema(BaseModel):
|
||||
@@ -53,7 +50,6 @@ class ParamsOutSchema(ParamsCreateSchema, BaseSchema, UserBySchema, TenantBySche
|
||||
model_config = ConfigDict(from_attributes=True)
|
||||
|
||||
|
||||
@dataclass
|
||||
class ParamsQueryParam(BaseQueryParam, UserByQueryParam, TenantByQueryParam):
|
||||
"""
|
||||
参数管理查询参数
|
||||
@@ -65,12 +61,13 @@ class ParamsQueryParam(BaseQueryParam, UserByQueryParam, TenantByQueryParam):
|
||||
- 业务字段:参数名称、参数键名、是否系统内置
|
||||
"""
|
||||
|
||||
config_name: str | None = Query(None, description="参数名称")
|
||||
config_key: str | None = Query(None, description="参数键名")
|
||||
config_type: bool | None = Query(None, description="是否系统内置(True:是 False:否)")
|
||||
status: int | None = Query(None, ge=0, le=1, description="状态(0:启动 1:停用)")
|
||||
config_name: str | None = Field(None, description="参数名称")
|
||||
config_key: str | None = Field(None, description="参数键名")
|
||||
config_type: bool | None = Field(None, description="是否系统内置(True:是 False:否)")
|
||||
status: int | None = Field(None, ge=0, le=1, description="状态(0:启动 1:停用)")
|
||||
|
||||
def __post_init__(self) -> None:
|
||||
@model_validator(mode="after")
|
||||
def validate_query_params(self) -> "ParamsQueryParam":
|
||||
if self.config_name:
|
||||
self.config_name = (QueueEnum.like.value, self.config_name)
|
||||
if self.config_key:
|
||||
@@ -79,3 +76,4 @@ class ParamsQueryParam(BaseQueryParam, UserByQueryParam, TenantByQueryParam):
|
||||
self.config_type = (QueueEnum.eq.value, self.config_type)
|
||||
if isinstance(self.status, int):
|
||||
self.status = (QueueEnum.eq.value, self.status)
|
||||
return self
|
||||
|
||||
@@ -6,29 +6,19 @@ from fastapi_cache import FastAPICache
|
||||
from fastapi_cache.decorator import cache
|
||||
|
||||
from app.common.response import ResponseSchema, StreamResponse, SuccessResponse
|
||||
from app.core.base_params import PaginationQueryParam
|
||||
from app.core.base_schema import AuthSchema, BatchSetAvailable, PageResultSchema
|
||||
from app.core.base_schema import AuthSchema, BatchSetAvailable, PageResultSchema, PaginationQueryParam
|
||||
from app.core.dependencies import AuthPermission
|
||||
from app.core.router_class import OperationLogRoute
|
||||
from app.utils.common_util import bytes2file_response
|
||||
|
||||
from .schema import (
|
||||
PositionCreateSchema,
|
||||
PositionOutSchema,
|
||||
PositionQueryParam,
|
||||
PositionUpdateSchema,
|
||||
)
|
||||
from .schema import PositionCreateSchema, PositionOutSchema, PositionQueryParam, PositionUpdateSchema
|
||||
from .service import PositionService
|
||||
|
||||
PositionRouter = APIRouter(route_class=OperationLogRoute, prefix="/position", tags=["岗位管理"])
|
||||
|
||||
_POS_NS = "position"
|
||||
|
||||
@PositionRouter.get(
|
||||
"/list",
|
||||
summary="查询岗位",
|
||||
response_model=ResponseSchema[PageResultSchema[PositionOutSchema]],
|
||||
)
|
||||
@PositionRouter.get("/list", summary="查询岗位", response_model=ResponseSchema[PageResultSchema[PositionOutSchema]])
|
||||
@cache(expire=300, namespace=_POS_NS)
|
||||
async def get_obj_list_controller(
|
||||
auth: Annotated[AuthSchema, Depends(AuthPermission(["module_system:position:query"]))],
|
||||
@@ -46,11 +36,7 @@ async def get_obj_list_controller(
|
||||
)
|
||||
return SuccessResponse(data=result_dict, msg="查询岗位列表成功")
|
||||
|
||||
@PositionRouter.get(
|
||||
"/detail/{id}",
|
||||
summary="查询岗位详情",
|
||||
response_model=ResponseSchema[PositionOutSchema],
|
||||
)
|
||||
@PositionRouter.get("/detail/{id}", summary="查询岗位详情", response_model=ResponseSchema[PositionOutSchema])
|
||||
async def get_obj_detail_controller(
|
||||
auth: Annotated[AuthSchema, Depends(AuthPermission(["module_system:position:detail"]))],
|
||||
id: Annotated[int, Path(description="岗位ID")],
|
||||
@@ -58,11 +44,7 @@ async def get_obj_detail_controller(
|
||||
result_dict = await PositionService(auth).detail(id=id)
|
||||
return SuccessResponse(data=result_dict, msg="获取岗位详情成功")
|
||||
|
||||
@PositionRouter.post(
|
||||
"/create",
|
||||
summary="创建岗位",
|
||||
response_model=ResponseSchema[PositionOutSchema],
|
||||
)
|
||||
@PositionRouter.post("/create", summary="创建岗位", response_model=ResponseSchema[PositionOutSchema])
|
||||
async def create_obj_controller(
|
||||
auth: Annotated[AuthSchema, Depends(AuthPermission(["module_system:position:create"]))],
|
||||
data: Annotated[PositionCreateSchema, Body(description="岗位创建参数")],
|
||||
@@ -71,11 +53,7 @@ async def create_obj_controller(
|
||||
await FastAPICache.clear(namespace=_POS_NS)
|
||||
return SuccessResponse(data=result_dict, msg="创建岗位成功")
|
||||
|
||||
@PositionRouter.put(
|
||||
"/update/{id}",
|
||||
summary="修改岗位",
|
||||
response_model=ResponseSchema[PositionOutSchema],
|
||||
)
|
||||
@PositionRouter.put("/update/{id}", summary="修改岗位", response_model=ResponseSchema[PositionOutSchema])
|
||||
async def update_obj_controller(
|
||||
auth: Annotated[AuthSchema, Depends(AuthPermission(["module_system:position:update"]))],
|
||||
id: Annotated[int, Path(description="岗位ID")],
|
||||
@@ -85,11 +63,7 @@ async def update_obj_controller(
|
||||
await FastAPICache.clear(namespace=_POS_NS)
|
||||
return SuccessResponse(data=result_dict, msg="修改岗位成功")
|
||||
|
||||
@PositionRouter.delete(
|
||||
"/delete",
|
||||
summary="删除岗位",
|
||||
response_model=ResponseSchema[None],
|
||||
)
|
||||
@PositionRouter.delete("/delete", summary="删除岗位", response_model=ResponseSchema[None])
|
||||
async def delete_obj_controller(
|
||||
auth: Annotated[AuthSchema, Depends(AuthPermission(["module_system:position:delete"]))],
|
||||
ids: Annotated[list[int], Body(description="ID列表")],
|
||||
@@ -98,11 +72,7 @@ async def delete_obj_controller(
|
||||
await FastAPICache.clear(namespace=_POS_NS)
|
||||
return SuccessResponse(msg="删除岗位成功")
|
||||
|
||||
@PositionRouter.patch(
|
||||
"/status/batch",
|
||||
summary="批量修改岗位状态",
|
||||
response_model=ResponseSchema[None],
|
||||
)
|
||||
@PositionRouter.patch("/status/batch", summary="批量修改岗位状态", response_model=ResponseSchema[None])
|
||||
async def batch_set_available_obj_controller(
|
||||
auth: Annotated[AuthSchema, Depends(AuthPermission(["module_system:position:patch"]))],
|
||||
data: Annotated[BatchSetAvailable, Body(description="状态设置")],
|
||||
@@ -111,15 +81,11 @@ async def batch_set_available_obj_controller(
|
||||
await FastAPICache.clear(namespace=_POS_NS)
|
||||
return SuccessResponse(msg="批量修改岗位状态成功")
|
||||
|
||||
@PositionRouter.get(
|
||||
"/export",
|
||||
summary="导出岗位",
|
||||
response_model=ResponseSchema[None],
|
||||
)
|
||||
@PositionRouter.get("/export", summary="导出岗位")
|
||||
async def export_obj_list_controller(
|
||||
auth: Annotated[AuthSchema, Depends(AuthPermission(["module_system:position:export"]))],
|
||||
search: Annotated[PositionQueryParam, Query(description="岗位查询参数")],
|
||||
) -> StreamingResponse:
|
||||
) -> StreamingResponse[bytes]:
|
||||
position_query_result = await PositionService(auth).get_list(search=search)
|
||||
position_export_result = PositionService.export_list(position_list=position_query_result)
|
||||
|
||||
|
||||
@@ -1,11 +1,7 @@
|
||||
from dataclasses import dataclass
|
||||
|
||||
from fastapi import Query
|
||||
from pydantic import BaseModel, ConfigDict, Field, field_validator
|
||||
from pydantic import BaseModel, ConfigDict, Field, field_validator, model_validator
|
||||
|
||||
from app.common.enums import QueueEnum
|
||||
from app.core.base_params import BaseQueryParam, TenantByQueryParam, UserByQueryParam
|
||||
from app.core.base_schema import BaseSchema, TenantBySchema, UserBySchema
|
||||
from app.core.base_schema import BaseQueryParam, BaseSchema, TenantByQueryParam, TenantBySchema, UserByQueryParam, UserBySchema
|
||||
|
||||
|
||||
class PositionCreateSchema(BaseModel):
|
||||
@@ -51,14 +47,16 @@ class PositionOutSchema(PositionCreateSchema, BaseSchema, UserBySchema, TenantBy
|
||||
model_config = ConfigDict(from_attributes=True)
|
||||
|
||||
|
||||
@dataclass
|
||||
class PositionQueryParam(BaseQueryParam, UserByQueryParam, TenantByQueryParam):
|
||||
"""岗位管理查询参数"""
|
||||
|
||||
name: str | None = Query(None, description="岗位名称")
|
||||
status: int | None = Query(None, ge=0, le=1, description="状态(0:启动 1:停用)")
|
||||
name: str | None = Field(None, description="岗位名称")
|
||||
status: int | None = Field(None, ge=0, le=1, description="状态(0:启动 1:停用)")
|
||||
|
||||
def __post_init__(self) -> None:
|
||||
self.name = (QueueEnum.like.value, self.name)
|
||||
@model_validator(mode="after")
|
||||
def validate_query_params(self) -> "PositionQueryParam":
|
||||
if self.name:
|
||||
self.name = (QueueEnum.like.value, self.name)
|
||||
if isinstance(self.status, int):
|
||||
self.status = (QueueEnum.eq.value, self.status)
|
||||
return self
|
||||
|
||||
@@ -6,30 +6,19 @@ from fastapi_cache import FastAPICache
|
||||
from fastapi_cache.decorator import cache
|
||||
|
||||
from app.common.response import ResponseSchema, StreamResponse, SuccessResponse
|
||||
from app.core.base_params import PaginationQueryParam
|
||||
from app.core.base_schema import AuthSchema, BatchSetAvailable, PageResultSchema
|
||||
from app.core.base_schema import AuthSchema, BatchSetAvailable, PageResultSchema, PaginationQueryParam
|
||||
from app.core.dependencies import AuthPermission
|
||||
from app.core.router_class import OperationLogRoute
|
||||
from app.utils.common_util import bytes2file_response
|
||||
|
||||
from .schema import (
|
||||
RoleCreateSchema,
|
||||
RoleOutSchema,
|
||||
RolePermissionSettingSchema,
|
||||
RoleQueryParam,
|
||||
RoleUpdateSchema,
|
||||
)
|
||||
from .schema import RoleCreateSchema, RoleOutSchema, RolePermissionSettingSchema, RoleQueryParam, RoleUpdateSchema
|
||||
from .service import RoleService
|
||||
|
||||
RoleRouter = APIRouter(route_class=OperationLogRoute, prefix="/role", tags=["角色管理"])
|
||||
|
||||
_ROLE_NS = "role"
|
||||
|
||||
@RoleRouter.get(
|
||||
"/list",
|
||||
summary="查询角色",
|
||||
response_model=ResponseSchema[PageResultSchema[RoleOutSchema]],
|
||||
)
|
||||
@RoleRouter.get("/list", summary="查询角色", response_model=ResponseSchema[PageResultSchema[RoleOutSchema]])
|
||||
@cache(expire=300, namespace=_ROLE_NS)
|
||||
async def get_role_list_controller(
|
||||
auth: Annotated[AuthSchema, Depends(AuthPermission(["module_system:role:query"]))],
|
||||
@@ -47,11 +36,7 @@ async def get_role_list_controller(
|
||||
)
|
||||
return SuccessResponse(data=result_dict, msg="查询角色成功")
|
||||
|
||||
@RoleRouter.get(
|
||||
"/detail/{id}",
|
||||
summary="查询角色详情",
|
||||
response_model=ResponseSchema[RoleOutSchema],
|
||||
)
|
||||
@RoleRouter.get("/detail/{id}", summary="查询角色详情", response_model=ResponseSchema[RoleOutSchema])
|
||||
async def get_role_detail_controller(
|
||||
auth: Annotated[AuthSchema, Depends(AuthPermission(["module_system:role:detail"]))],
|
||||
id: Annotated[int, Path(description="角色ID")],
|
||||
@@ -59,11 +44,7 @@ async def get_role_detail_controller(
|
||||
result_dict = await RoleService(auth).detail(id=id)
|
||||
return SuccessResponse(data=result_dict, msg="获取角色详情成功")
|
||||
|
||||
@RoleRouter.post(
|
||||
"/create",
|
||||
summary="创建角色",
|
||||
response_model=ResponseSchema[RoleOutSchema],
|
||||
)
|
||||
@RoleRouter.post("/create", summary="创建角色", response_model=ResponseSchema[RoleOutSchema])
|
||||
async def create_role_controller(
|
||||
auth: Annotated[AuthSchema, Depends(AuthPermission(["module_system:role:create"]))],
|
||||
data: Annotated[RoleCreateSchema, Body(description="角色创建参数")],
|
||||
@@ -72,11 +53,7 @@ async def create_role_controller(
|
||||
await FastAPICache.clear(namespace=_ROLE_NS)
|
||||
return SuccessResponse(data=result_dict, msg="创建角色成功")
|
||||
|
||||
@RoleRouter.put(
|
||||
"/update/{id}",
|
||||
summary="修改角色",
|
||||
response_model=ResponseSchema[RoleOutSchema],
|
||||
)
|
||||
@RoleRouter.put("/update/{id}", summary="修改角色", response_model=ResponseSchema[RoleOutSchema])
|
||||
async def update_role_controller(
|
||||
auth: Annotated[AuthSchema, Depends(AuthPermission(["module_system:role:update"]))],
|
||||
id: Annotated[int, Path(description="角色ID")],
|
||||
@@ -86,11 +63,7 @@ async def update_role_controller(
|
||||
await FastAPICache.clear(namespace=_ROLE_NS)
|
||||
return SuccessResponse(data=result_dict, msg="修改角色成功")
|
||||
|
||||
@RoleRouter.delete(
|
||||
"/delete",
|
||||
summary="删除角色",
|
||||
response_model=ResponseSchema[None],
|
||||
)
|
||||
@RoleRouter.delete("/delete", summary="删除角色", response_model=ResponseSchema[None])
|
||||
async def delete_role_controller(
|
||||
auth: Annotated[AuthSchema, Depends(AuthPermission(["module_system:role:delete"]))],
|
||||
ids: Annotated[list[int], Body(description="ID列表")],
|
||||
@@ -99,11 +72,7 @@ async def delete_role_controller(
|
||||
await FastAPICache.clear(namespace=_ROLE_NS)
|
||||
return SuccessResponse(msg="删除角色成功")
|
||||
|
||||
@RoleRouter.patch(
|
||||
"/status/batch",
|
||||
summary="批量修改角色状态",
|
||||
response_model=ResponseSchema[None],
|
||||
)
|
||||
@RoleRouter.patch("/status/batch", summary="批量修改角色状态", response_model=ResponseSchema[None])
|
||||
async def batch_set_available_role_controller(
|
||||
auth: Annotated[AuthSchema, Depends(AuthPermission(["module_system:role:patch"]))],
|
||||
data: Annotated[BatchSetAvailable, Body(description="状态设置")],
|
||||
@@ -112,11 +81,7 @@ async def batch_set_available_role_controller(
|
||||
await FastAPICache.clear(namespace=_ROLE_NS)
|
||||
return SuccessResponse(msg="批量修改角色状态成功")
|
||||
|
||||
@RoleRouter.put(
|
||||
"/permission",
|
||||
summary="角色授权",
|
||||
response_model=ResponseSchema[None],
|
||||
)
|
||||
@RoleRouter.put("/permission", summary="角色授权", response_model=ResponseSchema[None])
|
||||
async def set_role_permission_controller(
|
||||
auth: Annotated[AuthSchema, Depends(AuthPermission(["module_system:role:permission"]))],
|
||||
data: Annotated[RolePermissionSettingSchema, Body(description="角色授权参数")],
|
||||
@@ -125,15 +90,11 @@ async def set_role_permission_controller(
|
||||
await FastAPICache.clear(namespace=_ROLE_NS)
|
||||
return SuccessResponse(msg="授权角色成功")
|
||||
|
||||
@RoleRouter.get(
|
||||
"/export",
|
||||
summary="导出角色",
|
||||
response_model=ResponseSchema[None],
|
||||
)
|
||||
@RoleRouter.get("/export", summary="导出角色")
|
||||
async def export_role_list_controller(
|
||||
auth: Annotated[AuthSchema, Depends(AuthPermission(["module_system:role:export"]))],
|
||||
search: Annotated[RoleQueryParam, Query(description="角色查询参数")],
|
||||
) -> StreamingResponse:
|
||||
) -> StreamingResponse[bytes]:
|
||||
role_query_result = await RoleService(auth).get_list(search=search)
|
||||
role_export_result = RoleService.export_list(role_list=role_query_result)
|
||||
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
from dataclasses import dataclass
|
||||
|
||||
from fastapi import Query
|
||||
from pydantic import (
|
||||
BaseModel,
|
||||
ConfigDict,
|
||||
@@ -12,8 +9,7 @@ from pydantic import (
|
||||
from app.api.v1.module_platform.menu.schema import MenuOutSchema
|
||||
from app.api.v1.module_system.dept.schema import DeptOutSchema
|
||||
from app.common.enums import QueueEnum
|
||||
from app.core.base_params import BaseQueryParam, TenantByQueryParam, UserByQueryParam
|
||||
from app.core.base_schema import BaseSchema, TenantBySchema, UserBySchema
|
||||
from app.core.base_schema import BaseQueryParam, BaseSchema, TenantByQueryParam, TenantBySchema, UserByQueryParam, UserBySchema
|
||||
from app.core.validator import (
|
||||
role_permission_request_validator,
|
||||
validate_required_code,
|
||||
@@ -104,19 +100,21 @@ class RoleOutSchema(RoleCreateSchema, BaseSchema, UserBySchema, TenantBySchema):
|
||||
depts: list[DeptOutSchema] = Field(default_factory=list, description="角色部门列表")
|
||||
|
||||
|
||||
@dataclass
|
||||
class RoleQueryParam(BaseQueryParam, UserByQueryParam, TenantByQueryParam):
|
||||
"""
|
||||
角色管理查询参数
|
||||
"""
|
||||
|
||||
name: str | None = Query(None, description="角色名称")
|
||||
code: str | None = Query(None, description="角色编码")
|
||||
status: int | None = Query(None, description="状态(0:启动 1:停用)")
|
||||
name: str | None = Field(None, description="角色名称")
|
||||
code: str | None = Field(None, description="角色编码")
|
||||
status: int | None = Field(None, description="状态(0:启动 1:停用)")
|
||||
|
||||
def __post_init__(self) -> None:
|
||||
self.name = (QueueEnum.like.value, self.name)
|
||||
@model_validator(mode="after")
|
||||
def validate_query_params(self) -> "RoleQueryParam":
|
||||
if self.name:
|
||||
self.name = (QueueEnum.like.value, self.name)
|
||||
if self.code:
|
||||
self.code = (QueueEnum.like.value, self.code)
|
||||
if self.status is not None:
|
||||
self.status = (QueueEnum.eq.value, self.status)
|
||||
return self
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
from typing import Any
|
||||
|
||||
from app.api.v1.module_platform.tenant.service import TenantService
|
||||
from app.core.base_schema import AuthSchema, BatchSetAvailable
|
||||
from app.core.exceptions import CustomException
|
||||
from app.utils.excel_util import ExcelUtil
|
||||
@@ -84,6 +83,8 @@ class RoleService:
|
||||
)
|
||||
|
||||
async def create(self, data: RoleCreateSchema) -> RoleOutSchema:
|
||||
from app.api.v1.module_platform.tenant.service import TenantService
|
||||
|
||||
"""
|
||||
创建角色
|
||||
|
||||
|
||||
@@ -4,18 +4,11 @@ from fastapi import APIRouter, Body, Depends, Path, Query
|
||||
from fastapi.responses import JSONResponse
|
||||
|
||||
from app.common.response import ResponseSchema, SuccessResponse
|
||||
from app.core.base_params import PaginationQueryParam
|
||||
from app.core.base_schema import AuthSchema, PageResultSchema
|
||||
from app.core.base_schema import AuthSchema, PageResultSchema, PaginationQueryParam
|
||||
from app.core.dependencies import AuthPermission
|
||||
from app.core.router_class import OperationLogRoute
|
||||
|
||||
from .schema import (
|
||||
TicketBatchSchema,
|
||||
TicketCreateSchema,
|
||||
TicketOutSchema,
|
||||
TicketQueryParam,
|
||||
TicketUpdateSchema,
|
||||
)
|
||||
from .schema import TicketBatchSchema, TicketCreateSchema, TicketOutSchema, TicketQueryParam, TicketUpdateSchema
|
||||
from .service import TicketService
|
||||
|
||||
TicketRouter = APIRouter(route_class=OperationLogRoute, prefix="/ticket", tags=["工单管理"])
|
||||
|
||||
@@ -1,11 +1,7 @@
|
||||
from dataclasses import dataclass
|
||||
|
||||
from fastapi import Query
|
||||
from pydantic import BaseModel, ConfigDict, Field, field_validator
|
||||
from pydantic import BaseModel, ConfigDict, Field, field_validator, model_validator
|
||||
|
||||
from app.common.enums import QueueEnum, TicketTypeEnum
|
||||
from app.core.base_params import BaseQueryParam, TenantByQueryParam, UserByQueryParam
|
||||
from app.core.base_schema import BaseSchema, CommonSchema, TenantBySchema, UserBySchema
|
||||
from app.core.base_schema import BaseQueryParam, BaseSchema, CommonSchema, TenantByQueryParam, TenantBySchema, UserByQueryParam, UserBySchema
|
||||
|
||||
|
||||
class TicketCreateSchema(BaseModel):
|
||||
@@ -79,16 +75,16 @@ class TicketBatchSchema(BaseModel):
|
||||
return v
|
||||
|
||||
|
||||
@dataclass
|
||||
class TicketQueryParam(BaseQueryParam, UserByQueryParam, TenantByQueryParam):
|
||||
"""工单查询参数"""
|
||||
|
||||
title: str | None = None
|
||||
ticket_type: str | None = None
|
||||
assigned_id: int | None = None
|
||||
status: int | None = Query(None, ge=0, le=3, description="状态(0:待处理 1:处理中 2:已完成 3:已关闭)")
|
||||
title: str | None = Field(None, description="工单标题")
|
||||
ticket_type: str | None = Field(None, description="工单类型")
|
||||
assigned_id: int | None = Field(None, description="处理人ID")
|
||||
status: int | None = Field(None, ge=0, le=3, description="状态(0:待处理 1:处理中 2:已完成 3:已关闭)")
|
||||
|
||||
def __post_init__(self) -> None:
|
||||
@model_validator(mode="after")
|
||||
def validate_query_params(self) -> "TicketQueryParam":
|
||||
if self.title:
|
||||
self.title = (QueueEnum.like.value, self.title)
|
||||
if self.ticket_type:
|
||||
@@ -97,3 +93,4 @@ class TicketQueryParam(BaseQueryParam, UserByQueryParam, TenantByQueryParam):
|
||||
self.assigned_id = (QueueEnum.eq.value, self.assigned_id)
|
||||
if isinstance(self.status, int):
|
||||
self.status = (QueueEnum.eq.value, self.status)
|
||||
return self
|
||||
|
||||
@@ -6,8 +6,7 @@ from fastapi.responses import JSONResponse, StreamingResponse
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from app.common.response import ResponseSchema, StreamResponse, SuccessResponse
|
||||
from app.core.base_params import PaginationQueryParam
|
||||
from app.core.base_schema import AuthSchema, BatchSetAvailable, PageResultSchema
|
||||
from app.core.base_schema import AuthSchema, BatchSetAvailable, PageResultSchema, PaginationQueryParam
|
||||
from app.core.dependencies import AuthPermission, db_getter, get_current_user
|
||||
from app.core.logger import logger
|
||||
from app.core.router_class import OperationLogRoute
|
||||
@@ -28,22 +27,14 @@ from .service import UserService
|
||||
|
||||
UserRouter = APIRouter(route_class=OperationLogRoute, prefix="/user", tags=["用户管理"])
|
||||
|
||||
@UserRouter.get(
|
||||
"/current/info",
|
||||
summary="查询当前用户信息",
|
||||
response_model=ResponseSchema[UserOutSchema],
|
||||
)
|
||||
@UserRouter.get("/current/info", summary="查询当前用户信息", response_model=ResponseSchema[UserOutSchema])
|
||||
async def get_current_user_info_controller(
|
||||
auth: Annotated[AuthSchema, Depends(get_current_user)],
|
||||
) -> JSONResponse:
|
||||
user_dict = await UserService(auth).current_info()
|
||||
return SuccessResponse(data=user_dict, msg="获取当前用户信息成功")
|
||||
|
||||
@UserRouter.put(
|
||||
"/current/info/update",
|
||||
summary="更新当前用户基本信息",
|
||||
response_model=ResponseSchema[UserOutSchema],
|
||||
)
|
||||
@UserRouter.put("/current/info/update",summary="更新当前用户基本信息",response_model=ResponseSchema[UserOutSchema])
|
||||
async def update_current_user_info_controller(
|
||||
auth: Annotated[AuthSchema, Depends(get_current_user)],
|
||||
data: Annotated[CurrentUserUpdateSchema, Body(description="更新用户基本信息参数")],
|
||||
@@ -51,11 +42,7 @@ async def update_current_user_info_controller(
|
||||
result_dict = await UserService(auth).update_current_info(data=data)
|
||||
return SuccessResponse(data=result_dict, msg="更新当前用户基本信息成功")
|
||||
|
||||
@UserRouter.put(
|
||||
"/password/change",
|
||||
summary="修改当前用户密码",
|
||||
response_model=ResponseSchema[UserOutSchema],
|
||||
)
|
||||
@UserRouter.put("/password/change", summary="修改当前用户密码", response_model=ResponseSchema[UserOutSchema])
|
||||
async def change_current_user_password_controller(
|
||||
auth: Annotated[AuthSchema, Depends(get_current_user)],
|
||||
data: Annotated[UserChangePasswordSchema, Body(description="修改用户密码参数")],
|
||||
@@ -63,11 +50,7 @@ async def change_current_user_password_controller(
|
||||
result_dict = await UserService(auth).change_password(data=data)
|
||||
return SuccessResponse(data=result_dict, msg="修改密码成功, 请重新登录")
|
||||
|
||||
@UserRouter.put(
|
||||
"/password/reset/{id}",
|
||||
summary="重置用户密码",
|
||||
response_model=ResponseSchema[UserOutSchema],
|
||||
)
|
||||
@UserRouter.put("/password/reset/{id}", summary="重置用户密码", response_model=ResponseSchema[UserOutSchema])
|
||||
async def reset_password_controller(
|
||||
auth: Annotated[AuthSchema, Depends(AuthPermission(["module_system:user:update"]))],
|
||||
id: Annotated[int, Path(description="用户ID")],
|
||||
@@ -77,11 +60,7 @@ async def reset_password_controller(
|
||||
result_dict = await UserService(auth).reset_password(data=data)
|
||||
return SuccessResponse(data=result_dict, msg="重置密码成功")
|
||||
|
||||
@UserRouter.post(
|
||||
"/register",
|
||||
summary="注册用户",
|
||||
response_model=ResponseSchema[UserOutSchema],
|
||||
)
|
||||
@UserRouter.post("/register", summary="注册用户", response_model=ResponseSchema[UserOutSchema])
|
||||
async def register_user_controller(
|
||||
db: Annotated[AsyncSession, Depends(db_getter)],
|
||||
data: Annotated[UserRegisterSchema, Body(description="注册用户参数")],
|
||||
@@ -91,11 +70,7 @@ async def register_user_controller(
|
||||
logger.info(f"{data.username} 注册用户成功: {user_register_result}")
|
||||
return SuccessResponse(data=user_register_result, msg="注册用户成功")
|
||||
|
||||
@UserRouter.post(
|
||||
"/password/forget",
|
||||
summary="忘记密码",
|
||||
response_model=ResponseSchema[UserOutSchema],
|
||||
)
|
||||
@UserRouter.post("/password/forget", summary="忘记密码", response_model=ResponseSchema[UserOutSchema])
|
||||
async def forget_password_controller(
|
||||
db: Annotated[AsyncSession, Depends(db_getter)],
|
||||
data: Annotated[UserForgetPasswordSchema, Body(description="忘记密码参数")],
|
||||
@@ -105,11 +80,7 @@ async def forget_password_controller(
|
||||
logger.info(f"{data.username} 重置密码成功: {user_forget_password_result}")
|
||||
return SuccessResponse(data=user_forget_password_result, msg="重置密码成功")
|
||||
|
||||
@UserRouter.get(
|
||||
"/list",
|
||||
summary="查询用户",
|
||||
response_model=ResponseSchema[PageResultSchema[UserOutSchema]],
|
||||
)
|
||||
@UserRouter.get("/list", summary="查询用户", response_model=ResponseSchema[PageResultSchema[UserOutSchema]])
|
||||
async def get_user_list_controller(
|
||||
auth: Annotated[AuthSchema, Depends(AuthPermission(["module_system:user:query"]))],
|
||||
page: Annotated[PaginationQueryParam, Query(description="分页参数")],
|
||||
@@ -123,11 +94,7 @@ async def get_user_list_controller(
|
||||
)
|
||||
return SuccessResponse(data=result_dict, msg="查询用户成功")
|
||||
|
||||
@UserRouter.get(
|
||||
"/detail/{id}",
|
||||
summary="查询用户详情",
|
||||
response_model=ResponseSchema[UserOutSchema],
|
||||
)
|
||||
@UserRouter.get("/detail/{id}", summary="查询用户详情", response_model=ResponseSchema[UserOutSchema])
|
||||
async def get_user_detail_controller(
|
||||
auth: Annotated[AuthSchema, Depends(AuthPermission(["module_system:user:detail"]))],
|
||||
id: Annotated[int, Path(description="用户ID")],
|
||||
@@ -135,11 +102,7 @@ async def get_user_detail_controller(
|
||||
result_dict = await UserService(auth).detail(id=id)
|
||||
return SuccessResponse(data=result_dict, msg="获取用户详情成功")
|
||||
|
||||
@UserRouter.post(
|
||||
"/create",
|
||||
summary="创建用户",
|
||||
response_model=ResponseSchema[UserOutSchema],
|
||||
)
|
||||
@UserRouter.post("/create", summary="创建用户", response_model=ResponseSchema[UserOutSchema])
|
||||
async def create_user_controller(
|
||||
auth: Annotated[AuthSchema, Depends(AuthPermission(["module_system:user:create"]))],
|
||||
data: Annotated[UserCreateSchema, Body(description="创建用户参数")],
|
||||
@@ -147,11 +110,7 @@ async def create_user_controller(
|
||||
result_dict = await UserService(auth).create(data=data)
|
||||
return SuccessResponse(data=result_dict, msg="创建用户成功")
|
||||
|
||||
@UserRouter.put(
|
||||
"/update/{id}",
|
||||
summary="修改用户",
|
||||
response_model=ResponseSchema[UserOutSchema],
|
||||
)
|
||||
@UserRouter.put("/update/{id}", summary="修改用户", response_model=ResponseSchema[UserOutSchema])
|
||||
async def update_user_controller(
|
||||
auth: Annotated[AuthSchema, Depends(AuthPermission(["module_system:user:update"]))],
|
||||
id: Annotated[int, Path(description="用户ID")],
|
||||
@@ -160,11 +119,7 @@ async def update_user_controller(
|
||||
result_dict = await UserService(auth).update(id=id, data=data)
|
||||
return SuccessResponse(data=result_dict, msg="修改用户成功")
|
||||
|
||||
@UserRouter.delete(
|
||||
"/delete",
|
||||
summary="删除用户",
|
||||
response_model=ResponseSchema[None],
|
||||
)
|
||||
@UserRouter.delete("/delete", summary="删除用户", response_model=ResponseSchema[None])
|
||||
async def delete_user_controller(
|
||||
auth: Annotated[AuthSchema, Depends(AuthPermission(["module_system:user:delete"]))],
|
||||
ids: Annotated[list[int], Body(description="ID列表")],
|
||||
@@ -172,11 +127,7 @@ async def delete_user_controller(
|
||||
await UserService(auth).delete(ids=ids)
|
||||
return SuccessResponse(msg="删除用户成功")
|
||||
|
||||
@UserRouter.patch(
|
||||
"/status/batch",
|
||||
summary="批量修改用户状态",
|
||||
response_model=ResponseSchema[None],
|
||||
)
|
||||
@UserRouter.patch("/status/batch", summary="批量修改用户状态", response_model=ResponseSchema[None])
|
||||
async def batch_set_available_user_controller(
|
||||
auth: Annotated[AuthSchema, Depends(AuthPermission(["module_system:user:patch"]))],
|
||||
data: Annotated[BatchSetAvailable, Body(description="状态设置")],
|
||||
@@ -184,13 +135,8 @@ async def batch_set_available_user_controller(
|
||||
await UserService(auth).set_available(data=data)
|
||||
return SuccessResponse(msg="批量修改用户状态成功")
|
||||
|
||||
@UserRouter.get(
|
||||
"/import/template",
|
||||
summary="获取用户导入模板",
|
||||
response_model=ResponseSchema[None],
|
||||
dependencies=[Depends(AuthPermission(["module_system:user:download"]))],
|
||||
)
|
||||
async def export_user_import_template_controller() -> StreamingResponse:
|
||||
@UserRouter.get("/import/template", summary="获取用户导入模板", dependencies=[Depends(AuthPermission(["module_system:user:download"]))])
|
||||
async def export_user_import_template_controller() -> StreamingResponse[bytes]:
|
||||
user_import_template_result = UserService.get_import_template()
|
||||
|
||||
return StreamResponse(
|
||||
@@ -202,16 +148,12 @@ async def export_user_import_template_controller() -> StreamingResponse:
|
||||
},
|
||||
)
|
||||
|
||||
@UserRouter.get(
|
||||
"/export",
|
||||
summary="导出用户",
|
||||
response_model=ResponseSchema[None],
|
||||
)
|
||||
@UserRouter.get("/export", summary="导出用户", response_model=StreamResponse[bytes])
|
||||
async def export_user_list_controller(
|
||||
auth: Annotated[AuthSchema, Depends(AuthPermission(["module_system:user:export"]))],
|
||||
page: Annotated[PaginationQueryParam, Query(description="分页参数")],
|
||||
search: Annotated[UserQueryParam, Query(description="用户查询参数")],
|
||||
) -> StreamingResponse:
|
||||
) -> StreamingResponse[bytes]:
|
||||
user_list = await UserService(auth).get_list(search=search, order_by=page.order_by)
|
||||
user_export_result = UserService.export_list(user_list=user_list)
|
||||
|
||||
@@ -221,11 +163,7 @@ async def export_user_list_controller(
|
||||
headers={"Content-Disposition": "attachment; filename=user.xlsx"},
|
||||
)
|
||||
|
||||
@UserRouter.post(
|
||||
"/import/data",
|
||||
summary="导入用户",
|
||||
response_model=ResponseSchema[None],
|
||||
)
|
||||
@UserRouter.post("/import/data", summary="导入用户", response_model=ResponseSchema[None])
|
||||
async def import_user_list_controller(
|
||||
file: Annotated[UploadFile, File(description="用户导入文件")],
|
||||
auth: Annotated[AuthSchema, Depends(AuthPermission(["module_system:user:import"]))],
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
from dataclasses import dataclass
|
||||
from urllib.parse import urlparse
|
||||
|
||||
from fastapi import Query
|
||||
from pydantic import (
|
||||
BaseModel,
|
||||
ConfigDict,
|
||||
@@ -14,8 +12,7 @@ from pydantic import (
|
||||
from app.api.v1.module_platform.menu.schema import MenuOutSchema
|
||||
from app.api.v1.module_system.role.schema import RoleOutSchema
|
||||
from app.common.enums import QueueEnum
|
||||
from app.core.base_params import BaseQueryParam, TenantByQueryParam, UserByQueryParam
|
||||
from app.core.base_schema import BaseSchema, CommonSchema, TenantBySchema, UserBySchema
|
||||
from app.core.base_schema import BaseQueryParam, BaseSchema, CommonSchema, TenantByQueryParam, TenantBySchema, UserByQueryParam, UserBySchema
|
||||
from app.core.validator import email_validator, mobile_validator
|
||||
|
||||
|
||||
@@ -296,7 +293,6 @@ class UserOutSchema(UserUpdateSchema, BaseSchema, UserBySchema, TenantBySchema):
|
||||
menus: list[MenuOutSchema] | None = Field(default=[], description="菜单")
|
||||
|
||||
|
||||
@dataclass
|
||||
class UserQueryParam(BaseQueryParam, UserByQueryParam, TenantByQueryParam):
|
||||
"""
|
||||
用户管理查询参数(继承标准 Mixin)
|
||||
@@ -308,25 +304,29 @@ class UserQueryParam(BaseQueryParam, UserByQueryParam, TenantByQueryParam):
|
||||
- 业务字段:用户名、名称、手机号、邮箱、部门、状态
|
||||
"""
|
||||
|
||||
username: str | None = Query(None, description="用户名")
|
||||
name: str | None = Query(None, description="名称")
|
||||
mobile: str | None = Query(None, description="手机号", pattern=r"^1[3-9]\d{9}$")
|
||||
email: str | None = Query(
|
||||
username: str | None = Field(None, description="用户名")
|
||||
name: str | None = Field(None, description="名称")
|
||||
mobile: str | None = Field(None, description="手机号", pattern=r"^1[3-9]\d{9}$")
|
||||
email: str | None = Field(
|
||||
None,
|
||||
description="邮箱",
|
||||
pattern=r"^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$",
|
||||
)
|
||||
dept_id: int | None = Query(None, description="部门ID")
|
||||
status: int | None = Query(None, description="是否可用")
|
||||
dept_id: int | None = Field(None, description="部门ID")
|
||||
status: int | None = Field(None, description="是否可用")
|
||||
|
||||
def __post_init__(self) -> None:
|
||||
self.username = (QueueEnum.like.value, self.username)
|
||||
self.name = (QueueEnum.like.value, self.name)
|
||||
@model_validator(mode="after")
|
||||
def validate_query_params(self) -> "UserQueryParam":
|
||||
if self.username:
|
||||
self.username = (QueueEnum.like.value, self.username)
|
||||
if self.name:
|
||||
self.name = (QueueEnum.like.value, self.name)
|
||||
if self.mobile:
|
||||
self.mobile = (QueueEnum.like.value, self.mobile)
|
||||
if self.email:
|
||||
self.email = (QueueEnum.like.value, self.email)
|
||||
if self.dept_id:
|
||||
self.dept_id = (QueueEnum.eq.value, self.dept_id)
|
||||
if self.status:
|
||||
if self.status is not None:
|
||||
self.status = (QueueEnum.eq.value, self.status)
|
||||
return self
|
||||
|
||||
@@ -2,10 +2,6 @@ from typing import Any
|
||||
|
||||
from fastapi import UploadFile
|
||||
|
||||
from app.api.v1.module_platform.menu.crud import MenuCRUD
|
||||
from app.api.v1.module_platform.menu.schema import MenuOutSchema
|
||||
from app.api.v1.module_platform.package.service import PackageService
|
||||
from app.api.v1.module_platform.tenant.service import TenantService
|
||||
from app.api.v1.module_system.dept.crud import DeptCRUD
|
||||
from app.api.v1.module_system.position.crud import PositionCRUD
|
||||
from app.api.v1.module_system.role.crud import RoleCRUD
|
||||
@@ -69,6 +65,8 @@ class UserService:
|
||||
)
|
||||
|
||||
async def create(self, data: UserCreateSchema) -> UserOutSchema:
|
||||
from app.api.v1.module_platform.tenant.service import TenantService
|
||||
|
||||
if not data.username:
|
||||
raise CustomException(msg="用户名不能为空")
|
||||
if data.is_superuser:
|
||||
@@ -161,6 +159,10 @@ class UserService:
|
||||
await UserCRUD(self.auth).delete(ids=ids)
|
||||
|
||||
async def current_info(self) -> UserOutSchema:
|
||||
from app.api.v1.module_platform.menu.crud import MenuCRUD
|
||||
from app.api.v1.module_platform.menu.schema import MenuOutSchema
|
||||
from app.api.v1.module_platform.package.service import PackageService
|
||||
|
||||
if not self.auth.user or not self.auth.user.id:
|
||||
raise CustomException(msg="该数据不存在")
|
||||
user = await UserCRUD(self.auth).get(id=self.auth.user.id)
|
||||
|
||||
Reference in New Issue
Block a user