feat: 优化代码生成器功能并修复多个问题

- 前端表格列添加溢出提示工具
- 后端登录IP归属地查询与设置统一处理
- 分页服务明确仅用于非SQL数据源场景
- 代码生成器添加字段筛选和帮助面板
- 修复菜单高亮和布局切换问题
- 更新文档中的BUG状态和解决方案
- 优化AI聊天界面样式和交互
- 添加数据库分页支持到多个模块
- 代码生成器表单校验和流程优化
- 修复PostgreSQL日期类型问题
This commit is contained in:
zhangtao
2026-03-30 00:37:16 +08:00
parent c5ec09f06f
commit 837d8a5aa7
56 changed files with 1931 additions and 663 deletions
@@ -145,14 +145,7 @@ class LoginService:
# 若没有 X-Forwarded-For 头,则使用 request.client.host
request_ip = request.client.host if request.client else "127.0.0.1"
if settings.LOGIN_RESOLVE_IP_LOCATION:
login_location = await IpLocalUtil.get_ip_location(request_ip)
else:
login_location = (
"内网IP"
if IpLocalUtil.is_private_ip(request_ip)
else "未解析(已关闭归属地查询)"
)
login_location = await IpLocalUtil.resolve_location_for_log(request_ip)
request.scope["login_location"] = login_location
# 确保在请求上下文中设置用户名和会话ID
@@ -5,7 +5,6 @@ from fastapi.responses import JSONResponse, StreamingResponse
from redis.asyncio.client import Redis
from app.api.v1.module_system.auth.schema import AuthSchema
from app.common.request import PaginationService
from app.common.response import ResponseSchema, StreamResponse, SuccessResponse
from app.core.base_params import PaginationQueryParam
from app.core.base_schema import BatchSetAvailable
@@ -82,13 +81,12 @@ async def get_type_list_controller(
异常:
- CustomException: 查询字典类型失败时抛出异常。
"""
result_dict_list = await DictTypeService.get_obj_list_service(
auth=auth, search=search, order_by=page.order_by
)
result_dict = await PaginationService.paginate(
data_list=result_dict_list,
result_dict = await DictTypeService.get_obj_page_service(
auth=auth,
page_no=page.page_no,
page_size=page.page_size,
search=search,
order_by=page.order_by,
)
log.info("查询字典类型列表成功")
return SuccessResponse(data=result_dict, msg="查询字典类型列表成功")
@@ -331,13 +329,12 @@ async def get_data_list_controller(
order_by = [{"order": "asc"}]
if page.order_by:
order_by = page.order_by
result_dict_list = await DictDataService.get_obj_list_service(
auth=auth, search=search, order_by=order_by
)
result_dict = await PaginationService.paginate(
data_list=result_dict_list,
result_dict = await DictDataService.get_obj_page_service(
auth=auth,
page_no=page.page_no,
page_size=page.page_size,
search=search,
order_by=order_by,
)
log.info("查询字典数据列表成功")
return SuccessResponse(data=result_dict, msg="查询字典数据列表成功")
@@ -67,6 +67,25 @@ class DictTypeService:
)
return [DictTypeOutSchema.model_validate(obj).model_dump() for obj in obj_list]
@classmethod
async def get_obj_page_service(
cls,
auth: AuthSchema,
page_no: int,
page_size: int,
search: DictTypeQueryParam | None = None,
order_by: list[dict] | None = None,
) -> dict:
"""分页查询字典类型(数据库 OFFSET/LIMIT)。"""
offset = (page_no - 1) * page_size
return await DictTypeCRUD(auth).page(
offset=offset,
limit=page_size,
order_by=order_by or [{"id": "asc"}],
search=search.__dict__ if search else {},
out_schema=DictTypeOutSchema,
)
@classmethod
async def create_obj_service(
cls, auth: AuthSchema, redis: Redis, data: DictTypeCreateSchema
@@ -308,6 +327,25 @@ class DictDataService:
)
return [DictDataOutSchema.model_validate(obj).model_dump() for obj in obj_list]
@classmethod
async def get_obj_page_service(
cls,
auth: AuthSchema,
page_no: int,
page_size: int,
search: DictDataQueryParam | None = None,
order_by: list[dict] | None = None,
) -> dict:
"""分页查询字典数据(数据库 OFFSET/LIMIT)。"""
offset = (page_no - 1) * page_size
return await DictDataCRUD(auth).page(
offset=offset,
limit=page_size,
order_by=order_by or [{"id": "asc"}],
search=search.__dict__ if search else {},
out_schema=DictDataOutSchema,
)
@classmethod
async def init_dict_service(cls, redis: Redis) -> None:
"""
@@ -4,7 +4,6 @@ from fastapi import APIRouter, Body, Depends, Path
from fastapi.responses import JSONResponse, StreamingResponse
from app.api.v1.module_system.auth.schema import AuthSchema
from app.common.request import PaginationService
from app.common.response import ResponseSchema, StreamResponse, SuccessResponse
from app.core.base_params import PaginationQueryParam
from app.core.dependencies import AuthPermission
@@ -43,13 +42,12 @@ async def get_obj_list_controller(
order_by = [{"created_time": "desc"}]
if page.order_by:
order_by = page.order_by
result_dict_list = await OperationLogService.get_log_list_service(
search=search, auth=auth, order_by=order_by
)
result_dict = await PaginationService.paginate(
data_list=result_dict_list,
result_dict = await OperationLogService.get_log_page_service(
auth=auth,
page_no=page.page_no,
page_size=page.page_size,
search=search,
order_by=order_by,
)
log.info("查询日志成功")
return SuccessResponse(data=result_dict, msg="查询日志成功")
@@ -56,6 +56,25 @@ class OperationLogService:
log_dict_list = [OperationLogOutSchema.model_validate(log).model_dump() for log in log_list]
return log_dict_list
@classmethod
async def get_log_page_service(
cls,
auth: AuthSchema,
page_no: int,
page_size: int,
search: OperationLogQueryParam | None = None,
order_by: list | None = None,
) -> dict:
"""分页查询操作日志(数据库 OFFSET/LIMIT)。"""
offset = (page_no - 1) * page_size
return await OperationLogCRUD(auth).page(
offset=offset,
limit=page_size,
order_by=order_by or [{"id": "asc"}],
search=search.__dict__ if search else {},
out_schema=OperationLogOutSchema,
)
@classmethod
async def create_log_service(cls, auth: AuthSchema, data: OperationLogCreateSchema) -> dict:
"""
@@ -4,7 +4,6 @@ from fastapi import APIRouter, Body, Depends, Path
from fastapi.responses import JSONResponse, StreamingResponse
from app.api.v1.module_system.auth.schema import AuthSchema
from app.common.request import PaginationService
from app.common.response import ResponseSchema, StreamResponse, SuccessResponse
from app.core.base_params import PaginationQueryParam
from app.core.base_schema import BatchSetAvailable
@@ -66,13 +65,12 @@ async def get_obj_list_controller(
返回:
- JSONResponse: 包含分页公告详情的响应模型。
"""
result_dict_list = await NoticeService.get_notice_list_service(
auth=auth, search=search, order_by=page.order_by
)
result_dict = await PaginationService.paginate(
data_list=result_dict_list,
result_dict = await NoticeService.get_notice_page_service(
auth=auth,
page_no=page.page_no,
page_size=page.page_size,
search=search,
order_by=page.order_by,
)
log.info("查询公告列表成功")
return SuccessResponse(data=result_dict, msg="查询公告列表成功")
@@ -229,7 +227,6 @@ async def get_obj_list_available_controller(
返回:
- JSONResponse: 包含分页已启用公告详情的响应模型。
"""
result_dict_list = await NoticeService.get_notice_list_available_service(auth=auth)
result_dict = await PaginationService.paginate(data_list=result_dict_list)
result_dict = await NoticeService.get_notice_available_page_service(auth=auth)
log.info("查询已启用公告列表成功")
return SuccessResponse(data=result_dict, msg="查询已启用公告列表成功")
@@ -75,6 +75,36 @@ class NoticeService:
for notice_obj in notice_obj_list
]
@classmethod
async def get_notice_page_service(
cls,
auth: AuthSchema,
page_no: int,
page_size: int,
search: NoticeQueryParam | None = None,
order_by: list[dict] | None = None,
) -> dict:
"""分页查询公告(数据库 OFFSET/LIMIT)。"""
offset = (page_no - 1) * page_size
return await NoticeCRUD(auth).page(
offset=offset,
limit=page_size,
order_by=order_by or [{"id": "asc"}],
search=search.__dict__ if search else {},
out_schema=NoticeOutSchema,
)
@classmethod
async def get_notice_available_page_service(cls, auth: AuthSchema) -> dict:
"""已启用公告分页(与历史行为一致:默认第 1 页、每页 10 条)。"""
return await NoticeCRUD(auth).page(
offset=0,
limit=10,
order_by=[{"id": "asc"}],
search={"status": "0"},
out_schema=NoticeOutSchema,
)
@classmethod
async def create_notice_service(cls, auth: AuthSchema, data: NoticeCreateSchema) -> dict:
"""
@@ -5,7 +5,6 @@ from fastapi.responses import JSONResponse, StreamingResponse
from redis.asyncio.client import Redis
from app.api.v1.module_system.auth.schema import AuthSchema
from app.common.request import PaginationService
from app.common.response import ResponseSchema, StreamResponse, SuccessResponse
from app.core.base_params import PaginationQueryParam
from app.core.dependencies import AuthPermission, redis_getter
@@ -118,13 +117,12 @@ async def get_obj_list_controller(
返回:
- JSONResponse: 包含参数列表的 JSON 响应
"""
result_dict_list = await ParamsService.get_obj_list_service(
auth=auth, search=search, order_by=page.order_by
)
result_dict = await PaginationService.paginate(
data_list=result_dict_list,
result_dict = await ParamsService.get_obj_page_service(
auth=auth,
page_no=page.page_no,
page_size=page.page_size,
search=search,
order_by=page.order_by,
)
log.info("获取参数列表成功")
return SuccessResponse(data=result_dict, msg="查询参数列表成功")
@@ -103,6 +103,25 @@ class ParamsService:
obj_list = await ParamsCRUD(auth).get_obj_list_crud()
return [ParamsOutSchema.model_validate(obj).model_dump() for obj in obj_list]
@classmethod
async def get_obj_page_service(
cls,
auth: AuthSchema,
page_no: int,
page_size: int,
search: ParamsQueryParam | None = None,
order_by: list[dict[str, str]] | None = None,
) -> dict:
"""分页查询参数(数据库 OFFSET/LIMIT)。"""
offset = (page_no - 1) * page_size
return await ParamsCRUD(auth).page(
offset=offset,
limit=page_size,
order_by=order_by or [{"id": "asc"}],
search=search.__dict__ if search else {},
out_schema=ParamsOutSchema,
)
@classmethod
async def create_obj_service(
cls, auth: AuthSchema, redis: Redis, data: ParamsCreateSchema
@@ -4,7 +4,6 @@ from fastapi import APIRouter, Body, Depends, Path
from fastapi.responses import JSONResponse, StreamingResponse
from app.api.v1.module_system.auth.schema import AuthSchema
from app.common.request import PaginationService
from app.common.response import ResponseSchema, StreamResponse, SuccessResponse
from app.core.base_params import PaginationQueryParam
from app.core.base_schema import BatchSetAvailable
@@ -49,13 +48,12 @@ async def get_obj_list_controller(
order_by = [{"order": "asc"}]
if page.order_by:
order_by = page.order_by
result_dict_list = await PositionService.get_position_list_service(
search=search, auth=auth, order_by=order_by
)
result_dict = await PaginationService.paginate(
data_list=result_dict_list,
result_dict = await PositionService.get_position_page_service(
auth=auth,
page_no=page.page_no,
page_size=page.page_size,
search=search,
order_by=order_by,
)
log.info("查询岗位列表成功")
return SuccessResponse(data=result_dict, msg="查询岗位列表成功")
@@ -55,6 +55,25 @@ class PositionService:
PositionOutSchema.model_validate(position).model_dump() for position in position_list
]
@classmethod
async def get_position_page_service(
cls,
auth: AuthSchema,
page_no: int,
page_size: int,
search: PositionQueryParam | None = None,
order_by: list[dict[str, str]] | None = None,
) -> dict:
"""分页查询岗位(数据库 OFFSET/LIMIT)。"""
offset = (page_no - 1) * page_size
return await PositionCRUD(auth).page(
offset=offset,
limit=page_size,
order_by=order_by or [{"id": "asc"}],
search=search.__dict__ if search else {},
out_schema=PositionOutSchema,
)
@classmethod
async def create_position_service(cls, auth: AuthSchema, data: PositionCreateSchema) -> dict:
"""
@@ -4,7 +4,6 @@ from fastapi import APIRouter, Body, Depends, Path
from fastapi.responses import JSONResponse, StreamingResponse
from app.api.v1.module_system.auth.schema import AuthSchema
from app.common.request import PaginationService
from app.common.response import ResponseSchema, StreamResponse, SuccessResponse
from app.core.base_params import PaginationQueryParam
from app.core.base_schema import BatchSetAvailable
@@ -50,13 +49,12 @@ async def get_obj_list_controller(
order_by = [{"order": "asc"}]
if page.order_by:
order_by = page.order_by
result_dict_list = await RoleService.get_role_list_service(
search=search, auth=auth, order_by=order_by
)
result_dict = await PaginationService.paginate(
data_list=result_dict_list,
result_dict = await RoleService.get_role_page_service(
auth=auth,
page_no=page.page_no,
page_size=page.page_size,
search=search,
order_by=order_by,
)
log.info("查询角色成功")
return SuccessResponse(data=result_dict, msg="查询角色成功")
@@ -54,6 +54,25 @@ class RoleService:
role_list = await RoleCRUD(auth).get_list_crud(search=search.__dict__, order_by=order_by)
return [RoleOutSchema.model_validate(role).model_dump() for role in role_list]
@classmethod
async def get_role_page_service(
cls,
auth: AuthSchema,
page_no: int,
page_size: int,
search: RoleQueryParam | None = None,
order_by: list[dict[str, str]] | None = None,
) -> dict:
"""分页查询角色(数据库 OFFSET/LIMIT)。"""
offset = (page_no - 1) * page_size
return await RoleCRUD(auth).page(
offset=offset,
limit=page_size,
order_by=order_by or [{"id": "asc"}],
search=search.__dict__ if search else {},
out_schema=RoleOutSchema,
)
@classmethod
async def create_role_service(cls, auth: AuthSchema, data: RoleCreateSchema) -> dict:
"""
@@ -6,7 +6,6 @@ from fastapi.responses import JSONResponse, StreamingResponse
from sqlalchemy.ext.asyncio import AsyncSession
from app.api.v1.module_system.auth.schema import AuthSchema
from app.common.request import PaginationService
from app.common.response import ResponseSchema, StreamResponse, SuccessResponse
from app.core.base_params import PaginationQueryParam
from app.core.base_schema import BatchSetAvailable
@@ -225,13 +224,12 @@ async def get_obj_list_controller(
返回:
- JSONResponse: 分页查询结果JSON响应
"""
result_dict_list = await UserService.get_user_list_service(
search=search, auth=auth, order_by=page.order_by
)
result_dict = await PaginationService.paginate(
data_list=result_dict_list,
result_dict = await UserService.get_user_page_service(
auth=auth,
page_no=page.page_no,
page_size=page.page_size,
search=search,
order_by=page.order_by,
)
log.info("查询用户成功")
return SuccessResponse(data=result_dict, msg="查询用户成功")
@@ -86,6 +86,25 @@ class UserService:
return user_dict_list
@classmethod
async def get_user_page_service(
cls,
auth: AuthSchema,
page_no: int,
page_size: int,
search: UserQueryParam | None = None,
order_by: list[dict[str, str]] | None = None,
) -> dict:
"""分页查询用户(数据库 OFFSET/LIMIT)。"""
offset = (page_no - 1) * page_size
return await UserCRUD(auth).page(
offset=offset,
limit=page_size,
order_by=order_by or [{"id": "asc"}],
search=search.__dict__ if search else {},
out_schema=UserOutSchema,
)
@classmethod
async def create_user_service(cls, data: UserCreateSchema, auth: AuthSchema) -> dict:
"""