966 lines
46 KiB
Python
Raw Normal View History

2025-02-15 23:36:20 +08:00
# _*_ 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
2025-02-15 23:36:20 +08:00
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
2025-02-15 23:36:20 +08:00
from utils.log import logger
from utils.response import Response
codeAPI = APIRouter(
prefix="/code"
2025-02-15 23:36:20 +08:00
)
@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)):
2025-02-15 23:36:20 +08:00
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)):
2025-02-15 23:36:20 +08:00
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)):
2025-02-15 23:36:20 +08:00
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):
2025-02-15 23:36:20 +08:00
return Response.failure(msg="编码已存在")
else:
user_id = current_user.get("id")
code_import = await CodeImport.create(
2025-02-15 23:36:20 +08:00
code=params.code,
description=params.description,
status=3,
user_id=user_id
2025-02-15 23:36:20 +08:00
)
if code_import:
2025-02-15 23:36:20 +08:00
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"])
2025-02-15 23:36:20 +08:00
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):
2025-02-15 23:36:20 +08:00
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)
2025-02-15 23:36:20 +08:00
for index, row in df.iterrows():
row["code"] = row["code"].replace(".", "").replace("/", "").replace("_", "").replace("-",
"").replace(
2025-02-15 23:36:20 +08:00
"?",
"").replace(
":", "").replace("", "").replace("", "").strip()
await CodeImport.create(
2025-02-15 23:36:20 +08:00
code=row["code"],
description=row["description"],
status=3,
user_id=user_id
2025-02-15 23:36:20 +08:00
)
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)
2025-02-15 23:36:20 +08:00
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)):
2025-02-15 23:36:20 +08:00
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)
2025-02-15 23:36:20 +08:00
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"])
2025-02-15 23:36:20 +08:00
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):
2025-02-15 23:36:20 +08:00
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}})
2025-02-15 23:36:20 +08:00
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(
2025-02-15 23:36:20 +08:00
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",
2025-02-15 23:36:20 +08:00
):
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"])
2025-02-15 23:36:20 +08:00
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)):
2025-02-15 23:36:20 +08:00
filterArgs = {
f'{k}__contains': v for k, v in {
'user__username': username,
'user__nickname': nickname,
2025-02-15 23:36:20 +08:00
'code': code,
'description': description,
2025-02-15 23:36:20 +08:00
}.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(
2025-02-15 23:36:20 +08:00
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",
2025-02-15 23:36:20 +08:00
)
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"])
2025-02-15 23:36:20 +08:00
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": {
2025-02-17 19:38:34 +08:00
"description": {
2025-02-15 23:36:20 +08:00
"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)
2025-02-15 23:36:20 +08:00
# 归一化匹配度,转换为百分比
match_rate = round((hit["_score"] / max_score) * 100, 2) # 归一化后计算百分比
# 将匹配结果添加到列表中
matches.append({
"id": code.id if code else None,
2025-02-17 19:38:34 +08:00
"code": hit["_source"]["code"], # 获取商品编码
"description": hit["_source"]["description"], # 获取商品描述
2025-02-15 23:36:20 +08:00
"match_rate": match_rate # 匹配度(百分比)
})
query_code = await QueryCode.create(
query_text=description.strip(),
result_text=jsonable_encoder(matches),
2025-02-19 01:20:04 +08:00
session_id=log.id,
status=1 if matches else 0
2025-02-15 23:36:20 +08:00
)
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"])
2025-02-15 23:36:20 +08:00
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):
2025-02-15 23:36:20 +08:00
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": {
2025-02-17 19:38:34 +08:00
"description": {
2025-02-15 23:36:20 +08:00
"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)
2025-02-15 23:36:20 +08:00
# 归一化匹配度,转换为百分比
match_rate = round((hit["_score"] / max_score) * 100, 2) # 归一化后计算百分比
# 将匹配结果添加到列表中
matches.append({
"id": code.id if code else None,
2025-02-17 19:38:34 +08:00
"code": hit["_source"]["code"], # 获取商品编码
"description": hit["_source"]["description"], # 获取商品描述
2025-02-15 23:36:20 +08:00
"match_rate": match_rate # 匹配度(百分比)
})
query_code = await QueryCode.create(
query_text=row['text'].strip(),
result_text=jsonable_encoder(matches),
2025-02-19 01:20:04 +08:00
session_id=log.id,
status=1 if matches else 0
2025-02-15 23:36:20 +08:00
)
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"])
2025-02-15 23:36:20 +08:00
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="用户昵称"),
2025-02-15 23:36:20 +08:00
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
}
2025-02-15 23:36:20 +08:00
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
2025-02-15 23:36:20 +08:00
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",
)
2025-02-15 23:36:20 +08:00
return Response.success(data={
"page": page,
"pageSize": pageSize,
"result": data,
"total": count
})
2025-02-18 02:04:40 +08:00
@codeAPI.get("/logList/all", response_class=JSONResponse, response_model=GetCodeLogAllResponse,
summary="查询所有编码日志列表")
@Log(title="查询所有编码日志列表", business_type=BusinessType.EXPORT)
@Auth(permission_list=["code:btn:export"])
2025-02-18 02:04:40 +08:00
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="用户昵称"),
2025-02-18 02:04:40 +08:00
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
}
2025-02-18 02:04:40 +08:00
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
2025-02-18 02:04:40 +08:00
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",
)
2025-02-18 02:04:40 +08:00
return Response.success(data={
"result": data,
"total": count
})
2025-02-15 23:36:20 +08:00
@codeAPI.get("/logInfo/{id}", response_class=JSONResponse, response_model=GetQueryCodeLogDetailResponse,
summary="查询编码日志详情")
@Log(title="查询编码日志详情", business_type=BusinessType.SELECT)
@Auth(permission_list=["code:btn:logInfo"])
2025-02-15 23:36:20 +08:00
async def get_code_log_detail(request: Request,
id: str = Path(..., description="日志ID"),
current_user: dict = Depends(LoginController.get_current_user),
2025-02-15 23:36:20 +08:00
):
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):
2025-02-15 23:36:20 +08:00
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()