From afe1ae83531898977a330082994167cb16679a6d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=9A=93=E6=9C=88=E5=BD=92=E5=B0=98?= Date: Sun, 23 Feb 2025 23:50:42 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E7=BB=99=E7=BC=96=E7=A0=81=E7=AE=A1?= =?UTF-8?q?=E7=90=86=E6=B7=BB=E5=8A=A0=E6=8C=89=E9=92=AE=E7=BA=A7=E6=9D=83?= =?UTF-8?q?=E9=99=90=E7=AE=A1=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- api/code.py | 228 +++++++++++++++++++++++++----------------------- schemas/code.py | 15 +--- 2 files changed, 119 insertions(+), 124 deletions(-) diff --git a/api/code.py b/api/code.py index b892030..691ddbc 100644 --- a/api/code.py +++ b/api/code.py @@ -16,28 +16,29 @@ from fastapi import APIRouter, Depends, Path, Request, Query from fastapi.encoders import jsonable_encoder from fastapi.responses import JSONResponse, FileResponse +from annotation.auth import Auth from annotation.log import Log from config.constant import BusinessType from config.env import ElasticSearchConfig from controller.login import LoginController from exceptions.exception import ServiceException, PermissionException from models import File, Code, QueryCode, QueryCodeLog -from schemas.code import GetCodeInfoResponse, GetCodeListResponse, GetQueryCodeParams, \ - DeleteCodeListParams, QueryCodeResponse, AddCodeParams, GetQueryCodeLogResponse, GetQueryCodeLogDetailResponse, \ +from schemas.code import GetCodeInfoResponse, GetCodeListResponse, GetQueryCodeParams, QueryCodeResponse, AddCodeParams, \ + GetQueryCodeLogResponse, GetQueryCodeLogDetailResponse, \ GetCodeLogAllResponse -from schemas.common import BaseResponse +from schemas.common import BaseResponse, DeleteListParams from utils.log import logger from utils.response import Response codeAPI = APIRouter( - prefix="/code", - dependencies=[Depends(LoginController.get_current_user)] + prefix="/code" ) @codeAPI.get("/template", summary="获取上传编码模板") @Log(title="获取上传编码模板", business_type=BusinessType.SELECT) -async def get_upload_template(request: Request): +@Auth(permission_list=["code:btn:uploadTemplate"]) +async def get_upload_template(request: Request, current_user=Depends(LoginController.get_current_user)): template_path = os.path.join(os.path.abspath(os.getcwd()), 'assets', 'templates', '上传模版.xlsx') if not os.path.exists(template_path): raise ServiceException(message="文件不存在!") @@ -50,7 +51,8 @@ async def get_upload_template(request: Request): @codeAPI.get("/queryTemplate", summary="获取查询编码模板") @Log(title="获取查询编码模板", business_type=BusinessType.SELECT) -async def get_query_template(request: Request): +@Auth(permission_list=["code:btn:queryTemplate"]) +async def get_query_template(request: Request, current_user=Depends(LoginController.get_current_user)): template_path = os.path.join(os.path.abspath(os.getcwd()), 'assets', 'templates', '查询模版.xlsx') if not os.path.exists(template_path): raise ServiceException(message="文件不存在!") @@ -63,11 +65,12 @@ async def get_query_template(request: Request): @codeAPI.post("/add", response_class=JSONResponse, response_model=BaseResponse, summary="添加编码") @Log(title="添加编码", business_type=BusinessType.INSERT) -async def add_code(request: Request, params: AddCodeParams): +@Auth(permission_list=["code:btn:add"]) +async def add_code(request: Request, params: AddCodeParams, current_user=Depends(LoginController.get_current_user)): params.code = params.code.replace(".", "").replace("/", "").replace("_", "").replace("-", "").replace("?", "").replace( ":", "").replace(":", "").replace("?", "").strip() - if await Code.get_or_none(code=params.code): + if await Code.get_or_none(code=params.code, del_flag=1): return Response.failure(msg="编码已存在") else: if await request.app.state.es.indices.exists(index=ElasticSearchConfig.ES_INDEX): @@ -97,19 +100,19 @@ async def add_code(request: Request, params: AddCodeParams): @codeAPI.get("/addCode/{id}", response_class=JSONResponse, response_model=BaseResponse, summary="导入编码") @Log(title="导入编码", business_type=BusinessType.INSERT) +@Auth(permission_list=["code:btn:import"]) async def add_code_by_file(request: Request, id: str = Path(description="文件ID"), current_user=Depends(LoginController.get_current_user)): user_id = current_user.get("id") - if file := await File.get_or_none(id=id): + if file := await File.get_or_none(id=id, del_flag=1): uploader_id = await file.first().values(id="uploader__id") if str(uploader_id["id"]) == user_id: try: df = pd.read_excel(file.absolute_path, dtype={"code": str}) df["code"] = df["code"].astype(str).str.zfill(8) for index, row in df.iterrows(): - print(row['code'],type(row['code'])) row["code"] = row["code"].replace(".", "").replace("/", "").replace("_", "").replace("-", - "").replace( + "").replace( "?", "").replace( ":", "").replace(":", "").replace("?", "").strip() @@ -146,9 +149,12 @@ async def add_code_by_file(request: Request, id: str = Path(description="文件I @codeAPI.delete("/delete/{id}", response_class=JSONResponse, response_model=BaseResponse, summary="删除编码") @codeAPI.post("/delete/{id}", response_class=JSONResponse, response_model=BaseResponse, summary="删除编码") @Log(title="删除编码", business_type=BusinessType.DELETE) -async def delete_code_by_id(request: Request, id: str = Path(description="编码ID"), ): - if code := await Code.get_or_none(id=id): - await code.delete() +@Auth(permission_list=["code:btn:delete"]) +async def delete_code_by_id(request: Request, id: str = Path(description="编码ID"), + current_user=Depends(LoginController.get_current_user)): + if code := await Code.get_or_none(id=id, del_flag=1): + code.del_flag = 0 + await code.save() await request.app.state.es.delete(index=ElasticSearchConfig.ES_INDEX, id=code.code) return Response.success(msg="删除成功") else: @@ -158,10 +164,13 @@ async def delete_code_by_id(request: Request, id: str = Path(description="编码 @codeAPI.delete("/deleteList", response_class=JSONResponse, response_model=BaseResponse, summary="批量删除编码") @codeAPI.post("/deleteList", response_class=JSONResponse, response_model=BaseResponse, summary="批量删除编码") @Log(title="批量删除编码", business_type=BusinessType.DELETE) -async def delete_code_by_ids(request: Request, params: DeleteCodeListParams): +@Auth(permission_list=["code:btn:delete"]) +async def delete_code_by_ids(request: Request, params: DeleteListParams, + current_user=Depends(LoginController.get_current_user)): for id in set(params.ids): - if code := await Code.get_or_none(id=id): - await code.delete() + if code := await Code.get_or_none(id=id, del_flag=1): + code.del_flag = 0 + await code.save() await request.app.state.es.delete(index=ElasticSearchConfig.ES_INDEX, id=code.code) return Response.success(msg="删除成功") @@ -169,10 +178,12 @@ async def delete_code_by_ids(request: Request, params: DeleteCodeListParams): @codeAPI.put("/update/{id}", response_class=JSONResponse, response_model=BaseResponse, summary="更新编码") @codeAPI.post("/update/{id}", response_class=JSONResponse, response_model=BaseResponse, summary="更新编码") @Log(title="更新编码", business_type=BusinessType.UPDATE) +@Auth(permission_list=["code:btn:update"]) async def update_code(request: Request, params: AddCodeParams, - id: str = Path(description="编码ID")): - if code := await Code.get_or_none(id=id): + id: str = Path(description="编码ID"), + current_user=Depends(LoginController.get_current_user)): + if code := await Code.get_or_none(id=id, del_flag=1): code.code = params.code code.description = params.description await code.save() @@ -184,8 +195,10 @@ async def update_code(request: Request, @codeAPI.get("/info/{id}", response_class=JSONResponse, response_model=GetCodeInfoResponse, summary="获取编码信息") @Log(title="获取编码信息", business_type=BusinessType.SELECT) -async def get_code_info(request: Request, id: str = Path(description="编码ID")): - if code := await Code.get_or_none(id=id).values( +@Auth(permission_list=["code:btn:info"]) +async def get_code_info(request: Request, id: str = Path(description="编码ID"), + current_user=Depends(LoginController.get_current_user)): + if code := await Code.get_or_none(id=id, del_flag=1).values( id="id", code="code", description="description", @@ -200,19 +213,21 @@ async def get_code_info(request: Request, id: str = Path(description="编码ID") @codeAPI.get("/list", response_class=JSONResponse, response_model=GetCodeListResponse, summary="获取编码列表") @Log(title="获取编码列表", business_type=BusinessType.SELECT) +@Auth(permission_list=["code:btn:list"]) async def get_code_list(request: Request, page: int = Query(default=1, description="页码"), pageSize: int = Query(default=10, description="每页数量"), code: Optional[str] = Query(default=None, description="编码"), - description: Optional[str] = Query(default=None, description="商品描述")): + description: Optional[str] = Query(default=None, description="商品描述"), + current_user=Depends(LoginController.get_current_user)): filterArgs = { f'{k}__contains': v for k, v in { 'code': code, 'description': description }.items() if v } - total = await Code.filter(**filterArgs).count() - data = await Code.filter(**filterArgs).offset((page - 1) * pageSize).limit(pageSize).values( + total = await Code.filter(**filterArgs, del_flag=1).count() + data = await Code.filter(**filterArgs, del_flag=1).offset((page - 1) * pageSize).limit(pageSize).values( id="id", code="code", description="description", @@ -231,6 +246,7 @@ async def get_code_list(request: Request, @codeAPI.post("/query", response_class=JSONResponse, response_model=QueryCodeResponse, summary="查询编码") @Log(title="查询编码", business_type=BusinessType.SELECT) +@Auth(permission_list=["code:btn:query"]) async def get_code_list(request: Request, params: GetQueryCodeParams, current_user: dict = Depends(LoginController.get_current_user), @@ -278,7 +294,7 @@ async def get_code_list(request: Request, max_score = data["hits"].get("max_score", 1) # 处理每一条匹配结果 for hit in data["hits"]["hits"]: - code = await Code.get_or_none(code=hit["_source"]["code"]) + code = await Code.get_or_none(code=hit["_source"]["code"], del_flag=1) # 归一化匹配度,转换为百分比 match_rate = round((hit["_score"] / max_score) * 100, 2) # 归一化后计算百分比 # 将匹配结果添加到列表中 @@ -329,13 +345,14 @@ async def get_code_list(request: Request, @codeAPI.get("/query/{id}", response_class=JSONResponse, response_model=QueryCodeResponse, summary="查询编码") @Log(title="查询编码", business_type=BusinessType.SELECT) +@Auth(permission_list=["code:btn:importQuery"]) async def get_code_list(request: Request, id: str = Path(description="文件ID"), current_user: dict = Depends(LoginController.get_current_user), ): start_time = time.time() user_id = current_user.get("id") - if file := await File.get_or_none(id=id): + if file := await File.get_or_none(id=id, del_flag=1): uploader_id = await file.first().values(id="uploader__id") if str(uploader_id["id"]) == user_id: if log := await QueryCodeLog.create( @@ -379,7 +396,7 @@ async def get_code_list(request: Request, max_score = data["hits"].get("max_score", 1) # 处理每一条匹配结果 for hit in data["hits"]["hits"]: - code = await Code.get_or_none(code=hit["_source"]["code"]) + code = await Code.get_or_none(code=hit["_source"]["code"], del_flag=1) # 归一化匹配度,转换为百分比 match_rate = round((hit["_score"] / max_score) * 100, 2) # 归一化后计算百分比 # 将匹配结果添加到列表中 @@ -435,61 +452,53 @@ async def get_code_list(request: Request, @codeAPI.get("/logList", response_class=JSONResponse, response_model=GetQueryCodeLogResponse, summary="查询编码日志列表") @Log(title="查询编码日志列表", business_type=BusinessType.SELECT) +@Auth(permission_list=["code:btn:logList"]) async def get_code_log_list(request: Request, page: int = Query(default=1, description="当前页码"), pageSize: int = Query(default=10, description="每页数量"), + department_id: Optional[str] = Query(default=None, description="部门ID"), + username: Optional[str] = Query(default=None, description="用户账号"), + nickname: Optional[str] = Query(default=None, description="用户昵称"), startTime: Optional[str] = Query(default=None, description="开始时间"), endTime: Optional[str] = Query(default=None, description="结束时间"), current_user: dict = Depends(LoginController.get_current_user), ): - user_id = current_user.get("id") + sub_departments = current_user.get("sub_departments") + filterArgs = { + f'{k}__contains': v for k, v in { + 'operator__username': username, + 'operator__nickname': nickname, + }.items() if v + } if startTime and endTime: startTime = float(startTime) / 1000 endTime = float(endTime) / 1000 startTime = datetime.fromtimestamp(startTime) endTime = datetime.fromtimestamp(endTime) - count = await QueryCodeLog.filter(operator_id=user_id, del_flag=1, operation_time__gte=startTime, - operation_time__lte=endTime).count() - data = await QueryCodeLog.filter(operator_id=user_id, del_flag=1, operation_time__gte=startTime, - operation_time__lte=endTime).order_by("-operation_time").offset( - (page - 1) * pageSize).limit(pageSize).values( - id="id", - query_count="query_count", - result_count="result_count", - cost_time="cost_time", - operation_time="operation_time", - status="status", - request_params="request_params", - response_result="response_result", - create_time="create_time", - update_time="update_time", - operator_id="operator__id", - operator_name="operator__username", - operator_nickname="operator__nickname", - department_id="operator__department__id", - department_name="operator__department__name", - ) + filterArgs['operation_time__range'] = [startTime, endTime] + if not department_id: + filterArgs['operator__department__id__in'] = sub_departments else: - count = await QueryCodeLog.filter(operator_id=user_id, del_flag=1).count() - data = await QueryCodeLog.filter(operator_id=user_id, del_flag=1).order_by("-operation_time").offset( - (page - 1) * pageSize).limit(pageSize).values( - id="id", - query_count="query_count", - result_count="result_count", - cost_time="cost_time", - operation_time="operation_time", - status="status", - request_params="request_params", - response_result="response_result", - create_time="create_time", - update_time="update_time", - operator_id="operator__id", - operator_name="operator__username", - operator_nickname="operator__nickname", - department_id="operator__department__id", - department_name="operator__department__name", - ) - + filterArgs['operator__department__id'] = department_id + count = await QueryCodeLog.filter(**filterArgs, operator__del_flag=1, del_flag=1).count() + data = await QueryCodeLog.filter(**filterArgs, operator__del_flag=1, del_flag=1).order_by("-operation_time").offset( + (page - 1) * pageSize).limit(pageSize).values( + id="id", + query_count="query_count", + result_count="result_count", + cost_time="cost_time", + operation_time="operation_time", + status="status", + request_params="request_params", + response_result="response_result", + create_time="create_time", + update_time="update_time", + operator_id="operator__id", + operator_name="operator__username", + operator_nickname="operator__nickname", + department_id="operator__department__id", + department_name="operator__department__name", + ) return Response.success(data={ "page": page, "pageSize": pageSize, @@ -500,57 +509,51 @@ async def get_code_log_list(request: Request, @codeAPI.get("/logList/all", response_class=JSONResponse, response_model=GetCodeLogAllResponse, summary="查询所有编码日志列表") -@Log(title="查询所有编码日志列表", business_type=BusinessType.SELECT) +@Log(title="查询所有编码日志列表", business_type=BusinessType.EXPORT) +@Auth(permission_list=["code:btn:export"]) async def get_code_log_list(request: Request, + department_id: Optional[str] = Query(default=None, description="部门ID"), + username: Optional[str] = Query(default=None, description="用户账号"), + nickname: Optional[str] = Query(default=None, description="用户昵称"), startTime: Optional[str] = Query(default=None, description="开始时间"), endTime: Optional[str] = Query(default=None, description="结束时间"), current_user: dict = Depends(LoginController.get_current_user), ): - user_id = current_user.get("id") + sub_departments = current_user.get("sub_departments") + filterArgs = { + f'{k}__contains': v for k, v in { + 'operator__username': username, + 'operator__nickname': nickname, + }.items() if v + } if startTime and endTime: startTime = float(startTime) / 1000 endTime = float(endTime) / 1000 startTime = datetime.fromtimestamp(startTime) endTime = datetime.fromtimestamp(endTime) - count = await QueryCodeLog.filter(operator_id=user_id, del_flag=1, operation_time__gte=startTime, - operation_time__lte=endTime).count() - data = await QueryCodeLog.filter(operator_id=user_id, del_flag=1, operation_time__gte=startTime, - operation_time__lte=endTime).order_by("-operation_time").values( - id="id", - query_count="query_count", - result_count="result_count", - cost_time="cost_time", - operation_time="operation_time", - status="status", - request_params="request_params", - response_result="response_result", - create_time="create_time", - update_time="update_time", - operator_id="operator__id", - operator_name="operator__username", - operator_nickname="operator__nickname", - department_id="operator__department__id", - department_name="operator__department__name", - ) + filterArgs['operation_time__range'] = [startTime, endTime] + if not department_id: + filterArgs['operator__department__id__in'] = sub_departments else: - count = await QueryCodeLog.filter(operator_id=user_id, del_flag=1).count() - data = await QueryCodeLog.filter(operator_id=user_id, del_flag=1).order_by("-operation_time").values( - id="id", - query_count="query_count", - result_count="result_count", - cost_time="cost_time", - operation_time="operation_time", - status="status", - request_params="request_params", - response_result="response_result", - create_time="create_time", - update_time="update_time", - operator_id="operator__id", - operator_name="operator__username", - operator_nickname="operator__nickname", - department_id="operator__department__id", - department_name="operator__department__name", - ) + filterArgs['operator__department__id'] = department_id + count = await QueryCodeLog.filter(**filterArgs, operator__del_flag=1, del_flag=1).count() + data = await QueryCodeLog.filter(**filterArgs, operator__del_flag=1, del_flag=1).order_by("-operation_time").values( + id="id", + query_count="query_count", + result_count="result_count", + cost_time="cost_time", + operation_time="operation_time", + status="status", + request_params="request_params", + response_result="response_result", + create_time="create_time", + update_time="update_time", + operator_id="operator__id", + operator_name="operator__username", + operator_nickname="operator__nickname", + department_id="operator__department__id", + department_name="operator__department__name", + ) return Response.success(data={ "result": data, @@ -561,10 +564,13 @@ async def get_code_log_list(request: Request, @codeAPI.get("/logInfo/{id}", response_class=JSONResponse, response_model=GetQueryCodeLogDetailResponse, summary="查询编码日志详情") @Log(title="查询编码日志详情", business_type=BusinessType.SELECT) +@Auth(permission_list=["code:btn:logInfo"]) async def get_code_log_detail(request: Request, id: str = Path(..., description="日志ID"), + current_user: dict = Depends(LoginController.get_current_user), ): - if log := await QueryCodeLog.get_or_none(id=id): + sub_departments = current_user.get("sub_departments") + if log := await QueryCodeLog.get_or_none(id=id, operator__department__id__in=sub_departments, del_flag=1): data = await log.first().values( id="id", query_count="query_count", diff --git a/schemas/code.py b/schemas/code.py index ced0590..1ce7f00 100644 --- a/schemas/code.py +++ b/schemas/code.py @@ -6,12 +6,12 @@ # @Software : PyCharm # @Comment : 本程序 from datetime import datetime +from typing import List, Optional +from pydantic import BaseModel, ConfigDict, Field from pydantic.alias_generators import to_camel from schemas.common import BaseResponse, ListQueryResult -from pydantic import BaseModel, ConfigDict, Field -from typing import List, Optional class CodeInfo(BaseModel): @@ -42,17 +42,6 @@ class AddCodeParams(BaseModel): ) -class DeleteCodeListParams(BaseModel): - """ - 删除编码参数 - """ - ids: List[str] = Field(..., description="删除ID列表") - - model_config = ConfigDict( - alias_generator=to_camel - ) - - class GetCodeInfoResponse(BaseResponse): """ 获取编码信息响应