feat: 添加编码管理

This commit is contained in:
皓月归尘 2025-02-15 23:36:20 +08:00
parent e32bb8e740
commit 6122e390fb
10 changed files with 881 additions and 7 deletions

521
api/code.py Normal file
View File

@ -0,0 +1,521 @@
# _*_ 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.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.common import BaseResponse
from utils.log import logger
from utils.response import Response
codeAPI = APIRouter(
prefix="/code",
dependencies=[Depends(LoginController.get_current_user)]
)
@codeAPI.get("/template", summary="获取上传编码模板")
@Log(title="获取上传编码模板", business_type=BusinessType.SELECT)
async def get_upload_template(request: Request):
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)
async def get_query_template(request: Request):
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)
async def add_code(request: Request, params: AddCodeParams):
params.code = params.code.replace(".", "").replace("/", "").replace("_", "").replace("-", "").replace("?",
"").replace(
":", "").replace("", "").replace("", "").strip()
if await Code.get_or_none(code=params.code):
return Response.failure(msg="编码已存在")
else:
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)
code = await Code.create(
code=params.code,
description=params.description
)
if code:
# 构造 Bulk 导入数据
actions = [
{
"_index": ElasticSearchConfig.ES_INDEX,
"_id": code.code, # 以 code 作为 ID
"_source": {
"code": code.code,
"description": code.description
}
}
]
success, failed = await async_bulk(request.app.state.es, actions)
logger.info(f"成功导入 {success} 条数据,失败 {failed}")
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)
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):
uploader_id = await file.first().values(id="uploader__id")
if str(uploader_id["id"]) == user_id:
try:
df = pd.read_excel(file.absolute_path)
for index, row in df.iterrows():
row["code"] = str(row["code"]).replace(".", "").replace("/", "").replace("_", "").replace("-",
"").replace(
"?",
"").replace(
":", "").replace("", "").replace("", "").strip()
await Code.create(
code=row["code"],
description=row["description"]
)
if not await request.app.state.es.indices.exists(index=ElasticSearchConfig.ES_INDEX):
await request.app.state.es.indices.create(index=ElasticSearchConfig.ES_INDEX, ignore=400)
# 构造 Bulk 导入数据
actions = [
{
"_index": ElasticSearchConfig.ES_INDEX,
"_id": row["code"], # 以 code 作为 ID
"_source": {
"code": row["code"],
"description": row["description"]
}
}
for _, row in df.iterrows()
]
success, failed = await async_bulk(request.app.state.es, actions)
logger.info(f"成功导入 {success} 条数据,失败 {failed}")
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)
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()
await request.app.state.es.delete(index=ElasticSearchConfig.ES_INDEX, id=code.code)
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)
async def delete_code_by_ids(request: Request, params: DeleteCodeListParams):
for id in set(params.ids):
if code := await Code.get_or_none(id=id):
await code.delete()
await request.app.state.es.delete(index=ElasticSearchConfig.ES_INDEX, id=code.code)
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)
async def update_code(request: Request,
params: AddCodeParams,
id: str = Path(description="编码ID")):
if code := await Code.get_or_none(id=id):
code.code = params.code
code.description = params.description
await code.save()
await request.app.state.es.update(index=ElasticSearchConfig.ES_INDEX, id=code.code,
body={"doc": {"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)
async def get_code_info(request: Request, id: str = Path(description="编码ID")):
if code := await Code.get_or_none(id=id).values(
id="id",
code="code",
description="description",
create_time="create_time",
create_by="create_by",
update_time="update_time",
update_by="update_by"
):
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)
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="商品描述")):
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(
id="id",
code="code",
description="description",
create_time="create_time",
create_by="create_by",
update_time="update_time",
update_by="update_by"
)
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)
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": {
"brief_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(code=hit["_source"]["hts8"])
# 归一化匹配度,转换为百分比
match_rate = round((hit["_score"] / max_score) * 100, 2) # 归一化后计算百分比
# 将匹配结果添加到列表中
matches.append({
"id": code.id if code else None,
"code": hit["_source"]["hts8"], # 获取商品编码
"description": hit["_source"]["brief_description"], # 获取商品描述
"match_rate": match_rate # 匹配度(百分比)
})
query_code = await QueryCode.create(
query_text=description.strip(),
result_text=jsonable_encoder(matches),
session_id=log.id
)
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)
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):
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": {
"brief_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(code=hit["_source"]["hts8"])
# 归一化匹配度,转换为百分比
match_rate = round((hit["_score"] / max_score) * 100, 2) # 归一化后计算百分比
# 将匹配结果添加到列表中
matches.append({
"id": code.id if code else None,
"code": hit["_source"]["hts8"], # 获取商品编码
"description": hit["_source"]["brief_description"], # 获取商品描述
"match_rate": match_rate # 匹配度(百分比)
})
query_code = await QueryCode.create(
query_text=row['text'].strip(),
result_text=jsonable_encoder(matches),
session_id=log.id
)
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)
async def get_code_log_list(request: Request,
page: int = Query(default=1, description="当前页码"),
pageSize: int = Query(default=10, 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")
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",
)
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",
)
return Response.success(data={
"page": page,
"pageSize": pageSize,
"result": data,
"total": count
})
@codeAPI.get("/logInfo/{id}", response_class=JSONResponse, response_model=GetQueryCodeLogDetailResponse,
summary="查询编码日志详情")
@Log(title="查询编码日志详情", business_type=BusinessType.SELECT)
async def get_code_log_detail(request: Request,
id: str = Path(..., description="日志ID"),
):
if log := await QueryCodeLog.get_or_none(id=id):
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="日志不存在!")

View File

@ -59,7 +59,7 @@ async def upload_file(
file_type=file.content_type,
absolute_path=absolute_path,
relative_path=relative_path,
uploader=current_user.get("id"),
uploader_id=current_user.get("id"),
)
result = await file_record.first().values(
id="id",

2
app.py
View File

@ -23,6 +23,7 @@ from api.permission import permissionAPI
from api.role import roleAPI
from api.server import serverAPI
from api.user import userAPI
from api.code import codeAPI
from config.database import init_db, close_db
from config.env import AppConfig
from config.get_ElasticSearch import ElasticSearch
@ -91,6 +92,7 @@ api_list = [
{'api': serverAPI, 'tags': ['服务器管理']},
{'api': i18nAPI, 'tags': ['国际化管理']},
{'api': configApi, 'tags': ['配置管理']},
{'api': codeAPI, 'tags': ['编码管理']},
]
for api in api_list:

View File

@ -188,15 +188,27 @@ class LoginController:
child_node = await cls.find_node_recursive(child_item["id"], data)
if child_node:
children.append(child_node)
result = {
"name": item["name"],
"path": item["path"],
"meta": {
meta = {
k: v for k, v in {
"title": item["title"],
"rank": item["rank"],
"icon": item["icon"],
"extraIcon": item["extraIcon"],
"showParent": item["showParent"],
"keepAlive": item["keepAlive"],
"frameSrc": item["frameSrc"],
"frameLoading": item["frameLoading"],
"permissions": [item["auths"]],
},
}.items() if v
}
if item["showLink"]:
meta["showLink"] = True
else:
meta["showLink"] = False
result = {
"name": item["name"],
"path": item["path"],
"meta": meta,
"children": children
}
if item["component"]:

View File

@ -123,6 +123,9 @@ class QueryController:
leaveTransition="permission__leave_transition",
activePath="permission__active_path",
auths="permission__auths",
frameSrc="permission__frame_src",
frameLoading="permission__frame_loading",
fixedTag="permission__fixed_tag",
keepAlive="permission__keep_alive",
hiddenTag="permission__hidden_tag",
showLink="permission__show_link",

View File

@ -6,6 +6,7 @@
# @Software : PyCharm
# @Comment : 本程序
from models.code import Code, QueryCode, QueryCodeLog
from models.config import Config
from models.department import Department, DepartmentRole
from models.file import File
@ -28,5 +29,8 @@ __all__ = [
'UserRole',
'I18n',
'Locale',
'Config'
'Config',
'Code',
'QueryCode',
'QueryCodeLog'
]

157
models/code.py Normal file
View File

@ -0,0 +1,157 @@
# _*_ coding : UTF-8 _*_
# @Time : 2025/02/13 21:23
# @UpdateTime : 2025/02/13 21:23
# @Author : sonder
# @File : code.py
# @Software : PyCharm
# @Comment : 本程序
from tortoise import fields
from models.common import BaseModel
class Code(BaseModel):
"""
编码模型
"""
code = fields.CharField(
max_length=255,
description="编码",
source_field="code"
)
description = fields.TextField(
description="描述",
source_field="description"
)
class Meta:
table = "code"
table_description = "编码表"
class QueryCodeLog(BaseModel):
"""
查询编码日志模型
"""
request_params = fields.TextField(
null=True,
description="请求参数",
source_field="request_params" # 映射到数据库字段 request_params
)
"""
请求参数
- 记录用户请求的参数任意格式如字符串JSONXML
- 允许为空
- 映射到数据库字段 request_params
"""
response_result = fields.TextField(
null=True,
description="返回结果",
source_field="response_result" # 映射到数据库字段 response_result
)
"""
返回结果
- 记录操作的返回结果任意格式如字符串JSONXML
- 允许为空
- 映射到数据库字段 response_result
"""
status = fields.SmallIntField(
default=1,
description="操作状态1成功0失败",
source_field="status" # 映射到数据库字段 status
)
"""
操作状态
- 1成功
- 0失败
- 默认为 1
- 映射到数据库字段 status
"""
operation_time = fields.DatetimeField(
auto_now_add=True,
description="操作时间",
source_field="operation_time" # 映射到数据库字段 operation_time
)
"""
操作时间
- 自动设置为当前时间
- 映射到数据库字段 operation_time
"""
cost_time = fields.FloatField(
default=0,
description="消耗时间(毫秒)",
source_field="cost_time" # 映射到数据库字段 cost_time
)
"""
消耗时间
- 记录操作消耗的时间单位毫秒
- 默认为 0
- 映射到数据库字段 cost_time
"""
query_count = fields.IntField(
default=0,
description="查询统计",
source_field="query_count" # 映射到数据库字段 query_count
)
"""
查询统计
- 记录查询文本的数量
- 默认为 0
- 映射到数据库字段 query_count
"""
result_count = fields.IntField(
default=0,
description="结果统计",
source_field="result_count" # 映射到数据库字段 result_count
)
"""
结果统计
- 记录查询结果的数量
- 默认为 0
- 映射到数据库字段 result_count
"""
operator = fields.ForeignKeyField(
"models.User",
related_name="query_code_logs",
description="操作人员",
source_field="operator_id" # 映射到数据库字段 operator_id
)
"""
操作人员
- 外键关联到 User
- 允许为空
- 映射到数据库字段 operator_id
"""
class Meta:
table = "query_code_log"
table_description = "查询编码日志表"
class QueryCode(BaseModel):
"""
查询编码模型
"""
session = fields.ForeignKeyField(
"models.QueryCodeLog",
related_name="query_code",
description="会话ID",
source_field="session_id"
)
query_text = fields.TextField(
description="查询文本",
source_field="query_text" # 映射到数据库字段 query_text
)
result_text = fields.TextField(
description="结果文本",
source_field="result_text" # 映射到数据库字段 result_text
)
class Meta:
table = "query_code"
table_description = "查询编码表"

Binary file not shown.

174
schemas/code.py Normal file
View File

@ -0,0 +1,174 @@
# _*_ coding : UTF-8 _*_
# @Time : 2025/02/13 22:07
# @UpdateTime : 2025/02/13 22:07
# @Author : sonder
# @File : code.py
# @Software : PyCharm
# @Comment : 本程序
from datetime import datetime
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):
"""
编码信息模型
"""
model_config = ConfigDict(
alias_generator=to_camel
)
id: str = Field(..., description="主键")
create_by: str = Field(default="", description="创建者")
create_time: Optional[datetime] = Field(default=None, description="创建时间")
update_by: str = Field(default="", description="更新者")
update_time: Optional[datetime] = Field(default=None, description="更新时间")
code: str = Field(..., description="编码")
description: str = Field(..., description="描述")
class AddCodeParams(BaseModel):
"""
更新编码参数
"""
code: str = Field(..., description="编码")
description: str = Field(..., description="描述")
model_config = ConfigDict(
alias_generator=to_camel
)
class DeleteCodeListParams(BaseModel):
"""
删除编码参数
"""
ids: List[str] = Field(..., description="删除ID列表")
model_config = ConfigDict(
alias_generator=to_camel
)
class GetCodeInfoResponse(BaseResponse):
"""
获取编码信息响应
"""
data: CodeInfo = Field(..., description="编码信息")
class GetCodeListResult(ListQueryResult):
"""
获取编码列表结果
"""
result: List[CodeInfo] = Field(..., description="编码列表")
class GetCodeListResponse(BaseResponse):
"""
获取编码列表响应
"""
data: GetCodeListResult = Field(..., description="编码列表")
class GetQueryCodeParams(BaseModel):
"""
获取查询编码结果
"""
query_text: str = Field(..., description="查询文本")
class QueryResultItem(BaseModel):
"""
查询结果项
"""
model_config = ConfigDict(
alias_generator=to_camel
)
id: str = Field(..., description="主键")
code: str = Field(..., description="编码")
description: str = Field(..., description="描述")
match_rate: float = Field(..., description="匹配度")
class QueryResult(BaseModel):
"""
查询结果
"""
model_config = ConfigDict(
alias_generator=to_camel
)
id: str = Field(..., description="主键")
query_text: str = Field(..., description="查询文本")
status: int = Field(..., description="查询状态")
result: List[QueryResultItem] = Field(..., description="查询结果")
class QueryCodeResult(BaseModel):
"""
查询编码结果
"""
model_config = ConfigDict(
alias_generator=to_camel
)
id: str = Field(..., description="查询ID")
query: str = Field(..., description="查询文本")
query_count: int = Field(..., description="查询统计")
cost_time: float = Field(..., description="消耗时间(毫秒)")
result_count: int = Field(..., description="结果统计")
response_result: List[QueryResult] = Field(..., description="查询结果")
status: int = Field(..., description="查询状态")
operator_time: str = Field(default="", description="操作时间")
class QueryCodeResponse(BaseResponse):
"""
查询编码响应
"""
data: QueryCodeResult = Field(..., description="查询编码结果")
class QueryCodeLogInfo(BaseModel):
"""
查询编码日志信息
"""
model_config = ConfigDict(
alias_generator=to_camel
)
id: str = Field(default="", description="主键")
query_count: int = Field(default=0, description="查询统计")
result_count: int = Field(default=0, description="结果统计")
cost_time: float = Field(default=0.0, description="消耗时间(毫秒)")
operator_time: str = Field(default="", description="操作时间")
request_params: str = Field(default="", description="请求参数")
response_result: str = Field(default="", description="响应结果")
status: int = Field(default=0, description="查询状态")
operator_id: str = Field(default="", description="操作人员ID")
operator_name: str = Field(default="", description="操作人员名称")
operator_nickname: str = Field(default="", description="操作人员昵称")
department_id: str = Field(default="", description="操作人员部门ID")
department_name: str = Field(default="", description="操作人员部门名称")
class QueryCodeLogResult(ListQueryResult):
"""
查询编码日志结果
"""
result: List[QueryCodeLogInfo] = Field(..., description="查询编码日志列表")
class GetQueryCodeLogResponse(BaseResponse):
"""
查询编码日志响应
"""
data: QueryCodeLogResult = Field(..., description="查询编码日志结果")
class GetQueryCodeLogDetailResponse(BaseResponse):
"""
查询编码日志详情响应
"""
data: QueryCodeLogInfo = Field(..., description="查询编码日志详情")

View File

@ -28,6 +28,7 @@ class ListQueryResult(BaseModel):
result: List = Field(default=[], description="列表数据")
total: int = Field(default=0, description="总条数")
page: int = Field(default=1, description="当前页码")
pageSize: int = Field(default=10, description="每页数量")
class DeleteListParams(BaseModel):