From 4b0c1465203a9650c4d13d0fc11615340b919900 Mon Sep 17 00:00:00 2001 From: coderxslee Date: Mon, 20 Apr 2026 20:18:53 +0800 Subject: [PATCH] =?UTF-8?q?git=20commit=20-m=20"fix(codegen):=20=E6=B7=BB?= =?UTF-8?q?=E5=8A=A0=E8=BD=AF=E5=88=A0=E9=99=A4=E5=AD=97=E6=AE=B5=E6=94=AF?= =?UTF-8?q?=E6=8C=81=EF=BC=8C=E9=81=BF=E5=85=8D=E5=AD=97=E6=AE=B5=E9=87=8D?= =?UTF-8?q?=E5=A4=8D=E5=AE=9A=E4=B9=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## 背景 本次修复包含前后端两部分: 1. 前端SQL模板添加软删除字段(新功能) 2. 后端代码模板排除软删除字段(预防性修复) ## 修复内容 ### 前端模板:添加软删除字段(新功能) **文件**: createTableVisualPresets.ts 之前前端SQL模板缺少软删除字段,导致生成的表不完整。 - **mixinMysql()**: 添加软删除字段 - is_deleted: tinyint(1) NOT NULL - 标记是否已删除 - deleted_time: datetime NULL - 记录删除时间 - deleted_id: int NULL - 记录删除人ID - **mixinPostgres()**: 添加软删除字段 - is_deleted: boolean NOT NULL - 标记是否已删除 - deleted_time: timestamp without time zone NULL - 记录删除时间 - deleted_id: integer NULL - 记录删除人ID ### 后端模板:排除软删除字段(预防性修复) **文件**: model.py.j2, schema.py.j2 虽然之前前端模板没有软删除字段,但为了配合前端修复,需要确保后端模板正确排除这些字段。 - **model.py.j2**: 在排除列表中添加 is_deleted, deleted_time, deleted_id - 原排除列表: ['id', 'uuid', 'status', 'description', 'created_time', 'updated_time', 'created_id', 'updated_id'] - 新排除列表: 添加 'is_deleted', 'deleted_time', 'deleted_id' - 原因: 这些字段由 ModelMixin 和 UserMixin 提供,不应在生成的模型中重复定义 - **schema.py.j2**: 在排除列表中添加 is_deleted, deleted_time, deleted_id - 原排除列表: ['uuid', 'created_time', 'updated_time', 'created_id', 'updated_id'] - 新排除列表: 添加 'is_deleted', 'deleted_time', 'deleted_id' - 原因: 软删除字段由系统自动管理,不应出现在新增/更新Schema中 ## 技术说明 ### 软删除机制 软删除(逻辑删除)是一种不物理删除数据的删除方式: - **is_deleted**: 标记记录是否已删除(false=未删除, true=已删除) - **deleted_time**: 记录删除时间,用于审计和数据恢复 - **deleted_id**: 记录删除操作人ID,外键关联sys_user表 ### 字段继承关系 生成的模型继承自两个基类: - **ModelMixin**: 提供 id, uuid, status, description, created_time, updated_time, is_deleted, deleted_time - **UserMixin**: 提供 created_id, updated_id, deleted_id 及对应的关联关系 代码生成器应排除这些字段,避免重复定义。 ## 修复效果 ### 修复前 - 前端模板生成的表缺少软删除字段 ❌ - 后端模板排除列表不完整(虽然暂时没问题,因为前端也没生成这些字段) ### 修复后 - 前端模板生成的表包含完整的软删除字段 ✅ - 后端模板正确排除软删除字段,避免重复定义 ✅ - 前后端配合,生成的代码正确继承基类的软删除功能 ✅ ## 影响范围 - ✅ 使用\"单表·MySQL\"或\"单表·PostgreSQL\"模板创建的表自动包含软删除字段 - ✅ 生成的model.py只包含业务字段,不会重复定义基础字段 - ✅ 所有新生成的模型自动支持软删除功能 - ✅ 与现有系统的软删除机制保持一致" --- .../module_generator/gencode/templates/python/model.py.j2 | 4 ++-- .../module_generator/gencode/templates/python/schema.py.j2 | 2 +- .../gencode/utils/createTableVisualPresets.ts | 6 ++++++ 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/backend/app/plugin/module_generator/gencode/templates/python/model.py.j2 b/backend/app/plugin/module_generator/gencode/templates/python/model.py.j2 index c6b075d0..7f535c65 100644 --- a/backend/app/plugin/module_generator/gencode/templates/python/model.py.j2 +++ b/backend/app/plugin/module_generator/gencode/templates/python/model.py.j2 @@ -18,7 +18,7 @@ class {{ class_name }}Model(ModelMixin, UserMixin): {% if not is_sub_entity %} {% for column in columns %} - {% if column.column_name not in ['id', 'uuid', 'status', 'description', 'created_time', 'updated_time', 'created_id', 'updated_id'] %} + {% if column.column_name not in ['id', 'uuid', 'status', 'description', 'created_time', 'updated_time', 'created_id', 'updated_id', 'is_deleted', 'deleted_time', 'deleted_id'] %} {% set sqlalchemy_type = column|get_sqlalchemy_type %} {{ column.column_name }}: Mapped[{{ column.python_type }} | None] = mapped_column({{ sqlalchemy_type }}, {% if column.is_pk %}primary_key=True, {% endif %}{% if column.is_increment %}autoincrement=True, {% endif %}{% if (not column.is_nullable) or column.is_pk %}nullable=False{% else %}nullable=True{% endif %}, comment='{{ column.column_comment }}') {% endif %} @@ -29,7 +29,7 @@ class {{ class_name }}Model(ModelMixin, UserMixin): {% endif %} {% else %} {% for column in columns %} - {% if column.column_name not in ['id', 'uuid', 'status', 'description', 'created_time', 'updated_time', 'created_id', 'updated_id'] %} + {% if column.column_name not in ['id', 'uuid', 'status', 'description', 'created_time', 'updated_time', 'created_id', 'updated_id', 'is_deleted', 'deleted_time', 'deleted_id'] %} {% set sqlalchemy_type = column|get_sqlalchemy_type %} {% if column.column_name == sub_table_fk_name %} {{ column.column_name }}: Mapped[{{ column.python_type }} | None] = mapped_column({{ sqlalchemy_type }}, ForeignKey('{{ parent_table_name }}.{{ parent_pk_column_name }}', ondelete='CASCADE'), {% if column.is_pk %}primary_key=True, {% endif %}{% if column.is_increment %}autoincrement=True, {% endif %}{% if (not column.is_nullable) or column.is_pk %}nullable=False{% else %}nullable=True{% endif %}, comment='{{ column.column_comment }}') diff --git a/backend/app/plugin/module_generator/gencode/templates/python/schema.py.j2 b/backend/app/plugin/module_generator/gencode/templates/python/schema.py.j2 index 581300a4..dff37f54 100644 --- a/backend/app/plugin/module_generator/gencode/templates/python/schema.py.j2 +++ b/backend/app/plugin/module_generator/gencode/templates/python/schema.py.j2 @@ -17,7 +17,7 @@ class {{ class_name }}CreateSchema(BaseModel): {{ function_name }}新增模型 """ {% for column in columns %} - {% if column.column_name not in ['uuid', 'created_time', 'updated_time', 'created_id', 'updated_id'] and column.column_name != pk_column_name %} + {% if column.column_name not in ['uuid', 'created_time', 'updated_time', 'created_id', 'updated_id', 'is_deleted', 'deleted_time', 'deleted_id'] and column.column_name != pk_column_name %} {% if column.column_name == 'status' %} {{ column.column_name }}: {{ column.python_type }} = Field(default="0", description='{{ column.column_comment }}') {% elif column.column_name == 'description' %} diff --git a/frontend/src/views/module_generator/gencode/utils/createTableVisualPresets.ts b/frontend/src/views/module_generator/gencode/utils/createTableVisualPresets.ts index 47047c64..8be69df7 100644 --- a/frontend/src/views/module_generator/gencode/utils/createTableVisualPresets.ts +++ b/frontend/src/views/module_generator/gencode/utils/createTableVisualPresets.ts @@ -34,6 +34,9 @@ function mixinMysql(): ColDef[] { }, { name: "created_id", type: "int", nullable: true, isPk: false, comment: "创建人ID" }, { name: "updated_id", type: "int", nullable: true, isPk: false, comment: "更新人ID" }, + { name: "is_deleted", type: "tinyint(1)", nullable: false, isPk: false, comment: "是否已删除(0:未删除 1:已删除)" }, + { name: "deleted_time", type: "datetime", nullable: true, isPk: false, comment: "删除时间" }, + { name: "deleted_id", type: "int", nullable: true, isPk: false, comment: "删除人ID" }, ]; } @@ -63,6 +66,9 @@ function mixinPostgres(): ColDef[] { }, { name: "created_id", type: "integer", nullable: true, isPk: false, comment: "创建人ID" }, { name: "updated_id", type: "integer", nullable: true, isPk: false, comment: "更新人ID" }, + { name: "is_deleted", type: "boolean", nullable: false, isPk: false, comment: "是否已删除(0:未删除 1:已删除)" }, + { name: "deleted_time", type: "timestamp without time zone", nullable: true, isPk: false, comment: "删除时间" }, + { name: "deleted_id", type: "integer", nullable: true, isPk: false, comment: "删除人ID" }, ]; }