# _*_ coding : UTF-8 _*_ # @Time : 2025/02/13 19:20 # @UpdateTime : 2025/02/13 19:20 # @Author : sonder # @File : code.py # @Software : PyCharm # @Comment : 本程序 import os import time from datetime import datetime from typing import Optional import pandas as pd from elasticsearch.helpers import async_bulk 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, hasAuth 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, CodeFeedback, CodeImport from schemas.code import GetCodeInfoResponse, GetCodeListResponse, GetQueryCodeParams, QueryCodeResponse, AddCodeParams, \ GetQueryCodeLogResponse, GetQueryCodeLogDetailResponse, \ GetCodeLogAllResponse, AddCodeFeedbackParams, GetCodeFeedbackResponse, GetCodeFeedbackListResponse, \ UpdateCodeFeedbackStatusParams, GetCodeImportListResponse, UpdateCodeImportStatusParams from schemas.common import BaseResponse, DeleteListParams from utils.log import logger from utils.response import Response codeAPI = APIRouter( prefix="/code" ) @codeAPI.get("/template", summary="获取上传编码模板") @Log(title="获取上传编码模板", business_type=BusinessType.SELECT) @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="文件不存在!") return FileResponse( path=template_path, filename="上传模版.xlsx", media_type="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" ) @codeAPI.get("/queryTemplate", summary="获取查询编码模板") @Log(title="获取查询编码模板", business_type=BusinessType.SELECT) @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="文件不存在!") return FileResponse( path=template_path, filename="查询模版.xlsx", media_type="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" ) @codeAPI.post("/add", response_class=JSONResponse, response_model=BaseResponse, summary="添加编码") @Log(title="添加编码", business_type=BusinessType.INSERT) @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 CodeImport.get_or_none(code=params.code, del_flag=1): return Response.failure(msg="编码已存在") else: user_id = current_user.get("id") code_import = await CodeImport.create( code=params.code, description=params.description, status=3, user_id=user_id ) if code_import: return Response.success(msg="添加成功") else: return Response.failure(msg="添加失败") @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, 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(): row["code"] = row["code"].replace(".", "").replace("/", "").replace("_", "").replace("-", "").replace( "?", "").replace( ":", "").replace(":", "").replace("?", "").strip() await CodeImport.create( code=row["code"], description=row["description"], status=3, user_id=user_id ) except ServiceException as e: logger.error(e.message) raise ServiceException(message="文件读取失败") return Response.success(msg="添加成功") else: raise PermissionException(message="权限不足") else: return Response.failure(msg="文件不存在") @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) @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.id) return Response.success(msg="删除成功") else: return Response.failure(msg="编码不存在") @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) @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, del_flag=1): code.del_flag = 0 await code.save() await request.app.state.es.delete(index=ElasticSearchConfig.ES_INDEX, id=code.id) return Response.success(msg="删除成功") @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"), 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() await request.app.state.es.update(index=ElasticSearchConfig.ES_INDEX, id=code.id, body={"doc": {"id": code.id, "code": code.code, "description": params.description}}) return Response.success(msg="更新成功") return Response.failure(msg="编码不存在") @codeAPI.get("/info/{id}", response_class=JSONResponse, response_model=GetCodeInfoResponse, summary="获取编码信息") @Log(title="获取编码信息", business_type=BusinessType.SELECT) @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", create_time="create_time", create_by="create_by", update_time="update_time", update_by="update_by", user_id="user__id", username="user__username", nickname="user__nickname", department_id="user__department__id", department_name="user__department__name", ): return Response.success(data=code) return Response.failure(msg="编码不存在") @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="商品描述"), 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=Depends(LoginController.get_current_user)): filterArgs = { f'{k}__contains': v for k, v in { 'user__username': username, 'user__nickname': nickname, 'code': code, 'description': description, }.items() if v } if startTime and endTime: startTime = float(startTime) / 1000 endTime = float(endTime) / 1000 startTime = datetime.fromtimestamp(startTime) endTime = datetime.fromtimestamp(endTime) filterArgs['create_time__range'] = [startTime, endTime] if department_id: filterArgs['user__department__id'] = department_id 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", create_time="create_time", create_by="create_by", update_time="update_time", update_by="update_by", user_id="user__id", username="user__username", nickname="user__nickname", department_id="user__department__id", department_name="user__department__name", ) return Response.success(data={ "page": page, "pageSize": pageSize, "total": total, "result": data }) @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), ): start_time = time.time() user_id = current_user.get("id") if log := await QueryCodeLog.create( operator_id=user_id, query_count=0, result_count=0, cost_time=0, request_params=params.query_text, response_result={}, status=0, del_flag=0 ): description_list = set(params.query_text.split("\n")) query_count = 0 dataList = [] try: for description in description_list: if not description: continue query_count += 1 query = { "query": { "match": { "description": { "query": description.strip(), "fuzziness": "AUTO" # 自动模糊匹配 } } }, "sort": [ { "_score": { # 按照匹配度排序 "order": "desc" # 降序 } } ] } matches = [] data = await request.app.state.es.search(index=ElasticSearchConfig.ES_INDEX, body=query, size=5) # 获取当前查询的最大 _score max_score = data["hits"].get("max_score", 1) # 处理每一条匹配结果 for hit in data["hits"]["hits"]: code = await Code.get_or_none(id=hit["_source"]["id"], del_flag=1) # 归一化匹配度,转换为百分比 match_rate = round((hit["_score"] / max_score) * 100, 2) # 归一化后计算百分比 # 将匹配结果添加到列表中 matches.append({ "id": code.id if code else None, "code": hit["_source"]["code"], # 获取商品编码 "description": hit["_source"]["description"], # 获取商品描述 "match_rate": match_rate # 匹配度(百分比) }) query_code = await QueryCode.create( query_text=description.strip(), result_text=jsonable_encoder(matches), session_id=log.id, status=1 if matches else 0 ) dataList.append({ "id": query_code.id, "query_text": description.strip(), "result_text": jsonable_encoder(matches), "status": 1 if matches else 0, }) cost_time = float(time.time() - start_time) * 100 log.operator_id = user_id log.query_count = query_count log.result_count = len(dataList) log.cost_time = cost_time log.status = 1 if dataList else 0 log.response_result = jsonable_encoder(dataList) log.del_flag = 1 await log.save() return Response.success(data={ "id": log.id, "result_count": len(dataList), "query": params.query_text, "response_result": jsonable_encoder(dataList), "query_count": query_count, "cost_time": cost_time, "status": 1 if dataList else 0, "operation_time": log.operation_time }) except ServiceException as e: logger.error(e.message) await log.delete() raise ServiceException(message="查询失败!") return Response.failure(msg="查询失败!") @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, del_flag=1): uploader_id = await file.first().values(id="uploader__id") if str(uploader_id["id"]) == user_id: if log := await QueryCodeLog.create( operator_id=user_id, query_count=0, result_count=0, cost_time=0, request_params="", response_result={}, status=0, del_flag=0 ): try: query_text = "" query_count = 0 dataList = [] df = pd.read_excel(file.absolute_path) for index, row in df.iterrows(): query_count += 1 query_text += row["text"] + "\n" query = { "query": { "match": { "description": { "query": row["text"].strip(), "fuzziness": "AUTO" # 自动模糊匹配 } } }, "sort": [ { "_score": { # 按照匹配度排序 "order": "desc" # 降序 } } ] } matches = [] data = await request.app.state.es.search(index=ElasticSearchConfig.ES_INDEX, body=query, size=5) # 获取当前查询的最大 _score max_score = data["hits"].get("max_score", 1) # 处理每一条匹配结果 for hit in data["hits"]["hits"]: code = await Code.get_or_none(id=hit["_source"]["id"], del_flag=1) # 归一化匹配度,转换为百分比 match_rate = round((hit["_score"] / max_score) * 100, 2) # 归一化后计算百分比 # 将匹配结果添加到列表中 matches.append({ "id": code.id if code else None, "code": hit["_source"]["code"], # 获取商品编码 "description": hit["_source"]["description"], # 获取商品描述 "match_rate": match_rate # 匹配度(百分比) }) query_code = await QueryCode.create( query_text=row['text'].strip(), result_text=jsonable_encoder(matches), session_id=log.id, status=1 if matches else 0 ) dataList.append({ "id": query_code.id, "query_text": row['text'].strip(), "result_text": jsonable_encoder(matches), "status": 1 if matches else 0, }) cost_time = float(time.time() - start_time) * 100 log.request_params = query_text log.operator_id = user_id log.query_count = query_count log.result_count = len(dataList) log.cost_time = cost_time log.status = 1 if dataList else 0 log.response_result = jsonable_encoder(dataList) log.del_flag = 1 await log.save() return Response.success(data={ "id": log.id, "result_count": len(dataList), "query": query_text, "response_result": jsonable_encoder(dataList), "query_count": query_count, "cost_time": cost_time, "status": 1 if dataList else 0, "operation_time": log.operation_time }) except ServiceException as e: logger.error(e.message) await log.delete() raise ServiceException(message="查询失败!") else: raise PermissionException(message="权限不足") else: return Response.failure(msg="文件不存在") @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), ): 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) filterArgs['operation_time__range'] = [startTime, endTime] if await hasAuth(request, "code:btn:logAdmin"): if department_id: filterArgs['operator__department__id'] = department_id else: filterArgs['operator__department__id__in'] = sub_departments else: if department_id: 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, "result": data, "total": count }) @codeAPI.get("/logList/all", response_class=JSONResponse, response_model=GetCodeLogAllResponse, summary="查询所有编码日志列表") @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), ): 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) filterArgs['operation_time__range'] = [startTime, endTime] if await hasAuth(request, "code:btn:logAdmin"): if department_id: filterArgs['operator__department__id'] = department_id else: filterArgs['operator__department__id__in'] = sub_departments else: if department_id: 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, "total": count }) @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), ): 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", 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=data) return Response.failure(msg="日志不存在!") @codeAPI.delete("/deleteFeedback/{id}", response_class=JSONResponse, response_model=BaseResponse, summary="删除编码反馈") @codeAPI.post("/deleteFeedback/{id}", response_class=JSONResponse, response_model=BaseResponse, summary="删除编码反馈") @Log(title="删除编码反馈", business_type=BusinessType.DELETE) @Auth(permission_list=["code:btn:deleteFeedback"]) async def delete_feedback(request: Request, id: str = Path(..., description="编码反馈ID"), current_user: dict = Depends(LoginController.get_current_user), ): sub_departments = current_user.get("sub_departments") if feedback := await CodeFeedback.get_or_none(id=id, user__department__id__in=sub_departments, del_flag=1): feedback.del_flag = 0 await feedback.save() return Response.success(msg="删除成功!") return Response.failure(msg="删除失败!") @codeAPI.post("/addFeedback", response_class=JSONResponse, response_model=BaseResponse, summary="添加编码反馈") @Log(title="添加编码反馈", business_type=BusinessType.INSERT) @Auth(permission_list=["code:btn:addFeedback"]) async def add_feedback(request: Request, params: AddCodeFeedbackParams, current_user: dict = Depends(LoginController.get_current_user), ): user_id = current_user.get("id") if code := await Code.get_or_none(id=params.code_id, del_flag=1): feedback = await CodeFeedback.create( code_id=code.id, feedback_code=params.feedback_code, feedback_description=params.feedback_description, user_id=str(user_id), ) if feedback: return Response.success(msg="添加成功!") return Response.failure(msg="添加失败!") return Response.failure(msg="编码不存在!") @codeAPI.delete("/deleteFeedbackList", response_class=JSONResponse, response_model=BaseResponse, summary="批量删除编码反馈") @codeAPI.post("/deleteFeedbackList", response_class=JSONResponse, response_model=BaseResponse, summary="批量删除编码反馈") @Log(title="批量删除编码反馈", business_type=BusinessType.DELETE) @Auth(permission_list=["code:btn:deleteFeedback"]) async def delete_feedback_list(request: Request, params: DeleteListParams, current_user: dict = Depends(LoginController.get_current_user), ): sub_departments = current_user.get("sub_departments") for id in set(params.ids): if feedback := await CodeFeedback.get_or_none(id=id, user__department__id__in=sub_departments, del_flag=1): feedback.del_flag = 0 await feedback.save() return Response.success(msg="删除成功!") @codeAPI.put("/updateFeedback/{id}", response_class=JSONResponse, response_model=BaseResponse, summary="修改编码反馈") @codeAPI.post("/updateFeedback/{id}", response_class=JSONResponse, response_model=BaseResponse, summary="修改编码反馈") @Log(title="修改编码反馈", business_type=BusinessType.UPDATE) @Auth(permission_list=["code:btn:updateFeedback"]) async def update_feedback(request: Request, params: AddCodeFeedbackParams, id: str = Path(..., description="编码反馈ID"), current_user: dict = Depends(LoginController.get_current_user), ): sub_departments = current_user.get("sub_departments") if feedback := await CodeFeedback.get_or_none(id=id, user__department__id__in=sub_departments, del_flag=1): code = await Code.get_or_none(id=params.code_id, del_flag=1) if code: feedback.code = code else: return Response.failure(msg="编码不存在!") feedback.feedback_description = params.feedback_description feedback.feedback_code = params.feedback_code await feedback.save() return Response.success(msg="修改成功!") return Response.failure(msg="编码反馈不存在!") @codeAPI.get("/feedbackInfo/{id}", response_class=JSONResponse, response_model=GetCodeFeedbackResponse, summary="编码反馈详情") @Log(title="编码反馈详情", business_type=BusinessType.SELECT) @Auth(permission_list=["code:btn:feedbackInfo"]) async def feedback_info(request: Request, id: str = Path(..., description="编码反馈ID"), current_user: dict = Depends(LoginController.get_current_user), ): sub_departments = current_user.get("sub_departments") if feedback := await CodeFeedback.get_or_none(id=id, user__department__id__in=sub_departments, del_flag=1): data = await feedback.first().values( id="id", code_id="code__id", code="code__code", description="code__description", feedback_code="feedback_code", feedback_description="feedback_description", create_time="create_time", update_time="update_time", user_id="user__id", username="user__username", nickname="user__nickname", department_id="user__department__id", department_name="user__department__name", ) return Response.success(data=data) return Response.failure(msg="编码反馈不存在!") @codeAPI.get("/feedbackList", response_class=JSONResponse, response_model=GetCodeFeedbackListResponse, summary="编码反馈列表") @Log(title="编码反馈列表", business_type=BusinessType.SELECT) @Auth(permission_list=["code:btn:feedbackList"]) async def feedback_list(request: Request, page: int = Query(default=1, description="当前页码"), pageSize: int = Query(default=10, description="每页数量"), code: Optional[str] = Query(default=None, description="编码"), feedback_code: Optional[str] = Query(default=None, description="反馈编码"), feedback_description: Optional[str] = Query(default=None, description="反馈文本"), username: Optional[str] = Query(default=None, description="用户名"), status: Optional[str] = Query(default=None, description="状态"), nickname: Optional[str] = Query(default=None, description="用户昵称"), department_id: Optional[str] = Query(default=None, description="部门ID"), startTime: Optional[str] = Query(default=None, description="开始时间"), endTime: Optional[str] = Query(default=None, description="结束时间"), current_user: dict = Depends(LoginController.get_current_user), ): sub_departments = current_user.get("sub_departments") filterArgs = { f'{k}__contains': v for k, v in { 'user__username': username, 'user__nickname': nickname, 'code__code': code, 'feedback_code': feedback_code, 'feedback_description': feedback_description, }.items() if v } if startTime and endTime: startTime = float(startTime) / 1000 endTime = float(endTime) / 1000 startTime = datetime.fromtimestamp(startTime) endTime = datetime.fromtimestamp(endTime) filterArgs['create_time__range'] = [startTime, endTime] if await hasAuth(request, "code:btn:feedbackAdmin"): if department_id: filterArgs['user__department__id'] = department_id else: filterArgs['user__department__id__in'] = sub_departments else: if department_id: filterArgs['user__department__id'] = department_id if status is not None: filterArgs['status'] = int(status) total = await CodeFeedback.filter(**filterArgs, del_flag=1).count() data = await CodeFeedback.filter(**filterArgs, del_flag=1).order_by('-create_time').offset( (page - 1) * pageSize).limit(pageSize).values( id="id", code_id="code__id", code="code__code", description="code__description", feedback_code="feedback_code", feedback_description="feedback_description", create_time="create_time", update_time="update_time", user_id="user__id", username="user__username", nickname="user__nickname", department_id="user__department__id", department_name="user__department__name", status="status", ) return Response.success(data={ "page": page, "pageSize": pageSize, "result": data, "total": total, }) @codeAPI.put("/feedbackAudit", response_class=JSONResponse, response_model=BaseResponse, summary="编码反馈审核") @codeAPI.post("/feedbackAudit", response_class=JSONResponse, response_model=BaseResponse, summary="编码反馈审核") @Log(title="编码反馈审核", business_type=BusinessType.UPDATE) @Auth(permission_list=["code:btn:feedbackAudit"]) async def feedback_audit(request: Request, params: UpdateCodeFeedbackStatusParams, current_user: dict = Depends(LoginController.get_current_user), ): sub_departments = current_user.get("sub_departments") for id in set(params.ids): if feedback := await CodeFeedback.get_or_none(id=id, user__department__id__in=sub_departments, del_flag=1): feedback.status = params.status if params.status == 1: await Code.filter(id=feedback.code_id, del_flag=1).update(code=feedback.feedback_code, description=feedback.feedback_description) await request.app.state.es.update(index=ElasticSearchConfig.ES_INDEX, id=feedback.code_id, body={"doc": {"id": feedback.code_id, "code": feedback.feedback_code, "description": feedback.feedback_description}}) await feedback.save() return Response.failure(msg="编码反馈不存在!") @codeAPI.delete("/deleteCodeImport/{id}", response_class=JSONResponse, response_model=BaseResponse, summary="删除编码导入") @codeAPI.post("/deleteCodeImport/{id}", response_class=JSONResponse, response_model=BaseResponse, summary="删除编码导入") @Log(title="删除编码导入", business_type=BusinessType.DELETE) @Auth(permission_list=["code:btn:deleteCodeImport"]) async def delete_code_import(request: Request, id: str = Path(description="编码导入ID"), current_user: dict = Depends(LoginController.get_current_user)): sub_departments = current_user.get("sub_departments") if code_import := await CodeImport.get_or_none(id=id, user__department__id__in=sub_departments, del_flag=1): code_import.del_flag = 0 await code_import.save() return Response.success() return Response.failure(msg="编码导入不存在!") @codeAPI.delete("/deleteCodeImportList", response_class=JSONResponse, response_model=BaseResponse, summary="批量删除编码导入") @codeAPI.post("/deleteCodeImportList", response_class=JSONResponse, response_model=BaseResponse, summary="批量删除编码导入") @Log(title="批量删除编码导入", business_type=BusinessType.DELETE) @Auth(permission_list=["code:btn:deleteCodeImport"]) async def delete_code_import_list(request: Request, params: DeleteListParams, current_user: dict = Depends(LoginController.get_current_user)): sub_departments = current_user.get("sub_departments") for id in set(params.ids): if code_import := await CodeImport.get_or_none(id=id, user__department__id__in=sub_departments, del_flag=1): code_import.del_flag = 0 await code_import.save() return Response.success() @codeAPI.put("/updateCodeImport/{id}", response_class=JSONResponse, response_model=BaseResponse, summary="修改编码导入") @codeAPI.post("/updateCodeImport/{id}", response_class=JSONResponse, response_model=BaseResponse, summary="修改编码导入") @Log(title="修改编码导入", business_type=BusinessType.UPDATE) @Auth(permission_list=["code:btn:updateCodeImport"]) async def update_code_import(request: Request, params: AddCodeParams, id: str = Path(description="编码导入ID"), current_user: dict = Depends(LoginController.get_current_user)): sub_departments = current_user.get("sub_departments") if code_import := await CodeImport.get_or_none(id=id, user__department__id__in=sub_departments, del_flag=1): code_import.code = params.code code_import.description = params.description code_import.status = 3 await code_import.save() return Response.success() return Response.failure(msg="编码导入不存在!") @codeAPI.get("/codeImportList", response_class=JSONResponse, response_model=GetCodeImportListResponse, summary="查询编码导入列表") @Auth(permission_list=["code:btn:codeImportList"]) async def get_code_import_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="商品描述"), username: Optional[str] = Query(default=None, description="用户名"), status: Optional[str] = Query(default=None, description="状态"), nickname: Optional[str] = Query(default=None, description="用户昵称"), department_id: Optional[str] = Query(default=None, description="部门ID"), startTime: Optional[str] = Query(default=None, description="开始时间"), endTime: Optional[str] = Query(default=None, description="结束时间"), current_user: dict = Depends(LoginController.get_current_user), ): sub_departments = current_user.get("sub_departments") filterArgs = { f'{k}__contains': v for k, v in { 'user__username': username, 'user__nickname': nickname, 'code': code, 'description': description, }.items() if v } if startTime and endTime: startTime = float(startTime) / 1000 endTime = float(endTime) / 1000 startTime = datetime.fromtimestamp(startTime) endTime = datetime.fromtimestamp(endTime) filterArgs['create_time__range'] = [startTime, endTime] if await hasAuth(request, "code:btn:codeImportAdmin"): if department_id: filterArgs['user__department__id'] = department_id else: filterArgs['user__department__id__in'] = sub_departments else: if department_id: filterArgs['user__department__id'] = department_id if status is not None: filterArgs['status'] = int(status) total = await CodeImport.filter(**filterArgs, del_flag=1).count() data = await CodeImport.filter(**filterArgs, del_flag=1).order_by('-create_time').offset( (page - 1) * pageSize).limit(pageSize).values( id="id", code="code", description="description", create_time="create_time", update_time="update_time", user_id="user__id", username="user__username", nickname="user__nickname", department_id="user__department__id", department_name="user__department__name", status="status", ) return Response.success(data={ "page": page, "pageSize": pageSize, "result": data, "total": total, }) @codeAPI.put("/codeImportAudit", response_class=JSONResponse, response_model=BaseResponse, summary="编码导入审核") @codeAPI.post("/codeImportAudit", response_class=JSONResponse, response_model=BaseResponse, summary="编码导入审核") @Log(title="编码导入审核", business_type=BusinessType.INSERT) @Auth(permission_list=["code:btn:codeImportAudit"]) async def code_import_audit(request: Request, params: UpdateCodeImportStatusParams, current_user: dict = Depends(LoginController.get_current_user)): sub_departments = current_user.get("sub_departments") actions = [] for id in set(params.ids): if codeImport := await CodeImport.get_or_none(id=id, user__department__id__in=sub_departments, del_flag=1): codeImport.status = params.status if params.status == 1: codeImport.status = 1 code = codeImport.code.replace(".", "").replace("/", "").replace("_", "").replace("-", "").replace( "?", "").replace( ":", "").replace(":", "").replace("?", "").strip() user_id = current_user.get("id") codeInfo = await Code.create( code=code, description=codeImport.description, user_id=user_id, ) if codeInfo: # 构造 Bulk 导入数据 actions.append( { "_index": ElasticSearchConfig.ES_INDEX, "_id": codeInfo.id, # 以 code 作为 ID "_source": { "id": codeInfo.id, "code": codeInfo.code, "description": codeInfo.description } } ) await codeImport.save() if await request.app.state.es.indices.exists(index=ElasticSearchConfig.ES_INDEX): await request.app.state.es.indices.create(index=ElasticSearchConfig.ES_INDEX, ignore=400) success, failed = await async_bulk(request.app.state.es, actions) logger.info(f"成功导入 {success} 条数据,失败 {failed} 条") return Response.success()