feat: add backend rule group and permission support

This commit is contained in:
wren
2026-05-06 09:40:37 +08:00
parent 7acbe0f1d9
commit 76ba7e65ed
45 changed files with 6175 additions and 110 deletions
@@ -0,0 +1,38 @@
from typing import Any
from pydantic import BaseModel, Field
class EvaluationPointBaseDTO(BaseModel):
name: str | None = Field(None, description="评查点名称")
code: str | None = Field(None, description="评查点编码")
risk: str | None = Field(None, description="风险等级")
is_enabled: bool | None = Field(None, description="是否启用")
description: str | None = Field(None, description="评查点描述")
evaluation_point_groups_id: int | None = Field(None, description="二级分组ID")
evaluation_point_groups_pid: int | None = Field(None, description="一级分组ID")
document_attribute_type: str | None = Field(None, description="适用属性类型")
references_laws: dict[str, Any] | None = Field(None, description="法律依据")
extraction_config: dict[str, Any] | None = Field(None, description="抽取配置")
evaluation_config: dict[str, Any] | None = Field(None, description="评查配置")
pass_message: str | None = Field(None, description="通过提示")
fail_message: str | None = Field(None, description="不通过提示")
suggestion_message: str | None = Field(None, description="建议提示")
suggestion_message_type: str | None = Field(None, description="建议提示类型")
post_action: str | None = Field(None, description="后置动作")
action_config: str | None = Field(None, description="动作配置")
score: float | int | None = Field(None, description="分值")
area: str | None = Field(None, description="地区")
class EvaluationPointCreateDTO(EvaluationPointBaseDTO):
name: str = Field(..., description="评查点名称")
code: str = Field(..., description="评查点编码")
risk: str = Field(..., description="风险等级")
is_enabled: bool = Field(True, description="是否启用")
evaluation_point_groups_id: int = Field(..., description="二级分组ID")
evaluation_point_groups_pid: int = Field(..., description="一级分组ID")
class EvaluationPointUpdateDTO(EvaluationPointBaseDTO):
pass
@@ -0,0 +1,63 @@
from pydantic import BaseModel, Field
class EvaluationPointGroupCreateDTO(BaseModel):
"""创建评查点分组请求。"""
name: str = Field(..., description="分组名称")
code: str = Field(..., description="分组编码")
pid: int | None = Field(None, description="父分组ID,空或 0 表示一级业务分组")
description: str | None = Field(None, description="分组描述")
document_type_id: int | None = Field(None, description="关联文档类型ID;一级通常留空仅用于兼容旧数据,二级需绑定具体文档类型")
entry_module_id: int | None = Field(None, description="关联入口模块ID;一级业务分组可绑定,允许后补")
sort_order: int = Field(0, description="排序")
is_enabled: bool = Field(True, description="是否启用")
class EvaluationPointGroupUpdateDTO(BaseModel):
"""更新评查点分组请求。"""
name: str | None = Field(None, description="分组名称")
code: str | None = Field(None, description="分组编码")
pid: int | None = Field(None, description="父分组ID,空或 0 表示一级业务分组")
description: str | None = Field(None, description="分组描述")
document_type_id: int | None = Field(None, description="关联文档类型ID;一级通常留空仅用于兼容旧数据,二级需绑定具体文档类型")
entry_module_id: int | None = Field(None, description="关联入口模块ID;一级业务分组可绑定,允许后补")
sort_order: int | None = Field(None, description="排序")
is_enabled: bool | None = Field(None, description="是否启用")
class EvaluationPointGroupRebindDTO(BaseModel):
"""文档类型分组换绑请求。"""
new_parent_id: int = Field(..., ge=1, description="新的文档类型分组ID")
class EvaluationPointGroupBatchStatusDTO(BaseModel):
"""批量更新状态请求。"""
ids: list[int] = Field(default_factory=list, description="分组ID列表")
is_enabled: bool = Field(..., description="目标启用状态")
class EvaluationPointGroupBatchDeleteDTO(BaseModel):
"""批量删除分组请求。"""
ids: list[int] = Field(default_factory=list, description="分组ID列表")
class EvaluationPointGroupBindingCreateDTO(BaseModel):
"""规则组绑定创建请求。"""
rule_set_id: int = Field(..., ge=1, description="规则集ID")
priority: int = Field(0, description="优先级")
is_active: bool = Field(True, description="是否启用")
note: str | None = Field(None, description="备注")
class EvaluationPointGroupBindingUpdateDTO(BaseModel):
"""规则组绑定更新请求。"""
priority: int | None = Field(None, description="优先级")
is_active: bool | None = Field(None, description="是否启用")
note: str | None = Field(None, description="备注")
@@ -0,0 +1,28 @@
from typing import Any
from pydantic import BaseModel, Field
class PromptTemplateBaseDTO(BaseModel):
template_name: str | None = Field(None, description='模板名称')
template_code: str | None = Field(None, description='模板code')
template_type: str | None = Field(None, description='模板类型')
description: str | None = Field(None, description='模板描述')
template_content: str | None = Field(None, description='模板内容')
template_abbreviation: str | None = Field(None, description='模板简称')
variables: dict[str, Any] | None = Field(None, description='变量定义')
status: int | None = Field(None, description='状态')
version: str | None = Field(None, description='版本')
created_by: int | None = Field(None, description='创建人ID')
class PromptTemplateCreateDTO(PromptTemplateBaseDTO):
template_name: str = Field(..., description='模板名称')
template_type: str = Field(..., description='模板类型')
template_content: str = Field(..., description='模板内容')
status: int = Field(1, description='状态')
version: str = Field('v1.0', description='版本')
class PromptTemplateUpdateDTO(PromptTemplateBaseDTO):
pass
@@ -44,6 +44,16 @@ class RolePermissionsBatchDTO(BaseModel):
role_id: int = Field(..., description="角色ID")
permissions: list[RolePermissionConfigDTO] = Field(default_factory=list, description="权限列表")
replace: bool = Field(False, description="是否替换当前角色已有权限")
replace_scope_permission_ids: list[int] = Field(default_factory=list, description="替换模式下仅允许清理的权限ID范围")
class RoleAccessSaveDTO(BaseModel):
"""角色菜单与接口权限联合保存请求。"""
route_ids: list[int] = Field(default_factory=list, description="启用路由ID列表")
permission_ids: list[int] = Field(default_factory=list, description="启用接口权限ID列表")
route_permission: str = Field("RW", description="路由授权类型")
replace_scope_permission_ids: list[int] = Field(default_factory=list, description="允许本次替换清理的权限ID范围")
class UserRolesAssignDTO(BaseModel):
@@ -0,0 +1,43 @@
"""规则分组 DTO。"""
from pydantic import BaseModel, Field
class RuleGroupCreateDTO(BaseModel):
"""创建规则分组。"""
name: str = Field(..., description="分组名称")
code: str = Field(..., description="分组编码")
pid: int | None = Field(None, description="父分组ID,空或0表示一级分组")
description: str | None = Field(None, description="分组描述")
documentTypeId: int | None = Field(None, description="关联文档类型ID,仅二级分组使用")
isEnabled: bool = Field(True, description="是否启用")
sortOrder: int = Field(0, description="排序")
class RuleGroupUpdateDTO(BaseModel):
"""更新规则分组。"""
name: str | None = Field(None, description="分组名称")
code: str | None = Field(None, description="分组编码")
description: str | None = Field(None, description="分组描述")
documentTypeId: int | None = Field(None, description="关联文档类型ID")
isEnabled: bool | None = Field(None, description="是否启用")
sortOrder: int | None = Field(None, description="排序")
class RuleGroupBindingCreateDTO(BaseModel):
"""创建规则组绑定。"""
ruleSetId: int = Field(..., description="规则集ID")
priority: int = Field(0, description="优先级")
isActive: bool = Field(True, description="是否启用")
note: str | None = Field(None, description="备注")
class RuleGroupBindingUpdateDTO(BaseModel):
"""更新规则组绑定。"""
priority: int | None = Field(None, description="优先级")
isActive: bool | None = Field(None, description="是否启用")
note: str | None = Field(None, description="备注")
@@ -18,6 +18,7 @@ class DocumentUploadVO(BaseModel):
fileId: int = Field(..., description="文档文件ID")
typeId: int = Field(..., description="文档类型ID")
typeCode: str = Field(..., description="文档类型编码")
groupId: int | None = Field(None, description="命中的二级分组ID")
region: str = Field(..., description="所属地区")
fileName: str = Field(..., description="文件名")
ossUrl: str = Field(..., description="OSS 对象路径")
@@ -27,6 +28,16 @@ class DocumentUploadVO(BaseModel):
run: AuditRunVO | None = Field(None, description="自动触发后的运行信息")
class DocumentStatusItemVO(BaseModel):
"""文档状态项。"""
documentId: int = Field(..., description="文档ID")
processingStatus: str | None = Field(None, description="处理状态")
runStatus: str | None = Field(None, description="当前运行状态")
resultStatus: str | None = Field(None, description="当前结果状态")
updatedAt: str | None = Field(None, description="更新时间")
class DocumentHistoryVersionVO(BaseModel):
"""历史版本摘要。"""
@@ -41,6 +52,20 @@ class DocumentHistoryVersionVO(BaseModel):
updatedAt: str | None = Field(None, description="更新时间")
class DocumentAttachmentVO(BaseModel):
"""文档附件项。"""
fileId: int = Field(..., description="附件文件ID")
fileName: str = Field(..., description="附件文件名")
fileExt: str | None = Field(None, description="附件扩展名")
mimeType: str | None = Field(None, description="附件 MIME 类型")
fileSize: int | None = Field(None, description="附件文件大小")
fileRole: str = Field(..., description="文件角色")
ossUrl: str | None = Field(None, description="附件 OSS 路径")
createdBy: int | None = Field(None, description="上传人")
createdAt: str | None = Field(None, description="上传时间")
class DocumentListItemVO(BaseModel):
"""文档列表项。"""
@@ -52,6 +77,9 @@ class DocumentListItemVO(BaseModel):
previousVersionId: int | None = Field(None, description="上一版本文档ID")
typeId: int | None = Field(None, description="文档类型ID")
typeCode: str | None = Field(None, description="文档类型编码")
typeName: str | None = Field(None, description="文档类型名称")
groupId: int | None = Field(None, description="命中的二级分组ID")
groupName: str | None = Field(None, description="二级分组名称")
region: str = Field(..., description="区域")
normalizedName: str | None = Field(None, description="归一化名称")
fileId: int | None = Field(None, description="文件ID")
@@ -68,12 +96,23 @@ class DocumentListItemVO(BaseModel):
passedCount: int | None = Field(None, description="通过数")
failedCount: int | None = Field(None, description="失败数")
skippedCount: int | None = Field(None, description="跳过数")
documentNumber: str | None = Field(None, description="业务文号/案号")
auditStatus: int | None = Field(None, description="人工维护审核状态")
isTestDocument: bool = Field(False, description="是否测试文档")
updatedAt: str | None = Field(None, description="更新时间")
hasHistory: bool = Field(False, description="是否存在历史版本")
totalVersions: int = Field(1, description="总版本数")
historyVersions: list[DocumentHistoryVersionVO] = Field(default_factory=list, description="历史版本摘要")
class DocumentDetailVO(DocumentListItemVO):
"""文档详情。"""
remark: str | None = Field(None, description="备注")
pageCount: int | None = Field(None, description="页数,暂无精确值时可为空")
attachments: list[DocumentAttachmentVO] = Field(default_factory=list, description="附件列表")
class DocumentTypeItemVO(BaseModel):
"""文档类型列表项。"""
@@ -117,3 +156,12 @@ class DocumentListPageVO(BaseModel):
pageSize: int = Field(..., description="每页数量")
totalPages: int = Field(..., description="总页数")
documents: list[DocumentListItemVO] = Field(default_factory=list, description="文档列表")
class DocumentUpdateDTO(BaseModel):
"""文档元数据更新请求。"""
documentNumber: str | None = Field(None, description="业务文号/案号")
auditStatus: int | None = Field(None, description="人工维护审核状态(若表结构支持则写入)")
isTestDocument: bool | None = Field(None, description="是否测试文档")
remark: str | None = Field(None, description="备注")
@@ -0,0 +1,99 @@
from pydantic import BaseModel, Field
class RuleGroupBindingVO(BaseModel):
"""二级分组下的规则集绑定。"""
id: int = Field(..., description="绑定ID")
group_id: int = Field(..., description="分组ID")
rule_set_id: int = Field(..., description="规则集ID")
rule_type_binding_id: int | None = Field(None, description="镜像的运行时绑定ID")
priority: int = Field(0, description="优先级")
is_active: bool = Field(True, description="是否启用")
note: str | None = Field(None, description="备注")
rule_type: str | None = Field(None, description="规则类型编码")
rule_name: str | None = Field(None, description="规则集名称")
current_version_id: int | None = Field(None, description="当前版本ID")
fallback_version_id: int | None = Field(None, description="回退版本ID")
has_usable_version: bool = Field(False, description="是否存在可用版本")
usable_rule_count: int = Field(0, description="可用规则数")
class EvaluationPointGroupVO(BaseModel):
"""评查点分组详情。"""
id: int = Field(..., description="分组ID")
pid: int | None = Field(None, description="父分组ID")
name: str = Field(..., description="分组名称")
code: str = Field(..., description="分组编码")
description: str | None = Field(None, description="分组描述")
document_type_id: int | None = Field(None, description="关联文档类型ID")
document_type_name: str | None = Field(None, description="关联文档类型名称")
entry_module_id: int | None = Field(None, description="入口模块ID")
entry_module_name: str | None = Field(None, description="入口模块名称")
sort_order: int = Field(0, description="排序")
is_enabled: bool = Field(True, description="是否启用")
created_at: str | None = Field(None, description="创建时间")
updated_at: str | None = Field(None, description="更新时间")
rule_count: int | None = Field(None, description="绑定的规则集数量")
bindings: list[RuleGroupBindingVO] = Field(default_factory=list, description="二级分组绑定的规则集")
children: list["EvaluationPointGroupVO"] | None = Field(None, description="子分组")
class EvaluationPointGroupListVO(BaseModel):
"""评查点分组列表分页。"""
data: list[EvaluationPointGroupVO] = Field(default_factory=list, description="分组列表")
total: int = Field(0, description="总数")
page: int = Field(1, description="页码")
page_size: int = Field(20, description="分页大小")
class DocTypeInfoVO(BaseModel):
"""换绑提示中的文档类型信息。"""
id: int = Field(..., description="文档类型ID")
name: str = Field(..., description="文档类型名称")
class EvaluationPointGroupDeleteVO(BaseModel):
"""删除分组响应。"""
success: bool = Field(..., description="是否成功")
message: str | None = Field(None, description="提示信息")
deleted_count: int | None = Field(None, description="兼容字段")
deleted_groups: int | None = Field(None, description="删除的分组数")
deleted_points: int | None = Field(None, description="兼容旧字段:已删除绑定数")
need_rebind: bool = Field(False, description="是否需要先换绑")
points_count: int | None = Field(None, description="兼容旧字段")
single_bound_doc_types: list[DocTypeInfoVO] = Field(default_factory=list, description="兼容旧字段")
multi_bound_doc_types: list[DocTypeInfoVO] = Field(default_factory=list, description="兼容旧字段")
class EvaluationPointGroupRebindVO(BaseModel):
"""换绑结果。"""
success: bool = Field(..., description="是否成功")
message: str = Field(..., description="结果消息")
rebind_count: int = Field(0, description="迁移的二级分组数量")
doc_types_updated: int = Field(0, description="兼容字段")
class EvaluationPointGroupBatchStatusVO(BaseModel):
"""批量更新状态结果。"""
success: bool = Field(..., description="是否成功")
updated_count: int = Field(0, description="更新数量")
message: str = Field(..., description="结果消息")
class EvaluationPointGroupBatchDeleteVO(BaseModel):
"""批量删除结果。"""
success: bool = Field(..., description="是否成功")
deleted_groups: int = Field(0, description="删除的分组数量")
deleted_points: int = Field(0, description="兼容旧字段:删除的绑定数量")
message: str = Field(..., description="结果消息")
EvaluationPointGroupVO.model_rebuild()
@@ -0,0 +1,52 @@
from typing import Any
from pydantic import BaseModel, Field
class EvaluationPointVO(BaseModel):
id: int = Field(..., description="评查点ID")
code: str = Field(..., description="评查点编码")
name: str = Field(..., description="评查点名称")
evaluation_point_groups_id: int | None = Field(None, description="二级分组ID")
evaluation_point_groups_pid: int | None = Field(None, description="一级分组ID")
ruleType: str = Field("", description="一级分组名称")
groupName: str = Field("", description="二级分组名称")
groupId: str = Field("", description="二级分组ID字符串")
risk: str = Field("", description="风险等级")
description: str = Field("", description="评查点描述")
is_enabled: bool = Field(True, description="是否启用")
document_attribute_type: str = Field("通用", description="适用属性类型")
references_laws: dict[str, Any] = Field(default_factory=dict, description="法律依据")
extraction_config: dict[str, Any] = Field(default_factory=dict, description="抽取配置")
evaluation_config: dict[str, Any] = Field(default_factory=dict, description="评查配置")
pass_message: str = Field("", description="通过提示")
fail_message: str = Field("", description="不通过提示")
suggestion_message: str = Field("", description="建议提示")
suggestion_message_type: str = Field("warning", description="建议提示类型")
post_action: str = Field("none", description="后置动作")
action_config: str = Field("", description="动作配置")
score: float = Field(0, description="分值")
area: str = Field("", description="地区")
created_at: str | None = Field(None, description="创建时间")
updated_at: str | None = Field(None, description="更新时间")
class EvaluationPointListVO(BaseModel):
data: list[EvaluationPointVO] = Field(default_factory=list, description="评查点列表")
total: int = Field(0, description="总数")
page: int = Field(1, description="页码")
page_size: int = Field(20, description="分页大小")
class EvaluationPointDeleteVO(BaseModel):
success: bool = Field(..., description="是否成功")
message: str = Field(..., description="结果消息")
class AttributeTypeVO(BaseModel):
code: str = Field(..., description="属性类型编码")
label: str = Field(..., description="属性类型名称")
class AttributeTypeListVO(BaseModel):
types: list[AttributeTypeVO] = Field(default_factory=list, description="属性类型列表")
@@ -0,0 +1,37 @@
from typing import Any
from pydantic import BaseModel, Field
class PromptTemplateVO(BaseModel):
id: int = Field(..., description='模板ID')
template_name: str = Field(..., description='模板名称')
template_code: str | None = Field(None, description='模板code')
template_type: str = Field(..., description='模板类型')
description: str | None = Field(None, description='模板描述')
template_content: str = Field(..., description='模板内容')
template_abbreviation: str | None = Field(None, description='模板简称')
variables: dict[str, Any] = Field(default_factory=dict, description='变量定义')
status: int = Field(0, description='状态')
version: str = Field('v1.0', description='版本')
created_by: int | None = Field(None, description='创建人ID')
created_by_username: str | None = Field(None, description='创建人用户名')
created_at: str = Field('', description='创建时间')
updated_at: str = Field('', description='更新时间')
class PromptTemplateListVO(BaseModel):
total: int = Field(0, description='总数')
page: int = Field(1, description='页码')
page_size: int = Field(20, description='分页大小')
items: list[PromptTemplateVO] = Field(default_factory=list, description='模板列表')
class PromptTemplateTypeOptionVO(BaseModel):
value: str = Field(..., description='类型值')
label: str = Field(..., description='类型名称')
count: int = Field(0, description='数量')
class PromptTemplateTypeListVO(BaseModel):
items: list[PromptTemplateTypeOptionVO] = Field(default_factory=list, description='模板类型列表')
@@ -131,6 +131,14 @@ class RolePermissionsVO(BaseModel):
permissions: list[RolePermissionDetailVO] = Field(default_factory=list, description="权限列表")
class RoleAccessSaveVO(BaseModel):
"""角色菜单与接口权限联合保存响应。"""
role_id: int = Field(..., description="角色ID")
route_result: RoleRouteUpdateResultVO = Field(..., description="菜单保存结果")
permission_result: RolePermissionsVO = Field(..., description="接口权限保存结果")
class UserRolesVO(BaseModel):
"""用户角色响应。"""
@@ -0,0 +1,27 @@
"""规则配置页聚合 VO。"""
from pydantic import BaseModel, Field
class RuleConfigPackVO(BaseModel):
"""规则配置页的单个 pack。"""
packId: int = Field(..., description="pack 标识,当前等于二级分组ID")
groupId: int = Field(..., description="二级分组ID")
rootGroupId: int | None = Field(None, description="一级分组ID")
bindingId: int | None = Field(None, description="当前命中的规则集绑定ID")
ruleSetId: int | None = Field(None, description="命中的规则集ID")
ruleType: str | None = Field(None, description="规则类型编码")
ruleName: str | None = Field(None, description="规则集名称")
currentVersionId: int | None = Field(None, description="规则集当前版本ID")
fallbackVersionId: int | None = Field(None, description="规则集回退版本ID")
resolvedVersionId: int | None = Field(None, description="当前实际使用的版本ID")
hasUsableVersion: bool = Field(False, description="是否存在可用规则版本")
usableRuleCount: int = Field(0, description="可用规则数")
documentTypeId: int | None = Field(None, description="文档类型ID")
documentType: str = Field("", description="文档类型名称")
moduleType: str = Field("", description="模块名称")
mainType: str = Field("", description="一级业务类型名称")
subtype: str = Field("", description="二级业务子类型名称")
yamlText: str = Field("", description="当前规则 YAML 正文")
sourceStatus: str = Field(..., description="ready/empty/missing")
@@ -11,6 +11,9 @@ class RuleSetVO(BaseModel):
ruleName: str = Field(..., description="规则集名称")
domainType: str | None = Field(None, description="域类型")
currentVersionId: int | None = Field(None, description="当前激活版本ID")
fallbackVersionId: int | None = Field(None, description="最近一个可回退使用的已发布版本ID")
hasUsableVersion: bool = Field(False, description="是否存在可用于上传评查的规则版本")
usableRuleCount: int = Field(0, description="当前可用于上传评查的规则数")
status: str = Field(..., description="draft/active/inactive/archived")