Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion backend/plugin/code_generator/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

包含代码生成的相关配置,详情查看:`generator/model/gen_business.py`

### 2. 代码生成模型
### 2. 代码生成模型列

包含代码生成所需要的模型列信息,就像正常定义模型列一样,目前支持的功能有限

Expand Down
4 changes: 2 additions & 2 deletions backend/plugin/code_generator/api/router.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@
from backend.core.conf import settings
from backend.plugin.code_generator.api.v1.business import router as business_router
from backend.plugin.code_generator.api.v1.code import router as gen_router
from backend.plugin.code_generator.api.v1.column import router as model_router
from backend.plugin.code_generator.api.v1.column import router as column_router

v1 = APIRouter(prefix=f'{settings.FASTAPI_API_V1_PATH}/generates', tags=['代码生成'])

v1.include_router(business_router, prefix='/businesses')
v1.include_router(model_router, prefix='/models')
v1.include_router(column_router, prefix='/columns')
v1.include_router(gen_router, prefix='/codes')
18 changes: 12 additions & 6 deletions backend/plugin/code_generator/api/v1/business.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,19 @@
GetGenBusinessDetail,
UpdateGenBusinessParam,
)
from backend.plugin.code_generator.schema.column import GetGenModelDetail
from backend.plugin.code_generator.schema.column import GetGenColumnDetail
from backend.plugin.code_generator.service.business_service import gen_business_service
from backend.plugin.code_generator.service.column_service import gen_model_service
from backend.plugin.code_generator.service.column_service import gen_column_service

router = APIRouter()


@router.get('/all', summary='获取所有代码生成业务', dependencies=[DependsJwtAuth])
async def get_all_businesses() -> ResponseSchemaModel[list[GetGenBusinessDetail]]:
data = await gen_business_service.get_all()
return response_base.success(data=data)


@router.get('/{pk}', summary='获取代码生成业务详情', dependencies=[DependsJwtAuth])
async def get_business(
pk: Annotated[int, Path(description='业务 ID')],
Expand All @@ -47,11 +53,11 @@ async def get_businesses_paged(
return response_base.success(data=page_data)


@router.get('/{pk}/models', summary='获取代码生成业务所有模型', dependencies=[DependsJwtAuth])
async def get_business_all_models(
@router.get('/{pk}/columns', summary='获取代码生成业务所有模型列', dependencies=[DependsJwtAuth])
async def get_business_all_columns(
pk: Annotated[int, Path(description='业务 ID')],
) -> ResponseSchemaModel[list[GetGenModelDetail]]:
data = await gen_model_service.get_models(business_id=pk)
) -> ResponseSchemaModel[list[GetGenColumnDetail]]:
data = await gen_column_service.get_columns(business_id=pk)
return response_base.success(data=data)


Expand Down
2 changes: 1 addition & 1 deletion backend/plugin/code_generator/api/v1/code.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
@router.get('/tables', summary='获取数据库表')
async def get_all_tables(
table_schema: Annotated[str, Query(description='数据库名')] = 'fba',
) -> ResponseSchemaModel[list[str]]:
) -> ResponseSchemaModel[list[dict[str, str]]]:
data = await gen_service.get_tables(table_schema=table_schema)
return response_base.success(data=data)

Expand Down
40 changes: 20 additions & 20 deletions backend/plugin/code_generator/api/v1/column.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,62 +8,62 @@
from backend.common.security.jwt import DependsJwtAuth
from backend.common.security.permission import RequestPermission
from backend.common.security.rbac import DependsRBAC
from backend.plugin.code_generator.schema.column import CreateGenModelParam, GetGenModelDetail, UpdateGenModelParam
from backend.plugin.code_generator.service.column_service import gen_model_service
from backend.plugin.code_generator.schema.column import CreateGenColumnParam, GetGenColumnDetail, UpdateGenColumnParam
from backend.plugin.code_generator.service.column_service import gen_column_service

router = APIRouter()


@router.get('/types', summary='获取代码生成模型列类型', dependencies=[DependsJwtAuth])
async def get_model_types() -> ResponseSchemaModel[list[str]]:
model_types = await gen_model_service.get_types()
return response_base.success(data=model_types)
async def get_column_types() -> ResponseSchemaModel[list[str]]:
column_types = await gen_column_service.get_types()
return response_base.success(data=column_types)


@router.get('/{pk}', summary='获取代码生成模型详情', dependencies=[DependsJwtAuth])
async def get_model(pk: Annotated[int, Path(description='模型 ID')]) -> ResponseSchemaModel[GetGenModelDetail]:
data = await gen_model_service.get(pk=pk)
@router.get('/{pk}', summary='获取代码生成模型列详情', dependencies=[DependsJwtAuth])
async def get_column(pk: Annotated[int, Path(description='模型列 ID')]) -> ResponseSchemaModel[GetGenColumnDetail]:
data = await gen_column_service.get(pk=pk)
return response_base.success(data=data)


@router.post(
'',
summary='创建代码生成模型',
summary='创建代码生成模型列',
dependencies=[
Depends(RequestPermission('codegen:model:add')),
Depends(RequestPermission('codegen:column:add')),
DependsRBAC,
],
)
async def create_model(obj: CreateGenModelParam) -> ResponseModel:
await gen_model_service.create(obj=obj)
async def create_column(obj: CreateGenColumnParam) -> ResponseModel:
await gen_column_service.create(obj=obj)
return response_base.success()


@router.put(
'/{pk}',
summary='更新代码生成模型',
summary='更新代码生成模型列',
dependencies=[
Depends(RequestPermission('codegen:model:edit')),
Depends(RequestPermission('codegen:column:edit')),
DependsRBAC,
],
)
async def update_model(pk: Annotated[int, Path(description='模型 ID')], obj: UpdateGenModelParam) -> ResponseModel:
count = await gen_model_service.update(pk=pk, obj=obj)
async def update_column(pk: Annotated[int, Path(description='模型列 ID')], obj: UpdateGenColumnParam) -> ResponseModel:
count = await gen_column_service.update(pk=pk, obj=obj)
if count > 0:
return response_base.success()
return response_base.fail()


@router.delete(
'/{pk}',
summary='删除代码生成模型',
summary='删除代码生成模型列',
dependencies=[
Depends(RequestPermission('codegen:model:del')),
Depends(RequestPermission('codegen:column:del')),
DependsRBAC,
],
)
async def delete_model(pk: Annotated[int, Path(description='模型 ID')]) -> ResponseModel:
count = await gen_model_service.delete(pk=pk)
async def delete_column(pk: Annotated[int, Path(description='模型列 ID')]) -> ResponseModel:
count = await gen_column_service.delete(pk=pk)
if count > 0:
return response_base.success()
return response_base.fail()
12 changes: 11 additions & 1 deletion backend/plugin/code_generator/crud/crud_business.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from typing import Sequence

from sqlalchemy import Select
from sqlalchemy.ext.asyncio import AsyncSession
Expand Down Expand Up @@ -32,6 +33,15 @@ async def get_by_name(self, db: AsyncSession, name: str) -> GenBusiness | None:
"""
return await self.select_model_by_column(db, table_name=name)

async def get_all(self, db: AsyncSession) -> Sequence[GenBusiness]:
"""
获取所有代码生成业务

:param db: 数据库会话
:return:
"""
return await self.select_models(db)

async def get_list(self, table_name: str | None) -> Select:
"""
获取所有代码生成业务
Expand All @@ -44,7 +54,7 @@ async def get_list(self, table_name: str | None) -> Select:
if table_name is not None:
filters['table_name__like'] = f'%{table_name}%'

return await self.select_order('id', 'desc', **filters)
return await self.select_order('id', 'desc', load_strategies={'gen_column': 'noload'}, **filters)

async def create(self, db: AsyncSession, obj: CreateGenBusinessParam) -> None:
"""
Expand Down
36 changes: 20 additions & 16 deletions backend/plugin/code_generator/crud/crud_code.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# -*- coding: utf-8 -*-
from typing import Sequence

from sqlalchemy import Row, text
from sqlalchemy import Row, RowMapping, text
from sqlalchemy.ext.asyncio import AsyncSession

from backend.core.conf import settings
Expand All @@ -12,7 +12,7 @@ class CRUDGen:
"""代码生成 CRUD 类"""

@staticmethod
async def get_all_tables(db: AsyncSession, table_schema: str) -> Sequence[str]:
async def get_all_tables(db: AsyncSession, table_schema: str) -> Sequence[RowMapping]:
"""
获取所有表名

Expand All @@ -22,20 +22,23 @@ async def get_all_tables(db: AsyncSession, table_schema: str) -> Sequence[str]:
"""
if settings.DATABASE_TYPE == 'mysql':
sql = """
SELECT table_name AS table_name FROM information_schema.tables
WHERE table_name NOT LIKE 'sys_gen_%'
SELECT table_name AS table_name, table_comment AS table_comment
FROM information_schema.tables
WHERE table_name NOT LIKE 'sys_gen_%'
AND table_schema = :table_schema;
"""
else:
sql = """
SELECT table_name AS table_name FROM information_schema.tables
WHERE table_name NOT LIKE 'sys_gen_%'
AND table_catalog = :table_schema
AND table_schema = 'public'; -- schema 通常是 'public'
SELECT c.relname AS table_name, obj_description(c.oid) AS table_comment
FROM pg_class c
LEFT JOIN pg_namespace n ON n.oid = c.relnamespace
WHERE c.relkind = 'r'
AND n.nspname = 'public' -- schema 通常是 'public'
AND c.relname NOT LIKE 'sys_gen_%';
"""
stmt = text(sql).bindparams(table_schema=table_schema)
result = await db.execute(stmt)
return result.scalars().all()
return result.mappings().all()

@staticmethod
async def get_table(db: AsyncSession, table_name: str) -> Row[tuple]:
Expand All @@ -48,18 +51,19 @@ async def get_table(db: AsyncSession, table_name: str) -> Row[tuple]:
"""
if settings.DATABASE_TYPE == 'mysql':
sql = """
SELECT table_name AS table_name, table_comment AS table_comment FROM information_schema.tables
SELECT table_name AS table_name, table_comment AS table_comment
FROM information_schema.tables
WHERE table_name NOT LIKE 'sys_gen_%'
AND table_name = :table_name;
"""
else:
sql = """
SELECT t.tablename AS table_name,
pg_catalog.obj_description(t.tablename::regclass, 'pg_class') AS table_comment
FROM pg_tables t
WHERE t.tablename NOT LIKE 'sys_gen_%'
AND t.tablename = :table_name
AND t.schemaname = 'public'; -- schema 通常是 'public'
SELECT c.relname AS table_name, obj_description(c.oid) AS table_comment
FROM pg_class c
LEFT JOIN pg_namespace n ON n.oid = c.relnamespace
WHERE c.relkind = 'r'
AND n.nspname = 'public' -- schema 通常是 'public'
AND c.relname NOT LIKE 'sys_gen_%';
"""
stmt = text(sql).bindparams(table_name=table_name)
result = await db.execute(stmt)
Expand Down
26 changes: 13 additions & 13 deletions backend/plugin/code_generator/crud/crud_column.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@
from sqlalchemy_crud_plus import CRUDPlus

from backend.plugin.code_generator.model import GenColumn
from backend.plugin.code_generator.schema.column import CreateGenModelParam, UpdateGenModelParam
from backend.plugin.code_generator.schema.column import CreateGenColumnParam, UpdateGenColumnParam


class CRUDGenModel(CRUDPlus[GenColumn]):
"""代码生成模型 CRUD 类"""
class CRUDGenColumn(CRUDPlus[GenColumn]):
"""代码生成模型列 CRUD 类"""

async def get(self, db: AsyncSession, pk: int) -> GenColumn | None:
"""
Expand All @@ -32,38 +32,38 @@ async def get_all_by_business(self, db: AsyncSession, business_id: int) -> Seque
"""
return await self.select_models_order(db, sort_columns='sort', gen_business_id=business_id)

async def create(self, db: AsyncSession, obj: CreateGenModelParam, pd_type: str | None) -> None:
async def create(self, db: AsyncSession, obj: CreateGenColumnParam, pd_type: str | None) -> None:
"""
创建代码生成模型
创建代码生成模型列

:param db: 数据库会话
:param obj: 创建代码生成模型参数
:param obj: 创建代码生成模型列参数
:param pd_type: Pydantic 类型
:return:
"""
await self.create_model(db, obj, pd_type=pd_type)

async def update(self, db: AsyncSession, pk: int, obj: UpdateGenModelParam, pd_type: str | None) -> int:
async def update(self, db: AsyncSession, pk: int, obj: UpdateGenColumnParam, pd_type: str | None) -> int:
"""
更新代码生成模型
更新代码生成模型列

:param db: 数据库会话
:param pk: 代码生成模型 ID
:param obj: 更新代码生成模型参数
:param pk: 代码生成模型列 ID
:param obj: 更新代码生成模型列参数
:param pd_type: Pydantic 类型
:return:
"""
return await self.update_model(db, pk, obj, pd_type=pd_type)

async def delete(self, db: AsyncSession, pk: int) -> int:
"""
删除代码生成模型
删除代码生成模型列

:param db: 数据库会话
:param pk: 代码生成模型 ID
:param pk: 代码生成模型列 ID
:return:
"""
return await self.delete_model(db, pk)


gen_model_dao: CRUDGenModel = CRUDGenModel(GenColumn)
gen_column_dao: CRUDGenColumn = CRUDGenColumn(GenColumn)
4 changes: 2 additions & 2 deletions backend/plugin/code_generator/enums.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from backend.common.enums import StrEnum


class GenModelMySQLColumnType(StrEnum):
class GenMySQLColumnType(StrEnum):
"""代码生成模型列类型(MySQL)"""

# Python 类型映射
Expand Down Expand Up @@ -68,7 +68,7 @@ class GenModelMySQLColumnType(StrEnum):
YEAR = 'int'


class GenModelPostgreSQLColumnType(StrEnum):
class GenPostgreSQLColumnType(StrEnum):
"""代码生成模型列类型(PostgreSQL)"""

# Python 类型映射
Expand Down
2 changes: 1 addition & 1 deletion backend/plugin/code_generator/model/business.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,5 +33,5 @@ class GenBusiness(Base):
remark: Mapped[str | None] = mapped_column(
LONGTEXT().with_variant(TEXT, 'postgresql'), default=None, comment='备注'
)
# 代码生成业务模型一对多
# 代码生成业务模型列一对多
gen_column: Mapped[list['GenColumn']] = relationship(init=False, back_populates='gen_business')
2 changes: 1 addition & 1 deletion backend/plugin/code_generator/model/column.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ class GenColumn(DataClassBase):
is_pk: Mapped[bool] = mapped_column(default=False, comment='是否主键')
is_nullable: Mapped[bool] = mapped_column(default=False, comment='是否可为空')

# 代码生成业务模型一对多
# 代码生成业务模型列一对多
gen_business_id: Mapped[int] = mapped_column(
BigInteger, ForeignKey('gen_business.id', ondelete='CASCADE'), default=0, comment='代码生成业务ID'
)
Expand Down
2 changes: 1 addition & 1 deletion backend/plugin/code_generator/plugin.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[plugin]
summary = '代码生成'
version = '0.0.2'
version = '0.0.3'
description = '生成通用业务代码'
author = 'wu-clan'

Expand Down
8 changes: 4 additions & 4 deletions backend/plugin/code_generator/schema/business.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,12 @@ class GenBusinessSchemaBase(SchemaBase):
table_name: str = Field(description='表名称(英文)')
doc_comment: str = Field(description='文档注释(用于函数/参数文档)')
table_comment: str | None = Field(None, description='表描述')
class_name: str | None = Field(None, description='基础类名 (默认为英文表名称)')
schema_name: str | None = Field(None, description='Schema 名称 (默认为英文表名称)')
filename: str | None = Field(None, description='基础文件名(默认为英文表名称)')
class_name: str | None = Field(None, description='用于 python 代码基础类名')
schema_name: str | None = Field(None, description='用于 python Schema 代码基础类名')
filename: str | None = Field(None, description='用于 python 代码基础文件名')
default_datetime_column: bool = Field(True, description='是否存在默认时间列')
api_version: str = Field('v1', description='代码生成 api 版本')
gen_path: str | None = Field(None, description='代码生成路径(默认为 app 根路径)')
gen_path: str | None = Field(None, description='代码生成路径')
remark: str | None = Field(None, description='备注')


Expand Down
Loading