# 灵越智报 2.0 - 数据库设计文档(定稿) > **版本**: v1.0-final > **定稿时间**: 2026-02-12 > **设计原则**: 简化单层项目结构,前端只关心"项目"概念 > **数据库**: PostgreSQL 15+ > **初始化脚本**: `init_mock_new.sql` --- ## 一、整体架构 ### 1.1 设计思想 采用**关系型数据库实现图数据库**的思路: - **节点(Node)**: 所有业务实体均为节点,通过 `node_type` 区分 - **关系(Edge)**: 节点间的关联通过边表示,通过 `edge_type` 区分 - **属性(Property)**: 节点和边的属性通过 KV 表存储,支持动态扩展 - **视图(View)**: 通过数据库视图将图结构映射为业务友好的查询接口 ### 1.2 表分类 | 分类 | 表名前缀 | 数量 | 说明 | |------|----------|------|------| | 前端业务支撑表 | `sys_*` | 13张 | 用户、角色、权限、字典、日志等 | | 核心图结构表 | `nodes`, `edges`, `*_properties` | 7张 | 节点、关系、属性、类型定义 | | 业务视图 | `v_*` | 7个 | 项目、要素、值、附件、实体、规则等 | ### 1.3 数据模型概览 ``` PROJECT (项目) ├── HAS_ELEMENT ──→ ELEMENT (要素定义) ├── HAS_VALUE ────→ VALUE (要素值) ──FOR_ELEMENT──→ ELEMENT ├── HAS_ATTACHMENT → ATTACHMENT (附件) │ └── HAS_ENTITY ──→ ENTITY (实体) ├── HAS_RULE ────→ RULE (规则) │ ├── FOR_ELEMENT ──→ ELEMENT │ └── INPUT_FROM ──→ ENTITY / ATTACHMENT / VALUE └── COPIED_FROM ──→ PROJECT (复制来源) ``` --- ## 二、前端业务支撑表(sys_* 系列) ### 2.1 sys_users - 用户表 | 字段 | 类型 | 约束 | 说明 | |------|------|------|------| | id | BIGSERIAL | PK | 主键 | | node_id | BIGINT | | 关联 nodes 表(可选) | | username | VARCHAR(100) | NOT NULL, UNIQUE | 用户名 | | password_hash | VARCHAR(255) | NOT NULL | 密码哈希(BCrypt) | | salt | VARCHAR(50) | | 盐值 | | email | VARCHAR(200) | | 邮箱 | | phone | VARCHAR(20) | | 手机号 | | avatar | VARCHAR(500) | | 头像URL | | real_name | VARCHAR(100) | | 真实姓名 | | department | VARCHAR(200) | | 部门 | | position | VARCHAR(100) | | 职位 | | status | VARCHAR(20) | DEFAULT 'active' | 状态:active/disabled | | last_login_at | TIMESTAMP | | 最后登录时间 | | last_login_ip | VARCHAR(50) | | 最后登录IP | | login_count | INT | DEFAULT 0 | 登录次数 | | created_at | TIMESTAMP | DEFAULT NOW() | 创建时间 | | updated_at | TIMESTAMP | DEFAULT NOW() | 更新时间 | **索引**: - `idx_sys_users_username` ON (username) - `idx_sys_users_node` ON (node_id) --- ### 2.2 sys_sessions - 会话表 | 字段 | 类型 | 约束 | 说明 | |------|------|------|------| | id | BIGSERIAL | PK | 主键 | | user_id | BIGINT | NOT NULL, FK→sys_users | 用户ID | | session_token | VARCHAR(255) | NOT NULL, UNIQUE | 会话Token | | refresh_token | VARCHAR(255) | | 刷新Token | | device_type | VARCHAR(50) | | 设备类型:web/mobile/desktop | | device_info | TEXT | | 设备信息 | | ip_address | VARCHAR(50) | | IP地址 | | user_agent | TEXT | | User-Agent | | expires_at | TIMESTAMP | NOT NULL | 过期时间 | | created_at | TIMESTAMP | DEFAULT NOW() | 创建时间 | | updated_at | TIMESTAMP | DEFAULT NOW() | 更新时间 | **索引**: - `idx_sys_sessions_user` ON (user_id) - `idx_sys_sessions_token` ON (session_token) --- ### 2.3 sys_login_logs - 登录日志表 | 字段 | 类型 | 约束 | 说明 | |------|------|------|------| | id | BIGSERIAL | PK | 主键 | | user_id | BIGINT | FK→sys_users (SET NULL) | 用户ID | | username | VARCHAR(100) | | 用户名(冗余) | | login_type | VARCHAR(20) | | 登录类型:password/token/sso | | ip_address | VARCHAR(50) | | IP地址 | | user_agent | TEXT | | User-Agent | | device_type | VARCHAR(50) | | 设备类型 | | location | VARCHAR(200) | | 登录地点 | | status | VARCHAR(20) | NOT NULL | 状态:success/failed | | message | TEXT | | 消息(失败原因等) | | created_at | TIMESTAMP | DEFAULT NOW() | 创建时间 | **索引**: - `idx_sys_login_logs_user` ON (user_id) - `idx_sys_login_logs_created` ON (created_at DESC) --- ### 2.4 sys_roles - 角色表 | 字段 | 类型 | 约束 | 说明 | |------|------|------|------| | id | SERIAL | PK | 主键 | | role_code | VARCHAR(50) | NOT NULL, UNIQUE | 角色编码 | | role_name | VARCHAR(100) | NOT NULL | 角色名称 | | description | TEXT | | 描述 | | sort_order | INT | DEFAULT 0 | 排序 | | status | VARCHAR(20) | DEFAULT 'active' | 状态 | | created_by | BIGINT | | 创建人 | | created_at | TIMESTAMP | DEFAULT NOW() | 创建时间 | | updated_at | TIMESTAMP | DEFAULT NOW() | 更新时间 | **索引**: - `idx_sys_roles_code` ON (role_code) --- ### 2.5 sys_permissions - 权限表 | 字段 | 类型 | 约束 | 说明 | |------|------|------|------| | id | SERIAL | PK | 主键 | | perm_code | VARCHAR(100) | NOT NULL, UNIQUE | 权限编码 | | perm_name | VARCHAR(200) | NOT NULL | 权限名称 | | perm_type | VARCHAR(20) | NOT NULL | 类型:menu/button/api | | parent_id | INT | FK→sys_permissions | 父级ID | | path | VARCHAR(500) | | 路由路径 | | icon | VARCHAR(100) | | 图标 | | component | VARCHAR(200) | | 前端组件路径 | | sort_order | INT | DEFAULT 0 | 排序 | | status | VARCHAR(20) | DEFAULT 'active' | 状态 | | created_at | TIMESTAMP | DEFAULT NOW() | 创建时间 | **索引**: - `idx_sys_permissions_parent` ON (parent_id) - `idx_sys_permissions_type` ON (perm_type) --- ### 2.6 sys_user_roles - 用户角色关联表 | 字段 | 类型 | 约束 | 说明 | |------|------|------|------| | id | SERIAL | PK | 主键 | | user_id | BIGINT | NOT NULL, FK→sys_users | 用户ID | | role_id | INT | NOT NULL, FK→sys_roles | 角色ID | | created_at | TIMESTAMP | DEFAULT NOW() | 创建时间 | **约束**: UNIQUE(user_id, role_id) --- ### 2.7 sys_role_permissions - 角色权限关联表 | 字段 | 类型 | 约束 | 说明 | |------|------|------|------| | id | SERIAL | PK | 主键 | | role_id | INT | NOT NULL, FK→sys_roles | 角色ID | | permission_id | INT | NOT NULL, FK→sys_permissions | 权限ID | | created_at | TIMESTAMP | DEFAULT NOW() | 创建时间 | **约束**: UNIQUE(role_id, permission_id) --- ### 2.8 sys_configs - 系统配置表 | 字段 | 类型 | 约束 | 说明 | |------|------|------|------| | id | SERIAL | PK | 主键 | | config_key | VARCHAR(100) | NOT NULL, UNIQUE | 配置键 | | config_value | TEXT | | 配置值(文本) | | config_json | JSONB | | 配置值(JSON) | | config_type | VARCHAR(50) | | 值类型:string/number/boolean/json | | description | TEXT | | 描述 | | is_public | BOOLEAN | DEFAULT false | 是否公开(前端可读) | | created_at | TIMESTAMP | DEFAULT NOW() | 创建时间 | | updated_at | TIMESTAMP | DEFAULT NOW() | 更新时间 | --- ### 2.9 sys_dict_types - 数据字典类型表 | 字段 | 类型 | 约束 | 说明 | |------|------|------|------| | id | SERIAL | PK | 主键 | | dict_code | VARCHAR(100) | NOT NULL, UNIQUE | 字典编码 | | dict_name | VARCHAR(200) | NOT NULL | 字典名称 | | description | TEXT | | 描述 | | status | VARCHAR(20) | DEFAULT 'active' | 状态 | | created_at | TIMESTAMP | DEFAULT NOW() | 创建时间 | --- ### 2.10 sys_dict_items - 数据字典项表 | 字段 | 类型 | 约束 | 说明 | |------|------|------|------| | id | SERIAL | PK | 主键 | | dict_type_id | INT | NOT NULL, FK→sys_dict_types | 字典类型ID | | item_code | VARCHAR(100) | NOT NULL | 项编码 | | item_name | VARCHAR(200) | NOT NULL | 项名称 | | item_value | TEXT | | 项值 | | sort_order | INT | DEFAULT 0 | 排序 | | status | VARCHAR(20) | DEFAULT 'active' | 状态 | | extra | JSONB | | 扩展信息 | | created_at | TIMESTAMP | DEFAULT NOW() | 创建时间 | **约束**: UNIQUE(dict_type_id, item_code) --- ### 2.11 sys_operation_logs - 操作日志表 | 字段 | 类型 | 约束 | 说明 | |------|------|------|------| | id | BIGSERIAL | PK | 主键 | | user_id | BIGINT | | 用户ID | | username | VARCHAR(100) | | 用户名 | | module | VARCHAR(100) | | 模块名 | | action | VARCHAR(100) | | 操作名 | | method | VARCHAR(10) | | HTTP方法 | | url | VARCHAR(500) | | 请求URL | | params | TEXT | | 请求参数 | | result | TEXT | | 返回结果 | | ip_address | VARCHAR(50) | | IP地址 | | user_agent | TEXT | | User-Agent | | duration_ms | INT | | 耗时(毫秒) | | status | VARCHAR(20) | | 状态:success/error | | error_msg | TEXT | | 错误信息 | | created_at | TIMESTAMP | DEFAULT NOW() | 创建时间 | **索引**: - `idx_sys_operation_logs_user` ON (user_id) - `idx_sys_operation_logs_created` ON (created_at DESC) --- ### 2.12 sys_files - 文件存储表 | 字段 | 类型 | 约束 | 说明 | |------|------|------|------| | id | BIGSERIAL | PK | 主键 | | file_key | VARCHAR(100) | NOT NULL, UNIQUE | 文件唯一标识 | | original_name | VARCHAR(500) | NOT NULL | 原始文件名 | | storage_name | VARCHAR(200) | NOT NULL | 存储文件名 | | storage_path | VARCHAR(500) | NOT NULL | 存储路径 | | file_type | VARCHAR(100) | | MIME类型 | | file_size | BIGINT | | 文件大小(字节) | | md5_hash | VARCHAR(32) | | MD5哈希 | | storage_type | VARCHAR(20) | DEFAULT 'local' | 存储类型:local/oss/minio | | bucket | VARCHAR(100) | | 存储桶 | | url | VARCHAR(1000) | | 访问URL | | thumbnail_url | VARCHAR(1000) | | 缩略图URL | | uploaded_by | BIGINT | | 上传人 | | created_at | TIMESTAMP | DEFAULT NOW() | 创建时间 | --- ### 2.13 sys_tasks - 异步任务队列表 | 字段 | 类型 | 约束 | 说明 | |------|------|------|------| | id | BIGSERIAL | PK | 主键 | | task_type | VARCHAR(50) | NOT NULL | 任务类型:parse/ner/export | | task_key | VARCHAR(100) | | 任务标识 | | payload | JSONB | | 任务参数 | | status | VARCHAR(20) | DEFAULT 'pending' | 状态:pending/running/success/failed | | priority | INT | DEFAULT 0 | 优先级 | | retry_count | INT | DEFAULT 0 | 已重试次数 | | max_retries | INT | DEFAULT 3 | 最大重试次数 | | result | JSONB | | 执行结果 | | error_msg | TEXT | | 错误信息 | | started_at | TIMESTAMP | | 开始时间 | | finished_at | TIMESTAMP | | 完成时间 | | created_by | BIGINT | | 创建人 | | created_at | TIMESTAMP | DEFAULT NOW() | 创建时间 | | updated_at | TIMESTAMP | DEFAULT NOW() | 更新时间 | **索引**: - `idx_sys_tasks_type` ON (task_type) - `idx_sys_tasks_status` ON (status) - `idx_sys_tasks_created` ON (created_at DESC) --- ## 三、核心图结构表 ### 3.1 node_types - 节点类型定义表 | 字段 | 类型 | 约束 | 说明 | |------|------|------|------| | id | SERIAL | PK | 主键 | | type_code | VARCHAR(50) | NOT NULL, UNIQUE | 类型编码 | | type_name | VARCHAR(100) | NOT NULL | 类型名称 | | description | TEXT | | 描述 | | icon | VARCHAR(100) | | 图标名 | | color | VARCHAR(20) | | 颜色值 | | created_at | TIMESTAMP | DEFAULT NOW() | 创建时间 | **预置数据**: | type_code | type_name | 说明 | |-----------|-----------|------| | PROJECT | 项目 | 智报项目(包含要素定义和内容) | | ELEMENT | 要素 | 项目要素定义 | | VALUE | 要素值 | 要素的具体值 | | ATTACHMENT | 附件 | 项目附件 | | ENTITY | 实体 | NER识别的实体 | | RULE | 规则 | 数据提取规则 | --- ### 3.2 edge_types - 关系类型定义表 | 字段 | 类型 | 约束 | 说明 | |------|------|------|------| | id | SERIAL | PK | 主键 | | type_code | VARCHAR(50) | NOT NULL, UNIQUE | 类型编码 | | type_name | VARCHAR(100) | NOT NULL | 类型名称 | | from_node_type | VARCHAR(50) | | 起始节点类型 | | to_node_type | VARCHAR(50) | | 目标节点类型 | | description | TEXT | | 描述 | | created_at | TIMESTAMP | DEFAULT NOW() | 创建时间 | **预置数据**: | type_code | from → to | 说明 | |-----------|-----------|------| | HAS_ELEMENT | PROJECT → ELEMENT | 项目包含要素定义 | | HAS_VALUE | PROJECT → VALUE | 项目有要素值 | | FOR_ELEMENT | VALUE → ELEMENT | 值对应的要素 | | HAS_ATTACHMENT | PROJECT → ATTACHMENT | 项目有附件 | | HAS_ENTITY | ATTACHMENT → ENTITY | 附件有实体 | | HAS_RULE | PROJECT → RULE | 项目有规则 | | FOR_ELEMENT | RULE → ELEMENT | 规则对应的要素 | | INPUT_FROM | RULE → ENTITY | 规则输入来源(实体) | | INPUT_FROM | RULE → ATTACHMENT | 规则输入来源(附件) | | INPUT_FROM | RULE → VALUE | 规则输入来源(其他值) | | COPIED_FROM | PROJECT → PROJECT | 项目复制来源 | --- ### 3.3 nodes - 节点表(核心) | 字段 | 类型 | 约束 | 说明 | |------|------|------|------| | id | BIGSERIAL | PK | 主键 | | node_type | VARCHAR(50) | NOT NULL | 节点类型(对应 node_types.type_code) | | node_key | VARCHAR(200) | | 业务键(同类型内唯一) | | name | VARCHAR(500) | NOT NULL | 节点名称 | | status | VARCHAR(50) | DEFAULT 'active' | 状态 | | created_by | BIGINT | | 创建人(sys_users.id) | | created_at | TIMESTAMP | DEFAULT NOW() | 创建时间 | | updated_at | TIMESTAMP | DEFAULT NOW() | 更新时间 | **索引**: - `idx_nodes_type` ON (node_type) - `idx_nodes_type_status` ON (node_type, status) - `idx_nodes_key` ON (node_key) - `idx_nodes_type_key` UNIQUE ON (node_type, node_key) WHERE node_key IS NOT NULL - `idx_nodes_created_by` ON (created_by) - `idx_nodes_created_at` ON (created_at DESC) **各节点类型的 node_key 约定**: | node_type | node_key 格式 | 示例 | |-----------|---------------|------| | PROJECT | PRJ-{年份}-{序号} | PRJ-2024-001 | | ELEMENT | {namespace}.{fieldName} | basicInfo.projectCode | | VALUE | {projectKey}:{elementKey} | PRJ-2024-001:basicInfo.projectCode | | ATTACHMENT | ATT-{年份}-{序号} | ATT-2024-001 | | ENTITY | {entityType}:{entityText} | ORG:成都院 | | RULE | {projectKey}:{elementKey} | PRJ-2024-001:basicInfo.projectCode | --- ### 3.4 edges - 关系表(核心) | 字段 | 类型 | 约束 | 说明 | |------|------|------|------| | id | BIGSERIAL | PK | 主键 | | edge_type | VARCHAR(50) | NOT NULL | 关系类型(对应 edge_types.type_code) | | from_node_id | BIGINT | NOT NULL, FK→nodes | 起始节点ID | | to_node_id | BIGINT | NOT NULL, FK→nodes | 目标节点ID | | sort_order | INT | DEFAULT 0 | 排序序号 | | created_at | TIMESTAMP | DEFAULT NOW() | 创建时间 | **索引**: - `idx_edges_type` ON (edge_type) - `idx_edges_from` ON (from_node_id) - `idx_edges_to` ON (to_node_id) - `idx_edges_type_from` ON (edge_type, from_node_id) - `idx_edges_type_to` ON (edge_type, to_node_id) - `idx_edges_unique` UNIQUE ON (edge_type, from_node_id, to_node_id) --- ### 3.5 node_properties - 节点属性表 | 字段 | 类型 | 约束 | 说明 | |------|------|------|------| | id | BIGSERIAL | PK | 主键 | | node_id | BIGINT | NOT NULL, FK→nodes | 节点ID | | prop_key | VARCHAR(100) | NOT NULL | 属性键 | | prop_value | TEXT | | 文本值 | | prop_json | JSONB | | JSON值 | | prop_number | DECIMAL(20,4) | | 数值 | | prop_date | TIMESTAMP | | 日期值 | | created_at | TIMESTAMP | DEFAULT NOW() | 创建时间 | | updated_at | TIMESTAMP | DEFAULT NOW() | 更新时间 | **索引**: - `idx_node_props_node` ON (node_id) - `idx_node_props_unique` UNIQUE ON (node_id, prop_key) - `idx_node_props_key` ON (prop_key) **各节点类型的属性定义**: #### PROJECT 节点属性 | prop_key | 数据类型 | 说明 | |----------|----------|------| | title | prop_value | 项目标题 | | description | prop_value | 项目描述 | | status | prop_value | 状态:draft/in_progress/completed/archived | | template_type | prop_value | 模板类型(如"电力安全生产标准化复审报告") | | content_html | prop_value | 报告内容(HTML格式) | | content_markdown | prop_value | 报告内容(Markdown格式) | #### ELEMENT 节点属性 | prop_key | 数据类型 | 说明 | |----------|----------|------| | element_type | prop_value | 要素类型:text/paragraph/table | | namespace | prop_value | 命名空间(如 basicInfo, schedule, result) | | field_name | prop_value | 字段名(如 projectCode, startDate) | | required | prop_value | 是否必填:true/false | | default_value | prop_value | 默认值 | | description | prop_value | 要素描述 | | table_columns | prop_json | 表格列定义(仅 table 类型) | #### VALUE 节点属性 | prop_key | 数据类型 | 说明 | |----------|----------|------| | value_text | prop_value | 文本值 | | value_json | prop_json | JSON值(表格数据等) | | is_filled | prop_value | 是否已填充:true/false | | fill_source | prop_value | 填充来源:default/manual/rule/ai | #### ATTACHMENT 节点属性 | prop_key | 数据类型 | 说明 | |----------|----------|------| | file_name | prop_value | 文件名 | | file_path | prop_value | 文件路径 | | file_type | prop_value | 文件类型:pdf/docx/xlsx | | file_size | prop_number | 文件大小(字节) | | parse_status | prop_value | 解析状态:pending/parsing/completed/failed | | parsed_text | prop_value | 解析后的文本 | | parsed_at | prop_date | 解析完成时间 | #### ENTITY 节点属性 | prop_key | 数据类型 | 说明 | |----------|----------|------| | entity_type | prop_value | 实体类型:ORG/PERSON/DATE/NUMBER/CODE/LOCATION | | business_label | prop_value | 业务标签(如"评审对象"、"项目编号") | | confidence | prop_number | 置信度(0-1) | | occurrence_count | prop_number | 出现次数 | #### RULE 节点属性 | prop_key | 数据类型 | 说明 | |----------|----------|------| | rule_type | prop_value | 规则类型:direct_entity/extraction/llm/aggregate/dsl | | action_type | prop_value | 动作类型:use_entity_value/regex_extract/llm_generate | | description | prop_value | 规则描述 | | action_config | prop_json | 动作配置 | | dsl_content | prop_value | DSL代码(规则引擎对接,预留) | | last_output_text | prop_value | 最后输出文本 | | last_output_json | prop_json | 最后输出JSON | | last_run_status | prop_value | 最后运行状态:success/failed/pending | | last_run_time | prop_date | 最后运行时间 | | last_run_error | prop_value | 最后运行错误信息 | --- ### 3.6 edge_properties - 关系属性表 | 字段 | 类型 | 约束 | 说明 | |------|------|------|------| | id | BIGSERIAL | PK | 主键 | | edge_id | BIGINT | NOT NULL, FK→edges | 关系ID | | prop_key | VARCHAR(100) | NOT NULL | 属性键 | | prop_value | TEXT | | 文本值 | | prop_json | JSONB | | JSON值 | | created_at | TIMESTAMP | DEFAULT NOW() | 创建时间 | **索引**: - `idx_edge_props_edge` ON (edge_id) - `idx_edge_props_unique` UNIQUE ON (edge_id, prop_key) **INPUT_FROM 边属性**: | prop_key | 说明 | |----------|------| | input_key | 输入参数名(如 'entity') | | input_type | 输入类型:entity_ref/attachment_ref/value_ref | | input_name | 输入名称(显示用) | | fixed_value | 固定值(可选) | --- ### 3.7 property_definitions - 属性定义表 | 字段 | 类型 | 约束 | 说明 | |------|------|------|------| | id | SERIAL | PK | 主键 | | owner_type | VARCHAR(20) | NOT NULL | 所有者类型:node/edge | | target_type | VARCHAR(50) | NOT NULL | 目标类型(如 PROJECT, RULE) | | prop_key | VARCHAR(100) | NOT NULL | 属性键 | | prop_name | VARCHAR(200) | NOT NULL | 属性名称 | | data_type | VARCHAR(50) | NOT NULL | 数据类型:string/number/boolean/json/date | | required | BOOLEAN | DEFAULT false | 是否必填 | | default_value | TEXT | | 默认值 | | description | TEXT | | 描述 | | created_at | TIMESTAMP | DEFAULT NOW() | 创建时间 | --- ## 四、视图定义 ### 4.1 v_projects - 项目视图 ```sql CREATE OR REPLACE VIEW v_projects AS SELECT n.id, n.name AS title, n.node_key AS project_code, n.status, n.created_at, n.updated_at, -- 属性 (SELECT prop_value FROM node_properties WHERE node_id = n.id AND prop_key = 'description') AS description, (SELECT prop_value FROM node_properties WHERE node_id = n.id AND prop_key = 'template_type') AS template_type, (SELECT prop_value FROM node_properties WHERE node_id = n.id AND prop_key = 'content_html') AS content_html, (SELECT prop_value FROM node_properties WHERE node_id = n.id AND prop_key = 'content_markdown') AS content_markdown, -- 统计 (SELECT COUNT(*) FROM edges e WHERE e.from_node_id = n.id AND e.edge_type = 'HAS_ELEMENT') AS element_count, (SELECT COUNT(*) FROM edges e WHERE e.from_node_id = n.id AND e.edge_type = 'HAS_ATTACHMENT') AS attachment_count, (SELECT COUNT(*) FROM edges e WHERE e.from_node_id = n.id AND e.edge_type = 'HAS_RULE') AS rule_count, (SELECT COUNT(*) FROM edges e JOIN nodes v ON v.id = e.to_node_id WHERE e.from_node_id = n.id AND e.edge_type = 'HAS_VALUE' AND EXISTS (SELECT 1 FROM node_properties WHERE node_id = v.id AND prop_key = 'is_filled' AND prop_value = 'true') ) AS filled_count, -- 关联 (SELECT n2.id FROM edges e JOIN nodes n2 ON n2.id = e.to_node_id WHERE e.from_node_id = n.id AND e.edge_type = 'COPIED_FROM' LIMIT 1) AS source_project_id, n.created_by, (SELECT username FROM sys_users WHERE node_id = n.created_by) AS created_by_name FROM nodes n WHERE n.node_type = 'PROJECT'; ``` **用途**: 项目列表查询、项目详情查询 --- ### 4.2 v_project_elements - 项目要素视图 ```sql CREATE OR REPLACE VIEW v_project_elements AS SELECT n.id, n.name AS element_name, n.node_key AS element_key, n.created_at, (SELECT prop_value FROM node_properties WHERE node_id = n.id AND prop_key = 'element_type') AS element_type, (SELECT prop_value FROM node_properties WHERE node_id = n.id AND prop_key = 'namespace') AS namespace, (SELECT prop_value FROM node_properties WHERE node_id = n.id AND prop_key = 'field_name') AS field_name, (SELECT prop_json FROM node_properties WHERE node_id = n.id AND prop_key = 'table_columns') AS table_columns, (SELECT prop_value FROM node_properties WHERE node_id = n.id AND prop_key = 'required')::boolean AS required, (SELECT prop_value FROM node_properties WHERE node_id = n.id AND prop_key = 'default_value') AS default_value, (SELECT prop_value FROM node_properties WHERE node_id = n.id AND prop_key = 'description') AS description, (SELECT e.from_node_id FROM edges e WHERE e.to_node_id = n.id AND e.edge_type = 'HAS_ELEMENT' LIMIT 1) AS project_id, (SELECT e.sort_order FROM edges e WHERE e.to_node_id = n.id AND e.edge_type = 'HAS_ELEMENT' LIMIT 1) AS sort_order FROM nodes n WHERE n.node_type = 'ELEMENT'; ``` **用途**: 查询项目的要素定义列表 --- ### 4.3 v_project_values - 项目要素值视图 ```sql CREATE OR REPLACE VIEW v_project_values AS SELECT n.id AS value_id, n.node_key AS element_key, n.created_at, n.updated_at, (SELECT prop_value FROM node_properties WHERE node_id = n.id AND prop_key = 'value_text') AS value_text, (SELECT prop_json FROM node_properties WHERE node_id = n.id AND prop_key = 'value_json') AS value_json, (SELECT prop_value FROM node_properties WHERE node_id = n.id AND prop_key = 'is_filled')::boolean AS is_filled, (SELECT prop_value FROM node_properties WHERE node_id = n.id AND prop_key = 'fill_source') AS fill_source, (SELECT e.from_node_id FROM edges e WHERE e.to_node_id = n.id AND e.edge_type = 'HAS_VALUE' LIMIT 1) AS project_id FROM nodes n WHERE n.node_type = 'VALUE'; ``` **用途**: 查询项目的要素值列表 --- ### 4.4 v_attachments - 附件视图 ```sql CREATE OR REPLACE VIEW v_attachments AS SELECT n.id, n.name AS display_name, n.node_key AS file_key, n.created_at, n.updated_at, (SELECT prop_value FROM node_properties WHERE node_id = n.id AND prop_key = 'file_name') AS file_name, (SELECT prop_value FROM node_properties WHERE node_id = n.id AND prop_key = 'file_path') AS file_path, (SELECT prop_value FROM node_properties WHERE node_id = n.id AND prop_key = 'file_type') AS file_type, (SELECT prop_number FROM node_properties WHERE node_id = n.id AND prop_key = 'file_size')::bigint AS file_size, (SELECT prop_value FROM node_properties WHERE node_id = n.id AND prop_key = 'parse_status') AS parse_status, (SELECT prop_value FROM node_properties WHERE node_id = n.id AND prop_key = 'parsed_text') AS parsed_text, (SELECT prop_date FROM node_properties WHERE node_id = n.id AND prop_key = 'parsed_at') AS parsed_at, (SELECT COUNT(*) FROM edges e WHERE e.from_node_id = n.id AND e.edge_type = 'HAS_ENTITY') AS entity_count, (SELECT e.from_node_id FROM edges e WHERE e.to_node_id = n.id AND e.edge_type = 'HAS_ATTACHMENT' LIMIT 1) AS project_id, (SELECT e.sort_order FROM edges e WHERE e.to_node_id = n.id AND e.edge_type = 'HAS_ATTACHMENT' LIMIT 1) AS sort_order FROM nodes n WHERE n.node_type = 'ATTACHMENT'; ``` --- ### 4.5 v_entities - 实体视图 ```sql CREATE OR REPLACE VIEW v_entities AS SELECT n.id, n.name AS entity_text, n.node_key AS entity_key, n.created_at, n.updated_at, (SELECT prop_value FROM node_properties WHERE node_id = n.id AND prop_key = 'entity_type') AS entity_type, (SELECT prop_value FROM node_properties WHERE node_id = n.id AND prop_key = 'business_label') AS business_label, (SELECT prop_number FROM node_properties WHERE node_id = n.id AND prop_key = 'confidence') AS confidence, (SELECT prop_number FROM node_properties WHERE node_id = n.id AND prop_key = 'occurrence_count')::int AS occurrence_count, (SELECT e.from_node_id FROM edges e WHERE e.to_node_id = n.id AND e.edge_type = 'HAS_ENTITY' LIMIT 1) AS attachment_id FROM nodes n WHERE n.node_type = 'ENTITY'; ``` --- ### 4.6 v_rules - 规则视图 ```sql CREATE OR REPLACE VIEW v_rules AS SELECT n.id, n.name AS rule_name, n.node_key AS element_key, n.status, n.created_at, n.updated_at, (SELECT prop_value FROM node_properties WHERE node_id = n.id AND prop_key = 'description') AS description, (SELECT prop_value FROM node_properties WHERE node_id = n.id AND prop_key = 'rule_type') AS rule_type, (SELECT prop_value FROM node_properties WHERE node_id = n.id AND prop_key = 'action_type') AS action_type, (SELECT prop_json FROM node_properties WHERE node_id = n.id AND prop_key = 'action_config') AS action_config, (SELECT prop_value FROM node_properties WHERE node_id = n.id AND prop_key = 'dsl_content') AS dsl_content, (SELECT prop_value FROM node_properties WHERE node_id = n.id AND prop_key = 'last_output_text') AS last_output_text, (SELECT prop_json FROM node_properties WHERE node_id = n.id AND prop_key = 'last_output_json') AS last_output_json, (SELECT prop_value FROM node_properties WHERE node_id = n.id AND prop_key = 'last_run_status') AS last_run_status, (SELECT prop_date FROM node_properties WHERE node_id = n.id AND prop_key = 'last_run_time') AS last_run_time, (SELECT prop_value FROM node_properties WHERE node_id = n.id AND prop_key = 'last_run_error') AS last_run_error, (SELECT e.from_node_id FROM edges e WHERE e.to_node_id = n.id AND e.edge_type = 'HAS_RULE' LIMIT 1) AS project_id FROM nodes n WHERE n.node_type = 'RULE'; ``` --- ### 4.7 v_rule_inputs - 规则输入视图 ```sql CREATE OR REPLACE VIEW v_rule_inputs AS SELECT e.id AS input_id, e.from_node_id AS rule_id, e.to_node_id AS source_node_id, e.sort_order, (SELECT prop_value FROM edge_properties WHERE edge_id = e.id AND prop_key = 'input_key') AS input_key, (SELECT prop_value FROM edge_properties WHERE edge_id = e.id AND prop_key = 'input_name') AS input_name, (SELECT prop_value FROM edge_properties WHERE edge_id = e.id AND prop_key = 'input_type') AS input_type, (SELECT prop_value FROM edge_properties WHERE edge_id = e.id AND prop_key = 'fixed_value') AS fixed_value, n.node_type AS source_type, n.name AS source_name FROM edges e JOIN nodes n ON n.id = e.to_node_id WHERE e.edge_type = 'INPUT_FROM'; ``` --- ## 五、常用查询示例 ### 5.1 获取项目列表(分页) ```sql SELECT * FROM v_projects WHERE status != 'archived' ORDER BY updated_at DESC LIMIT 20 OFFSET 0; ``` ### 5.2 获取项目详情(含要素和值) ```sql -- 项目基本信息 SELECT * FROM v_projects WHERE id = 10; -- 要素定义列表 SELECT * FROM v_project_elements WHERE project_id = 10 ORDER BY sort_order; -- 要素值列表 SELECT * FROM v_project_values WHERE project_id = 10; -- 附件列表 SELECT * FROM v_attachments WHERE project_id = 10 ORDER BY sort_order; -- 规则列表 SELECT * FROM v_rules WHERE project_id = 10; ``` ### 5.3 获取项目所有实体 ```sql SELECT e.* FROM v_entities e JOIN v_attachments a ON a.id = e.attachment_id WHERE a.project_id = 10 ORDER BY e.entity_type, e.confidence DESC; ``` ### 5.4 获取规则的输入来源 ```sql SELECT * FROM v_rule_inputs WHERE rule_id = 600; ``` ### 5.5 创建项目完整流程 ```sql -- 1. 创建项目节点 INSERT INTO nodes (node_type, node_key, name, status, created_by) VALUES ('PROJECT', 'PRJ-2024-002', '新项目', 'draft', 1) RETURNING id; -- 假设返回 id = 20 -- 2. 设置项目属性 INSERT INTO node_properties (node_id, prop_key, prop_value) VALUES (20, 'title', '新项目'), (20, 'description', '项目描述'), (20, 'status', 'draft'), (20, 'template_type', '电力安全生产标准化复审报告'); -- 3. 创建要素定义(从模板复制或手动创建) INSERT INTO nodes (node_type, node_key, name, created_by) VALUES ('ELEMENT', 'basicInfo.projectCode', '项目编号', 1) RETURNING id; -- 假设返回 id = 210 -- 4. 建立关系 INSERT INTO edges (edge_type, from_node_id, to_node_id, sort_order) VALUES ('HAS_ELEMENT', 20, 210, 1); -- 5. 创建空值节点 INSERT INTO nodes (node_type, node_key, name, created_by) VALUES ('VALUE', 'PRJ-2024-002:basicInfo.projectCode', '项目编号值', 1) RETURNING id; -- 假设返回 id = 310 -- 6. 建立值关系 INSERT INTO edges (edge_type, from_node_id, to_node_id) VALUES ('HAS_VALUE', 20, 310); INSERT INTO edges (edge_type, from_node_id, to_node_id) VALUES ('FOR_ELEMENT', 310, 210); -- 7. 初始化值属性 INSERT INTO node_properties (node_id, prop_key, prop_value) VALUES (310, 'is_filled', 'false'); ``` --- ## 六、规则引擎对接(预留) ### 6.1 当前状态 规则引擎由独立团队开发,将提供接口供本系统调用。当前设计中: - RULE 节点的 `dsl_content` 属性预留存储 DSL 代码 - RULE 节点的 `rule_type` 支持 `dsl` 类型 - INPUT_FROM 边记录规则的输入参数 ### 6.2 对接时需要提供的数据 根据规则引擎 DSL 示例,对接时需要传递的核心参数为**节点ID**: ```python # 规则引擎需要的参数就是各种节点ID one_two_ch_id = 12578 # 某个节点的ID standard_item1_score_id = 234808 # 某个节点的ID ``` 当前设计中,所有业务实体都是 nodes 表中的记录,每条记录都有唯一的 `id`,可以直接作为规则引擎的输入参数。 ### 6.3 待确认事项 - [ ] 规则引擎接口的请求/响应格式 - [ ] 参数传递方式(HTTP/gRPC/消息队列) - [ ] 异步执行和回调机制 - [ ] 错误处理和重试策略 --- ## 七、数据统计 ### 7.1 表统计 | 分类 | 数量 | |------|------| | sys_* 业务支撑表 | 13张 | | 核心图结构表 | 7张 | | 业务视图 | 7个 | | **合计** | **20张表 + 7个视图** | ### 7.2 节点类型统计 | 类型 | 数量 | |------|------| | 节点类型 | 6种 | | 关系类型 | 11种 | ### 7.3 索引统计 | 表 | 索引数 | |----|--------| | nodes | 6个 | | edges | 6个 | | node_properties | 3个 | | edge_properties | 2个 | | sys_* 表 | 约20个 | | **合计** | **约37个** |