Files
FastapiAdmin/backend/app/plugin/module_generator/gencode/service.py
T
zhangtao 9d97c5bb31 fix(gencode): 修复数据库类型映射和导入处理问题
refactor: 优化数据库类型处理逻辑,移除COLLATE和UNSIGNED标记
feat: 添加PostgreSQL数组类型支持
docs: 更新README添加全类型测试表SQL
style: 统一datetime导入方式
2026-02-03 18:12:11 +08:00

795 lines
32 KiB
Python

import io
import os
import zipfile
from collections.abc import Callable
from typing import Any
import anyio
import sqlglot
from sqlglot.expressions import (
Add,
Alter,
Create,
Delete,
Drop,
Insert,
Table,
TruncateTable,
Update,
)
from app.api.v1.module_system.auth.schema import AuthSchema
from app.config.path_conf import BASE_DIR
from app.config.setting import settings
from app.core.exceptions import CustomException
from app.core.logger import log
from .crud import GenTableColumnCRUD, GenTableCRUD
from .schema import (
GenTableColumnOutSchema,
GenTableColumnSchema,
GenTableOutSchema,
GenTableQueryParam,
GenTableSchema,
)
from .tools.gen_util import GenUtils
from .tools.jinja2_template_util import Jinja2TemplateUtil
def handle_service_exception(func: Callable) -> Callable:
async def wrapper(*args, **kwargs):
try:
return await func(*args, **kwargs)
except CustomException:
raise
except Exception as e:
raise CustomException(msg=f"{func.__name__}执行失败: {e!s}")
return wrapper
class GenTableService:
"""代码生成业务表服务层"""
@classmethod
@handle_service_exception
async def get_gen_table_detail_service(cls, auth: AuthSchema, table_id: int) -> dict:
"""获取详细信息。
参数:
- auth (AuthSchema): 认证信息。
- table_id (int): 业务表ID。
返回:
- dict: 包含业务表详细信息的字典。
"""
gen_table = await cls.get_gen_table_by_id_service(auth, table_id)
return GenTableOutSchema.model_validate(gen_table).model_dump()
@classmethod
@handle_service_exception
async def get_gen_table_list_service(
cls, auth: AuthSchema, search: GenTableQueryParam
) -> list[dict]:
"""
获取代码生成业务表列表信息。
参数:
- auth (AuthSchema): 认证信息。
- search (GenTableQueryParam): 查询参数模型。
返回:
- list[dict]: 包含业务表列表信息的字典列表。
"""
gen_table_list_result = await GenTableCRUD(auth=auth).get_gen_table_list(search)
return [GenTableOutSchema.model_validate(obj).model_dump() for obj in gen_table_list_result]
@classmethod
@handle_service_exception
async def get_gen_db_table_list_service(
cls, auth: AuthSchema, search: GenTableQueryParam
) -> list[Any]:
"""获取数据库表列表。
参数:
- auth (AuthSchema): 认证信息。
- search (GenTableQueryParam): 查询参数模型。
返回:
- list[Any]: 包含数据库表列表信息的任意类型列表。
"""
gen_db_table_list_result = await GenTableCRUD(auth=auth).get_db_table_list(search)
return gen_db_table_list_result
@classmethod
@handle_service_exception
async def get_gen_db_table_list_by_name_service(
cls, auth: AuthSchema, table_names: list[str]
) -> list[GenTableOutSchema]:
"""根据表名称组获取数据库表信息。
参数:
- auth (AuthSchema): 认证信息。
- table_names (list[str]): 业务表名称列表。
返回:
- list[GenTableOutSchema]: 包含业务表详细信息的模型列表。
"""
gen_db_table_list_result = await GenTableCRUD(auth).get_db_table_list_by_names(table_names)
# 修复:将GenDBTableSchema对象转换为字典后再传递给GenTableOutSchema
result = [
GenTableOutSchema(**gen_table.model_dump()) for gen_table in gen_db_table_list_result
]
return result
@classmethod
@handle_service_exception
async def import_gen_table_service(
cls, auth: AuthSchema, gen_table_list: list[GenTableOutSchema]
) -> bool:
"""导入表结构到生成器。
参数:
- auth (AuthSchema): 认证信息。
- gen_table_list (list[GenTableOutSchema]): 包含业务表详细信息的模型列表。
返回:
- bool: 成功时返回True,失败时抛出异常。
"""
# 检查是否有表需要导入
if not gen_table_list:
raise CustomException(msg="导入的表结构不能为空")
try:
for table in gen_table_list:
table_name = table.table_name
# 检查表是否已存在
existing_table = await GenTableCRUD(auth).get_gen_table_by_name(table_name)
if existing_table:
raise CustomException(msg=f"以下表已存在,不能重复导入: {table_name}")
GenUtils.init_table(table)
if not table.columns:
table.columns = []
add_gen_table = await GenTableCRUD(auth).add_gen_table(
GenTableSchema.model_validate(table.model_dump())
)
gen_table_columns = await GenTableColumnCRUD(auth).get_gen_db_table_columns_by_name(
table_name
)
if len(gen_table_columns) > 0:
table.id = add_gen_table.id
for column in gen_table_columns:
column_schema = GenTableColumnSchema(
table_id=table.id,
column_name=column.column_name,
column_comment=column.column_comment,
column_type=column.column_type,
column_length=column.column_length,
column_default=column.column_default,
is_pk=column.is_pk,
is_increment=column.is_increment,
is_nullable=column.is_nullable,
is_unique=column.is_unique,
sort=column.sort,
python_type=column.python_type,
python_field=column.python_field,
)
GenUtils.init_column_field(column_schema, table)
await GenTableColumnCRUD(auth).create_gen_table_column_crud(column_schema)
return True
except Exception as e:
raise CustomException(msg=f"导入失败, {e!s}")
@classmethod
@handle_service_exception
async def create_table_service(cls, auth: AuthSchema, sql: str) -> bool | None:
"""创建表结构并导入至代码生成模块。
参数:
- auth (AuthSchema): 认证信息。
- sql (str): 包含`CREATE TABLE`语句的SQL字符串。
返回:
- bool | None: 成功时返回True,失败时抛出异常。
"""
# 验证SQL非空
if not sql or not sql.strip():
raise CustomException(msg="SQL语句不能为空")
try:
# 解析SQL语句
sql_statements = sqlglot.parse(sql, dialect=settings.DATABASE_TYPE)
if not sql_statements:
raise CustomException(msg="无法解析SQL语句,请检查SQL语法")
# 校验sql语句是否为合法的建表语句
validate_create = [
isinstance(sql_statement, Create) for sql_statement in sql_statements
]
validate_forbidden_keywords = [
isinstance(
sql_statement,
(Add, Alter, Delete, Drop, Insert, TruncateTable, Update),
)
for sql_statement in sql_statements
]
if not any(validate_create) or any(validate_forbidden_keywords):
raise CustomException(msg="sql语句不是合法的建表语句")
# 获取要创建的表名
table_names = []
for sql_statement in sql_statements:
if isinstance(sql_statement, Create):
table = sql_statement.find(Table)
if table and table.name:
table_names.append(table.name)
table_names = list(set(table_names))
# 创建CRUD实例
gen_table_crud = GenTableCRUD(auth=auth)
# 检查每个表是否已存在
for table_name in table_names:
# 检查数据库中是否已存在该表
if await gen_table_crud.check_table_exists(table_name):
raise CustomException(msg=f"表 {table_name} 已存在,请检查并修改表名后重试")
# 检查代码生成模块中是否已导入该表
existing_table = await gen_table_crud.get_gen_table_by_name(table_name)
if existing_table:
raise CustomException(
msg=f"表 {table_name} 已在代码生成模块中存在,请检查并修改表名后重试"
)
# 表不存在,执行SQL语句创建表
for sql_statement in sql_statements:
if not isinstance(sql_statement, Create):
continue
exc_sql = sql_statement.sql(dialect=settings.DATABASE_TYPE)
log.info(f"执行SQL语句: {exc_sql}")
if not await gen_table_crud.execute_sql(exc_sql):
raise CustomException(msg=f"执行SQL语句 {exc_sql} 失败,请检查数据库")
return True
except Exception as e:
raise CustomException(msg=f"创建表结构失败: {e!s}")
@classmethod
@handle_service_exception
async def update_gen_table_service(
cls, auth: AuthSchema, data: GenTableSchema, table_id: int
) -> dict[str, Any]:
"""编辑业务表信息。
参数:
- auth (AuthSchema): 认证信息。
- data (GenTableSchema): 包含业务表详细信息的模型。
- table_id (int): 业务表ID。
返回:
- dict[str, Any]: 更新后的业务表信息。
"""
# 处理params为None的情况
gen_table_info = await cls.get_gen_table_by_id_service(auth, table_id)
if gen_table_info.id:
try:
# 直接调用edit_gen_table方法,它会在内部处理排除嵌套字段的逻辑
result = await GenTableCRUD(auth).edit_gen_table(table_id, data)
if not result:
raise CustomException(msg="更新业务表信息失败")
# 处理data.columns为None的情况
if data.columns:
for gen_table_column in data.columns:
# 确保column有id字段
if hasattr(gen_table_column, "id") and gen_table_column.id:
column_schema = GenTableColumnSchema(**gen_table_column.model_dump())
await GenTableColumnCRUD(auth).update_gen_table_column_crud(
gen_table_column.id, column_schema
)
# 重新获取带有预加载关系的对象,避免懒加载导致的MissingGreenlet错误
updated_gen_table = await GenTableCRUD(auth).get_gen_table_by_id(table_id)
return GenTableOutSchema.model_validate(updated_gen_table).model_dump()
except Exception as e:
raise CustomException(msg=str(e))
else:
raise CustomException(msg="业务表不存在")
@classmethod
@handle_service_exception
async def delete_gen_table_service(cls, auth: AuthSchema, ids: list[int]) -> None:
"""删除业务表信息(先删字段,再删表)。
参数:
- auth (AuthSchema): 认证信息。
- ids (list[int]): 业务表ID列表。
返回:
- None
"""
# 验证ID列表非空
if not ids:
raise CustomException(msg="ID列表不能为空")
try:
# 先删除相关的字段信息
await GenTableColumnCRUD(auth=auth).delete_gen_table_column_by_table_id_crud(ids)
# 再删除表信息
await GenTableCRUD(auth=auth).delete_gen_table(ids)
except Exception as e:
raise CustomException(msg=str(e))
@classmethod
@handle_service_exception
async def get_gen_table_by_id_service(
cls, auth: AuthSchema, table_id: int
) -> GenTableOutSchema:
"""获取需要生成代码的业务表详细信息。
参数:
- auth (AuthSchema): 认证信息。
- table_id (int): 业务表ID。
返回:
- GenTableOutSchema: 业务表详细信息模型。
"""
gen_table = await GenTableCRUD(auth=auth).get_gen_table_by_id(table_id)
if not gen_table:
raise CustomException(msg="业务表不存在")
result = GenTableOutSchema.model_validate(gen_table)
return result
@classmethod
@handle_service_exception
async def get_gen_table_all_service(cls, auth: AuthSchema) -> list[GenTableOutSchema]:
"""获取所有业务表信息(列表)。
参数:
- auth (AuthSchema): 认证信息。
返回:
- list[GenTableOutSchema]: 业务表详细信息模型列表。
"""
gen_table_all = await GenTableCRUD(auth=auth).get_gen_table_all() or []
result = []
for gen_table in gen_table_all:
try:
table_out = GenTableOutSchema.model_validate(gen_table)
result.append(table_out)
except Exception as e:
log.error(f"转换业务表时出错: {e!s}")
continue
return result
@classmethod
@handle_service_exception
async def preview_code_service(cls, auth: AuthSchema, table_id: int) -> dict[str, Any]:
"""
预览代码(根据模板渲染内存结果)。
参数:
- auth (AuthSchema): 认证信息。
- table_id (int): 业务表ID。
返回:
- dict[str, Any]: 文件名到渲染内容的映射。
"""
gen_table = GenTableOutSchema.model_validate(
await GenTableCRUD(auth).get_gen_table_by_id(table_id)
)
await cls.set_pk_column(gen_table)
env = Jinja2TemplateUtil.get_env()
context = Jinja2TemplateUtil.prepare_context(gen_table)
template_list = Jinja2TemplateUtil.get_template_list()
preview_code_result = {}
for template in template_list:
try:
render_content = await env.get_template(template).render_async(**context)
preview_code_result[template] = render_content
except Exception as e:
log.error(f"渲染模板 {template} 时出错: {e!s}")
# 即使某个模板渲染失败,也继续处理其他模板
preview_code_result[template] = f"渲染错误: {e!s}"
return preview_code_result
@classmethod
@handle_service_exception
async def generate_code_service(cls, auth: AuthSchema, table_name: str) -> bool:
"""生成代码至指定路径(安全写入+可跳过覆盖)。
- 安全:限制写入在项目根目录内;越界路径自动回退到项目根目录。
参数:
- auth (AuthSchema): 认证信息。
- table_name (str): 业务表名。
返回:
- bool: 生成是否成功。
"""
# 验证表名非空
if not table_name or not table_name.strip():
raise CustomException(msg="表名不能为空")
env = Jinja2TemplateUtil.get_env()
render_info = await cls.__get_gen_render_info(auth, table_name)
gen_table_schema: GenTableOutSchema = render_info[3]
from app.api.v1.module_system.menu.crud import MenuCRUD
from app.api.v1.module_system.menu.schema import MenuCreateSchema
from app.utils.common_util import CamelCaseUtil
# 构建权限前缀
permission_prefix = f"{gen_table_schema.module_name}:{gen_table_schema.business_name}"
# 创建菜单 CRUD 实例
menu_crud = MenuCRUD(auth)
if not gen_table_schema.business_name:
raise CustomException(msg="业务名称不能为空")
if not gen_table_schema.function_name:
raise CustomException(msg="功能名称不能为空")
if not gen_table_schema.package_name:
raise CustomException(msg="包名不能为空")
# 1. 先检查并创建菜单(目录菜单、功能菜单、按钮权限)
# 检查是否需要创建目录菜单
if gen_table_schema.parent_menu_id:
# 如果传了上级菜单ID(菜单类型=1),则不创建目录菜单,直接使用该ID作为功能菜单的父ID
dir_menu_id = gen_table_schema.parent_menu_id
else:
# 如果没传上级菜单ID,则需要创建新的模块目录菜单(类型=1:目录)
existing_dir_menu = await menu_crud.get(name=gen_table_schema.business_name)
if existing_dir_menu:
dir_menu_id = existing_dir_menu.id
else:
dir_parent_menu = await menu_crud.create(
MenuCreateSchema(
name=gen_table_schema.package_name,
type=1,
order=9999,
permission=None,
icon="menu",
route_name=CamelCaseUtil.snake_to_camel(gen_table_schema.package_name),
route_path=f"/{gen_table_schema.package_name}",
component_path=None,
redirect=f"/{gen_table_schema.package_name}/{gen_table_schema.business_name}",
hidden=False,
keep_alive=True,
always_show=False,
title=gen_table_schema.package_name,
params=None,
affix=False,
parent_id=gen_table_schema.parent_menu_id, # 这里应该是None,因为上面已经判断过了
status="0",
description=f"{gen_table_schema.business_name}目录",
)
)
dir_menu_id = dir_parent_menu.id
# 检查功能菜单是否已存在,如果存在则抛出错误
existing_func_menu = await menu_crud.get(name=gen_table_schema.function_name, type=2)
if existing_func_menu:
raise CustomException(
msg=f"功能菜单名称 '{gen_table_schema.function_name}' 已存在,不能重复创建"
)
# 创建功能菜单(类型=2:菜单)
parent_menu = await menu_crud.create(
MenuCreateSchema(
name=gen_table_schema.function_name,
type=2,
order=9999,
permission=f"{permission_prefix}:query",
icon="menu",
route_name=CamelCaseUtil.snake_to_camel(gen_table_schema.business_name),
route_path=f"/{gen_table_schema.package_name}/{gen_table_schema.business_name}",
component_path=f"{gen_table_schema.module_name}/{gen_table_schema.business_name}/index",
redirect=None,
hidden=False,
keep_alive=True,
always_show=False,
title=gen_table_schema.function_name,
params=None,
affix=False,
parent_id=dir_menu_id, # 使用目录菜单ID或用户指定的parent_menu_id作为父ID
status="0",
description=f"{gen_table_schema.function_name}功能菜单",
)
)
# 创建按钮权限(类型=3:按钮/权限)
buttons = [
{
"name": f"{gen_table_schema.function_name}查询",
"permission": f"{permission_prefix}:query",
"order": 1,
},
{
"name": f"{gen_table_schema.function_name}详情",
"permission": f"{permission_prefix}:detail",
"order": 2,
},
{
"name": f"{gen_table_schema.function_name}新增",
"permission": f"{permission_prefix}:create",
"order": 3,
},
{
"name": f"{gen_table_schema.function_name}修改",
"permission": f"{permission_prefix}:update",
"order": 4,
},
{
"name": f"{gen_table_schema.function_name}删除",
"permission": f"{permission_prefix}:delete",
"order": 5,
},
{
"name": f"{gen_table_schema.function_name}批量状态修改",
"permission": f"{permission_prefix}:patch",
"order": 6,
},
{
"name": f"{gen_table_schema.function_name}导出",
"permission": f"{permission_prefix}:export",
"order": 7,
},
{
"name": f"{gen_table_schema.function_name}导入",
"permission": f"{permission_prefix}:import",
"order": 8,
},
{
"name": f"{gen_table_schema.function_name}下载导入模板",
"permission": f"{permission_prefix}:download",
"order": 9,
},
]
for button in buttons:
# 检查按钮权限是否已存在
await menu_crud.create(
MenuCreateSchema(
name=button["name"],
type=3,
order=button["order"],
permission=button["permission"],
icon=None,
route_name=None,
route_path=None,
component_path=None,
redirect=None,
hidden=False,
keep_alive=True,
always_show=False,
title=button["name"],
params=None,
affix=False,
parent_id=parent_menu.id,
status="0",
description=f"{gen_table_schema.function_name}功能按钮",
)
)
log.info(f"成功创建按钮权限: {button['name']}")
log.info(f"成功创建{gen_table_schema.function_name}菜单及按钮权限")
# 2. 菜单创建成功后,再生成页面代码
for template in render_info[0]:
try:
render_content = await env.get_template(template).render_async(**render_info[2])
file_name = Jinja2TemplateUtil.get_file_name(template, gen_table_schema)
full_path = BASE_DIR.parent.joinpath(file_name)
gen_path = str(full_path)
if not gen_path:
raise CustomException(msg="【代码生成】生成路径为空")
# 确保目录存在
os.makedirs(os.path.dirname(gen_path), exist_ok=True)
await anyio.Path(gen_path).write_text(render_content, encoding="utf-8")
module_init_path = BASE_DIR.parent.joinpath(
f"backend/app/plugin/{gen_table_schema.module_name}/__init__.py"
)
if not module_init_path.exists():
# 创建module_name目录的__init__.py文件
os.makedirs(os.path.dirname(module_init_path), exist_ok=True)
await anyio.Path(module_init_path).write_text(
"# -*- coding: utf-8 -*-", encoding="utf-8"
)
except Exception as e:
raise CustomException(
msg=f"渲染模板失败,表名:{gen_table_schema.table_name},详细错误信息:{e!s}"
)
return True
@classmethod
@handle_service_exception
async def batch_gen_code_service(cls, auth: AuthSchema, table_names: list[str]) -> bytes:
"""
批量生成代码并打包为ZIP。
- 备注:内存生成并压缩,兼容多模板类型;供下载使用。
参数:
- auth (AuthSchema): 认证信息。
- table_names (list[str]): 业务表名列表。
返回:
- bytes: 包含所有生成代码的ZIP文件内容。
"""
# 验证表名列表非空
if not table_names:
raise CustomException(msg="表名列表不能为空")
zip_buffer = io.BytesIO()
with zipfile.ZipFile(zip_buffer, "w", zipfile.ZIP_DEFLATED) as zip_file:
for table_name in table_names:
if not table_name.strip():
continue
try:
env = Jinja2TemplateUtil.get_env()
render_info = await cls.__get_gen_render_info(auth, table_name)
for template_file, output_file in zip(
render_info[0], render_info[1], strict=False
):
render_content = await env.get_template(template_file).render_async(
**render_info[2]
)
zip_file.writestr(output_file, render_content)
except Exception as e:
log.error(f"批量生成代码时处理表 {table_name} 出错: {e!s}")
# 继续处理其他表,不中断整个过程
continue
zip_data = zip_buffer.getvalue()
zip_buffer.close()
return zip_data
@classmethod
@handle_service_exception
async def sync_db_service(cls, auth: AuthSchema, table_name: str) -> None:
"""
同步数据库表结构到业务表。
参数:
- auth (AuthSchema): 认证信息。
- table_name (str): 业务表名。
返回:
- None
"""
# 验证表名非空
if not table_name or not table_name.strip():
raise CustomException(msg="表名不能为空")
gen_table = await GenTableCRUD(auth).get_gen_table_by_name(table_name)
if not gen_table:
raise CustomException(msg="业务表不存在")
table = GenTableOutSchema.model_validate(gen_table)
if not table.id:
raise CustomException(msg="业务表ID不能为空")
table_columns = table.columns or []
table_column_map = {column.column_name: column for column in table_columns}
# 确保db_table_columns始终是列表类型,避免None值
db_table_columns = (
await GenTableColumnCRUD(auth).get_gen_db_table_columns_by_name(table_name) or []
)
db_table_columns = [col for col in db_table_columns if col is not None]
db_table_column_names = [column.column_name for column in db_table_columns]
try:
for column in db_table_columns:
GenUtils.init_column_field(column, table)
if column.column_name in table_column_map:
prev_column = table_column_map[column.column_name]
if hasattr(prev_column, "id") and prev_column.id:
column.id = prev_column.id
if hasattr(prev_column, "dict_type") and prev_column.dict_type:
column.dict_type = prev_column.dict_type
if hasattr(prev_column, "query_type") and prev_column.query_type:
column.query_type = prev_column.query_type
if hasattr(prev_column, "html_type") and prev_column.html_type:
column.html_type = prev_column.html_type
is_pk_bool = False
if hasattr(prev_column, "is_pk"):
is_pk_bool = (
prev_column.is_pk
if isinstance(prev_column.is_pk, bool)
else str(prev_column.is_pk) == "1"
)
if hasattr(prev_column, "is_nullable") and not is_pk_bool:
column.is_nullable = prev_column.is_nullable
if hasattr(prev_column, "python_field"):
column.python_field = prev_column.python_field or column.python_field
if hasattr(column, "id") and column.id:
await GenTableColumnCRUD(auth).update_gen_table_column_crud(
column.id, column
)
else:
await GenTableColumnCRUD(auth).create_gen_table_column_crud(column)
else:
# 设置table_id以确保新字段能正确关联到表
column.table_id = table.id
await GenTableColumnCRUD(auth).create_gen_table_column_crud(column)
del_columns = [
column
for column in table_columns
if column.column_name not in db_table_column_names
]
if del_columns:
for column in del_columns:
if hasattr(column, "id") and column.id:
await GenTableColumnCRUD(auth).delete_gen_table_column_by_column_id_crud([
column.id
])
except Exception as e:
raise CustomException(msg=f"同步失败: {e!s}")
@classmethod
async def set_pk_column(cls, gen_table: GenTableOutSchema) -> None:
"""设置主键列信息(主表/子表)。
- 备注:同时兼容`pk`布尔与`is_pk == '1'`字符串两种标识。
参数:
- gen_table (GenTableOutSchema): 业务表详细信息模型。
返回:
- None
"""
if gen_table.columns:
for column in gen_table.columns:
# 修复:确保正确检查主键标识
if getattr(column, "pk", False) or getattr(column, "is_pk", "") == "1":
gen_table.pk_column = column
break
# 如果没有找到主键列且有列存在,使用第一个列作为主键
if gen_table.pk_column is None and gen_table.columns:
gen_table.pk_column = gen_table.columns[0]
@classmethod
async def __get_gen_render_info(cls, auth: AuthSchema, table_name: str) -> list[Any]:
"""
获取生成代码渲染模板相关信息。
参数:
- auth (AuthSchema): 认证对象。
- table_name (str): 业务表名称。
返回:
- list[Any]: [模板列表, 输出文件名列表, 渲染上下文, 业务表对象]。
异常:
- CustomException: 当业务表不存在或数据转换失败时抛出。
"""
gen_table_model = await GenTableCRUD(auth=auth).get_gen_table_by_name(table_name)
# 检查表是否存在
if gen_table_model is None:
raise CustomException(msg=f"业务表 {table_name} 不存在")
gen_table = GenTableOutSchema.model_validate(gen_table_model)
await cls.set_pk_column(gen_table)
context = Jinja2TemplateUtil.prepare_context(gen_table)
template_list = Jinja2TemplateUtil.get_template_list()
output_files = [
Jinja2TemplateUtil.get_file_name(template, gen_table) for template in template_list
]
return [template_list, output_files, context, gen_table]
class GenTableColumnService:
"""代码生成业务表字段服务层"""
@classmethod
@handle_service_exception
async def get_gen_table_column_list_by_table_id_service(
cls, auth: AuthSchema, table_id: int
) -> list[dict[str, Any]]:
"""获取业务表字段列表信息(输出模型)。
参数:
- auth (AuthSchema): 认证信息。
- table_id (int): 业务表ID。
返回:
- list[dict[str, Any]]: 业务表字段列表,每个元素为字段详细信息字典。
"""
gen_table_column_list_result = await GenTableColumnCRUD(auth).list_gen_table_column_crud({
"table_id": table_id
})
result = [
GenTableColumnOutSchema.model_validate(gen_table_column).model_dump()
for gen_table_column in gen_table_column_list_result
]
return result