init.sql 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668
  1. -- =====================================================
  2. -- 灵越智报 2.0 数据库初始化脚本
  3. -- PostgreSQL 15+ / pgvector
  4. -- 设计参考: a_docs/数据库设计文档.md
  5. -- =====================================================
  6. CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
  7. CREATE EXTENSION IF NOT EXISTS vector;
  8. -- ==================== 用户表 ====================
  9. CREATE TABLE IF NOT EXISTS users (
  10. id VARCHAR(36) PRIMARY KEY,
  11. username VARCHAR(50) NOT NULL UNIQUE,
  12. email VARCHAR(100) UNIQUE,
  13. password_hash VARCHAR(255) NOT NULL,
  14. display_name VARCHAR(100),
  15. avatar_url VARCHAR(500),
  16. role VARCHAR(20) DEFAULT 'user',
  17. preferences JSONB DEFAULT '{}',
  18. is_active BOOLEAN DEFAULT TRUE,
  19. last_login_at TIMESTAMP,
  20. create_by VARCHAR(36),
  21. create_by_name VARCHAR(100),
  22. create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  23. update_by VARCHAR(36),
  24. update_by_name VARCHAR(100),
  25. update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP
  26. );
  27. CREATE INDEX IF NOT EXISTS idx_users_username ON users(username);
  28. CREATE INDEX IF NOT EXISTS idx_users_email ON users(email);
  29. -- ==================== 文档表 ====================
  30. CREATE TABLE IF NOT EXISTS documents (
  31. id VARCHAR(36) PRIMARY KEY,
  32. user_id VARCHAR(36) NOT NULL REFERENCES users(id) ON DELETE CASCADE,
  33. name VARCHAR(255) NOT NULL,
  34. file_name VARCHAR(500) NOT NULL,
  35. file_path VARCHAR(500) NOT NULL,
  36. file_size BIGINT,
  37. file_type VARCHAR(20) NOT NULL,
  38. status VARCHAR(20) DEFAULT 'uploaded',
  39. parsed_text TEXT,
  40. page_count INT,
  41. word_count INT,
  42. entity_count INT DEFAULT 0,
  43. relation_count INT DEFAULT 0,
  44. rule_count INT DEFAULT 0,
  45. metadata JSONB DEFAULT '{}',
  46. del_flag BOOLEAN DEFAULT FALSE,
  47. create_by VARCHAR(36),
  48. create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  49. update_by VARCHAR(36),
  50. update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP
  51. );
  52. CREATE INDEX IF NOT EXISTS idx_documents_user ON documents(user_id);
  53. CREATE INDEX IF NOT EXISTS idx_documents_type ON documents(file_type);
  54. CREATE INDEX IF NOT EXISTS idx_documents_status ON documents(status);
  55. -- ==================== 文档章节结构表 ====================
  56. CREATE TABLE IF NOT EXISTS document_sections (
  57. id VARCHAR(36) PRIMARY KEY,
  58. document_id VARCHAR(36) NOT NULL REFERENCES documents(id) ON DELETE CASCADE,
  59. parent_id VARCHAR(36) REFERENCES document_sections(id) ON DELETE CASCADE,
  60. section_index INT NOT NULL,
  61. level INT NOT NULL DEFAULT 1,
  62. title VARCHAR(500),
  63. content TEXT,
  64. start_page INT,
  65. end_page INT,
  66. start_char INT,
  67. end_char INT,
  68. section_type VARCHAR(32) DEFAULT 'heading',
  69. table_data JSONB,
  70. image_path VARCHAR(500),
  71. image_caption VARCHAR(500),
  72. metadata JSONB DEFAULT '{}',
  73. sort_order INT DEFAULT 0,
  74. create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP
  75. );
  76. CREATE INDEX IF NOT EXISTS idx_doc_sections_document ON document_sections(document_id);
  77. CREATE INDEX IF NOT EXISTS idx_doc_sections_parent ON document_sections(parent_id);
  78. CREATE INDEX IF NOT EXISTS idx_doc_sections_level ON document_sections(level);
  79. CREATE INDEX IF NOT EXISTS idx_doc_sections_type ON document_sections(section_type);
  80. -- ==================== 文档分块表 ====================
  81. CREATE TABLE IF NOT EXISTS document_chunks (
  82. id VARCHAR(36) PRIMARY KEY,
  83. document_id VARCHAR(36) NOT NULL REFERENCES documents(id) ON DELETE CASCADE,
  84. section_id VARCHAR(36) REFERENCES document_sections(id) ON DELETE SET NULL,
  85. chunk_index INT NOT NULL,
  86. content TEXT NOT NULL,
  87. start_char INT,
  88. end_char INT,
  89. page_number INT,
  90. token_count INT,
  91. metadata JSONB DEFAULT '{}',
  92. create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP
  93. );
  94. CREATE INDEX IF NOT EXISTS idx_doc_chunks_document ON document_chunks(document_id);
  95. CREATE INDEX IF NOT EXISTS idx_doc_chunks_section ON document_chunks(section_id);
  96. -- ==================== 解析任务表(parse-service 依赖) ====================
  97. CREATE TABLE IF NOT EXISTS parse_tasks (
  98. id VARCHAR(36) PRIMARY KEY,
  99. document_id VARCHAR(36) NOT NULL REFERENCES documents(id) ON DELETE CASCADE,
  100. status VARCHAR(20) DEFAULT 'pending',
  101. progress INT DEFAULT 0,
  102. current_step VARCHAR(32),
  103. error_message TEXT,
  104. options JSONB DEFAULT '{}',
  105. started_at TIMESTAMP,
  106. completed_at TIMESTAMP,
  107. parse_status VARCHAR(20) DEFAULT 'pending',
  108. parse_progress INT DEFAULT 0,
  109. rag_status VARCHAR(20) DEFAULT 'pending',
  110. rag_progress INT DEFAULT 0,
  111. structured_status VARCHAR(20) DEFAULT 'pending',
  112. structured_progress INT DEFAULT 0,
  113. structured_element_count INT,
  114. structured_image_count INT,
  115. structured_table_count INT,
  116. ner_status VARCHAR(20) DEFAULT 'pending',
  117. ner_progress INT DEFAULT 0,
  118. ner_task_id VARCHAR(100),
  119. ner_entity_count INT,
  120. ner_relation_count INT,
  121. ner_message TEXT,
  122. graph_status VARCHAR(20) DEFAULT 'pending',
  123. graph_progress INT DEFAULT 0,
  124. create_by VARCHAR(36),
  125. create_by_name VARCHAR(100),
  126. create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  127. update_by VARCHAR(36),
  128. update_by_name VARCHAR(100),
  129. update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP
  130. );
  131. CREATE INDEX IF NOT EXISTS idx_parse_tasks_document ON parse_tasks(document_id);
  132. -- ==================== 文档结构化元素表(结构化解析 / 前端展示依赖) ====================
  133. CREATE TABLE IF NOT EXISTS document_elements (
  134. id VARCHAR(36) PRIMARY KEY,
  135. document_id VARCHAR(36) NOT NULL REFERENCES documents(id) ON DELETE CASCADE,
  136. element_index INT,
  137. element_type VARCHAR(50),
  138. content TEXT,
  139. style JSONB DEFAULT '{}',
  140. runs JSONB DEFAULT '[]',
  141. image_url VARCHAR(500),
  142. image_path VARCHAR(500),
  143. image_alt VARCHAR(500),
  144. image_width INT,
  145. image_height INT,
  146. image_format VARCHAR(20),
  147. table_index INT,
  148. table_data JSONB,
  149. table_row_count INT,
  150. table_col_count INT,
  151. table_text TEXT,
  152. create_by VARCHAR(36),
  153. create_by_name VARCHAR(100),
  154. create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  155. update_by VARCHAR(36),
  156. update_by_name VARCHAR(100),
  157. update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP
  158. );
  159. CREATE INDEX IF NOT EXISTS idx_document_elements_document ON document_elements(document_id);
  160. -- ==================== 向量嵌入表 ====================
  161. CREATE TABLE IF NOT EXISTS embeddings (
  162. id VARCHAR(36) PRIMARY KEY,
  163. chunk_id VARCHAR(36) NOT NULL REFERENCES document_chunks(id) ON DELETE CASCADE,
  164. embedding vector(1536),
  165. model_name VARCHAR(100) DEFAULT 'text-embedding-ada-002',
  166. model_version VARCHAR(50),
  167. create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP
  168. );
  169. CREATE INDEX IF NOT EXISTS idx_embeddings_chunk ON embeddings(chunk_id);
  170. CREATE INDEX IF NOT EXISTS idx_embeddings_vector ON embeddings USING ivfflat (embedding vector_cosine_ops) WITH (lists = 100);
  171. -- ==================== 实体类型表 ====================
  172. CREATE TABLE IF NOT EXISTS entity_types (
  173. id VARCHAR(36) PRIMARY KEY,
  174. type_code VARCHAR(50) NOT NULL UNIQUE,
  175. type_name VARCHAR(100) NOT NULL,
  176. category VARCHAR(32),
  177. color VARCHAR(20),
  178. icon VARCHAR(50),
  179. patterns JSONB DEFAULT '[]',
  180. examples JSONB DEFAULT '[]',
  181. description TEXT,
  182. is_active BOOLEAN DEFAULT TRUE,
  183. sort_order INT DEFAULT 0,
  184. create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  185. update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP
  186. );
  187. CREATE INDEX IF NOT EXISTS idx_entity_types_code ON entity_types(type_code);
  188. -- ==================== 实体节点表(方案 B:视图驱动)====================
  189. CREATE TABLE IF NOT EXISTS entity_nodes (
  190. id VARCHAR(36) PRIMARY KEY,
  191. entity_type VARCHAR(50) NOT NULL,
  192. name VARCHAR(500) NOT NULL,
  193. normalized_text VARCHAR(500),
  194. embedding vector(1536),
  195. del_flag BOOLEAN DEFAULT FALSE,
  196. create_by VARCHAR(36),
  197. create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  198. update_by VARCHAR(36),
  199. update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  200. UNIQUE(entity_type, normalized_text)
  201. );
  202. CREATE INDEX IF NOT EXISTS idx_entity_nodes_type ON entity_nodes(entity_type);
  203. CREATE INDEX IF NOT EXISTS idx_entity_nodes_name ON entity_nodes(name);
  204. CREATE INDEX IF NOT EXISTS idx_entity_nodes_normalized ON entity_nodes(normalized_text);
  205. -- ==================== 实体属性表 ====================
  206. CREATE TABLE IF NOT EXISTS entity_attributes (
  207. id VARCHAR(36) PRIMARY KEY,
  208. entity_id VARCHAR(36) NOT NULL REFERENCES entity_nodes(id) ON DELETE CASCADE,
  209. attribute_key VARCHAR(100) NOT NULL,
  210. attribute_value TEXT,
  211. value_type VARCHAR(32) DEFAULT 'STRING',
  212. sort_order INT DEFAULT 0,
  213. create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  214. UNIQUE(entity_id, attribute_key)
  215. );
  216. CREATE INDEX IF NOT EXISTS idx_entity_attributes_entity ON entity_attributes(entity_id);
  217. CREATE INDEX IF NOT EXISTS idx_entity_attributes_key ON entity_attributes(attribute_key);
  218. -- ==================== 实体视图 v_entities(读模型)====================
  219. CREATE OR REPLACE VIEW v_entities AS
  220. SELECT
  221. n.id,
  222. n.entity_type,
  223. n.name AS entity_text,
  224. n.normalized_text,
  225. n.embedding,
  226. n.del_flag,
  227. n.create_by,
  228. n.create_time,
  229. n.update_by,
  230. n.update_time,
  231. (SELECT attribute_value FROM entity_attributes WHERE entity_id = n.id AND attribute_key = 'aliases' LIMIT 1) AS aliases,
  232. (SELECT attribute_value FROM entity_attributes WHERE entity_id = n.id AND attribute_key = 'metadata' LIMIT 1) AS metadata,
  233. COALESCE((SELECT (attribute_value::INT) FROM entity_attributes WHERE entity_id = n.id AND attribute_key = 'occurrence_count' LIMIT 1), 1) AS occurrence_count,
  234. COALESCE((SELECT (attribute_value::FLOAT) FROM entity_attributes WHERE entity_id = n.id AND attribute_key = 'confidence' LIMIT 1), 1.0) AS confidence,
  235. COALESCE((SELECT (attribute_value::BOOLEAN) FROM entity_attributes WHERE entity_id = n.id AND attribute_key = 'is_confirmed' LIMIT 1), FALSE) AS is_confirmed,
  236. COALESCE((SELECT (attribute_value::BOOLEAN) FROM entity_attributes WHERE entity_id = n.id AND attribute_key = 'is_merged' LIMIT 1), FALSE) AS is_merged,
  237. (SELECT attribute_value FROM entity_attributes WHERE entity_id = n.id AND attribute_key = 'merged_to_id' LIMIT 1) AS merged_to_id
  238. FROM entity_nodes n
  239. WHERE n.del_flag = FALSE;
  240. -- ==================== 文档–实体关联表 ====================
  241. CREATE TABLE IF NOT EXISTS document_entities (
  242. id VARCHAR(36) PRIMARY KEY,
  243. document_id VARCHAR(36) NOT NULL REFERENCES documents(id) ON DELETE CASCADE,
  244. entity_id VARCHAR(36) NOT NULL REFERENCES entity_nodes(id) ON DELETE CASCADE,
  245. business_label VARCHAR(100),
  246. display_text VARCHAR(500),
  247. create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  248. UNIQUE(document_id, entity_id, business_label)
  249. );
  250. CREATE INDEX IF NOT EXISTS idx_document_entities_document ON document_entities(document_id);
  251. CREATE INDEX IF NOT EXISTS idx_document_entities_entity ON document_entities(entity_id);
  252. CREATE INDEX IF NOT EXISTS idx_document_entities_label ON document_entities(business_label);
  253. -- ==================== 关系类型表 ====================
  254. CREATE TABLE IF NOT EXISTS relation_types (
  255. id VARCHAR(36) PRIMARY KEY,
  256. type_code VARCHAR(50) NOT NULL UNIQUE,
  257. type_name VARCHAR(100) NOT NULL,
  258. source_entity_types JSONB DEFAULT '[]',
  259. target_entity_types JSONB DEFAULT '[]',
  260. is_symmetric BOOLEAN DEFAULT FALSE,
  261. description TEXT,
  262. is_active BOOLEAN DEFAULT TRUE,
  263. sort_order INT DEFAULT 0,
  264. create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  265. update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP
  266. );
  267. CREATE INDEX IF NOT EXISTS idx_relation_types_code ON relation_types(type_code);
  268. -- ==================== 实体关系表 ====================
  269. CREATE TABLE IF NOT EXISTS entity_relations (
  270. id VARCHAR(36) PRIMARY KEY,
  271. document_id VARCHAR(36) NOT NULL REFERENCES documents(id) ON DELETE CASCADE,
  272. source_entity_id VARCHAR(36) NOT NULL REFERENCES entity_nodes(id) ON DELETE CASCADE,
  273. target_entity_id VARCHAR(36) NOT NULL REFERENCES entity_nodes(id) ON DELETE CASCADE,
  274. relation_type VARCHAR(50) NOT NULL,
  275. relation_text VARCHAR(500),
  276. confidence FLOAT DEFAULT 1.0,
  277. extraction_method VARCHAR(32) DEFAULT 'auto',
  278. evidence_text TEXT,
  279. is_confirmed BOOLEAN DEFAULT FALSE,
  280. metadata JSONB DEFAULT '{}',
  281. create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  282. update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP
  283. );
  284. CREATE INDEX IF NOT EXISTS idx_relations_document ON entity_relations(document_id);
  285. CREATE INDEX IF NOT EXISTS idx_relations_source ON entity_relations(source_entity_id);
  286. CREATE INDEX IF NOT EXISTS idx_relations_target ON entity_relations(target_entity_id);
  287. CREATE INDEX IF NOT EXISTS idx_relations_type ON entity_relations(relation_type);
  288. -- ==================== 规则表 ====================
  289. CREATE TABLE IF NOT EXISTS rules (
  290. id VARCHAR(36) PRIMARY KEY,
  291. document_id VARCHAR(36) REFERENCES documents(id) ON DELETE SET NULL,
  292. user_id VARCHAR(36) NOT NULL REFERENCES users(id) ON DELETE CASCADE,
  293. name VARCHAR(200) NOT NULL,
  294. description TEXT,
  295. category VARCHAR(50),
  296. rule_type VARCHAR(32) NOT NULL,
  297. source VARCHAR(32) DEFAULT 'auto',
  298. priority INT DEFAULT 0,
  299. status VARCHAR(20) DEFAULT 'draft',
  300. embedding vector(1536),
  301. is_global BOOLEAN DEFAULT FALSE,
  302. del_flag BOOLEAN DEFAULT FALSE,
  303. create_by VARCHAR(36),
  304. create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  305. update_by VARCHAR(36),
  306. update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP
  307. );
  308. CREATE INDEX IF NOT EXISTS idx_rules_document ON rules(document_id);
  309. CREATE INDEX IF NOT EXISTS idx_rules_user ON rules(user_id);
  310. CREATE INDEX IF NOT EXISTS idx_rules_type ON rules(rule_type);
  311. CREATE INDEX IF NOT EXISTS idx_rules_status ON rules(status);
  312. CREATE INDEX IF NOT EXISTS idx_rules_category ON rules(category);
  313. -- ==================== 规则条件表 ====================
  314. CREATE TABLE IF NOT EXISTS rule_conditions (
  315. id VARCHAR(36) PRIMARY KEY,
  316. rule_id VARCHAR(36) NOT NULL REFERENCES rules(id) ON DELETE CASCADE,
  317. condition_index INT NOT NULL,
  318. condition_type VARCHAR(32) NOT NULL,
  319. config JSONB NOT NULL,
  320. logic_operator VARCHAR(10) DEFAULT 'AND',
  321. sort_order INT DEFAULT 0,
  322. create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP
  323. );
  324. CREATE INDEX IF NOT EXISTS idx_rule_conditions_rule ON rule_conditions(rule_id);
  325. -- ==================== 规则动作表 ====================
  326. CREATE TABLE IF NOT EXISTS rule_actions (
  327. id VARCHAR(36) PRIMARY KEY,
  328. rule_id VARCHAR(36) NOT NULL REFERENCES rules(id) ON DELETE CASCADE,
  329. action_index INT NOT NULL,
  330. action_type VARCHAR(32) NOT NULL,
  331. config JSONB NOT NULL,
  332. target_field VARCHAR(100),
  333. sort_order INT DEFAULT 0,
  334. create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP
  335. );
  336. CREATE INDEX IF NOT EXISTS idx_rule_actions_rule ON rule_actions(rule_id);
  337. -- ==================== 生成任务表 ====================
  338. CREATE TABLE IF NOT EXISTS generations (
  339. id VARCHAR(36) PRIMARY KEY,
  340. user_id VARCHAR(36) NOT NULL REFERENCES users(id) ON DELETE CASCADE,
  341. document_id VARCHAR(36) REFERENCES documents(id) ON DELETE SET NULL,
  342. template_id VARCHAR(36),
  343. name VARCHAR(200),
  344. applied_rules JSONB DEFAULT '[]',
  345. source_file_map JSONB DEFAULT '{}',
  346. extracted_data JSONB DEFAULT '{}',
  347. confirmed_data JSONB DEFAULT '{}',
  348. output_file_path VARCHAR(500),
  349. output_file_name VARCHAR(255),
  350. output_document_id VARCHAR(36),
  351. progress INTEGER,
  352. status VARCHAR(20) DEFAULT 'pending',
  353. error_message TEXT,
  354. started_at TIMESTAMP,
  355. reviewed_at TIMESTAMP,
  356. completed_at TIMESTAMP,
  357. del_flag BOOLEAN DEFAULT FALSE,
  358. create_by VARCHAR(36),
  359. create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  360. update_by VARCHAR(36),
  361. update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP
  362. );
  363. CREATE INDEX IF NOT EXISTS idx_generations_user ON generations(user_id);
  364. CREATE INDEX IF NOT EXISTS idx_generations_document ON generations(document_id);
  365. CREATE INDEX IF NOT EXISTS idx_generations_status ON generations(status);
  366. -- ==================== 生成输出表 ====================
  367. CREATE TABLE IF NOT EXISTS generation_outputs (
  368. id VARCHAR(36) PRIMARY KEY,
  369. generation_id VARCHAR(36) NOT NULL REFERENCES generations(id) ON DELETE CASCADE,
  370. version INT NOT NULL DEFAULT 1,
  371. file_path VARCHAR(500) NOT NULL,
  372. file_name VARCHAR(255) NOT NULL,
  373. file_size BIGINT,
  374. file_type VARCHAR(20) DEFAULT 'docx',
  375. share_token VARCHAR(100),
  376. share_expires_at TIMESTAMP,
  377. download_count INT DEFAULT 0,
  378. is_final BOOLEAN DEFAULT FALSE,
  379. create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP
  380. );
  381. CREATE INDEX IF NOT EXISTS idx_gen_outputs_generation ON generation_outputs(generation_id);
  382. CREATE INDEX IF NOT EXISTS idx_gen_outputs_share ON generation_outputs(share_token);
  383. -- ==================== 模板/变量/来源文件(兼容现有模板流程) ====================
  384. CREATE TABLE IF NOT EXISTS templates (
  385. id VARCHAR(36) PRIMARY KEY,
  386. user_id VARCHAR(36) NOT NULL,
  387. name VARCHAR(200),
  388. description TEXT,
  389. base_document_id VARCHAR(36),
  390. status VARCHAR(20) DEFAULT 'draft',
  391. config JSONB DEFAULT '{}',
  392. is_public BOOLEAN DEFAULT FALSE,
  393. use_count INT DEFAULT 0,
  394. rating DOUBLE PRECISION,
  395. create_by VARCHAR(36),
  396. create_by_name VARCHAR(100),
  397. create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  398. update_by VARCHAR(36),
  399. update_by_name VARCHAR(100),
  400. update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP
  401. );
  402. CREATE INDEX IF NOT EXISTS idx_templates_user ON templates(user_id);
  403. CREATE TABLE IF NOT EXISTS variables (
  404. id VARCHAR(36) PRIMARY KEY,
  405. template_id VARCHAR(36) NOT NULL REFERENCES templates(id) ON DELETE CASCADE,
  406. name VARCHAR(100) NOT NULL,
  407. display_name VARCHAR(200),
  408. variable_group VARCHAR(100),
  409. category VARCHAR(50),
  410. location JSONB,
  411. example_value TEXT,
  412. value_type VARCHAR(20),
  413. source_file_alias VARCHAR(100),
  414. source_type VARCHAR(30),
  415. source_config JSONB DEFAULT '{}',
  416. extract_type VARCHAR(30),
  417. extract_config JSONB DEFAULT '{}',
  418. display_order INT DEFAULT 0,
  419. create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  420. update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP
  421. );
  422. CREATE INDEX IF NOT EXISTS idx_variables_template ON variables(template_id);
  423. CREATE TABLE IF NOT EXISTS source_files (
  424. id VARCHAR(36) PRIMARY KEY,
  425. template_id VARCHAR(36) NOT NULL REFERENCES templates(id) ON DELETE CASCADE,
  426. alias VARCHAR(100) NOT NULL,
  427. description TEXT,
  428. file_types JSONB DEFAULT '[]',
  429. required BOOLEAN DEFAULT TRUE,
  430. example_document_id VARCHAR(36),
  431. display_order INT DEFAULT 0,
  432. create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP
  433. );
  434. CREATE INDEX IF NOT EXISTS idx_source_files_template ON source_files(template_id);
  435. -- ==================== 标准实体表 ====================
  436. CREATE TABLE IF NOT EXISTS standard_entities (
  437. id VARCHAR(36) PRIMARY KEY,
  438. entity_type VARCHAR(50) NOT NULL,
  439. name VARCHAR(500) NOT NULL,
  440. aliases JSONB DEFAULT '[]',
  441. attributes JSONB DEFAULT '{}',
  442. embedding vector(1536),
  443. occurrence_count INT DEFAULT 1,
  444. document_count INT DEFAULT 1,
  445. is_verified BOOLEAN DEFAULT FALSE,
  446. del_flag BOOLEAN DEFAULT FALSE,
  447. create_by VARCHAR(36),
  448. create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  449. update_by VARCHAR(36),
  450. update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP
  451. );
  452. CREATE INDEX IF NOT EXISTS idx_std_entities_type ON standard_entities(entity_type);
  453. CREATE INDEX IF NOT EXISTS idx_std_entities_name ON standard_entities(name);
  454. CREATE INDEX IF NOT EXISTS idx_std_entities_vector ON standard_entities USING ivfflat (embedding vector_cosine_ops) WITH (lists = 100);
  455. -- ==================== 标准关系表 ====================
  456. CREATE TABLE IF NOT EXISTS standard_relations (
  457. id VARCHAR(36) PRIMARY KEY,
  458. source_entity_id VARCHAR(36) NOT NULL REFERENCES standard_entities(id) ON DELETE CASCADE,
  459. target_entity_id VARCHAR(36) NOT NULL REFERENCES standard_entities(id) ON DELETE CASCADE,
  460. relation_type VARCHAR(50) NOT NULL,
  461. attributes JSONB DEFAULT '{}',
  462. occurrence_count INT DEFAULT 1,
  463. is_verified BOOLEAN DEFAULT FALSE,
  464. del_flag BOOLEAN DEFAULT FALSE,
  465. create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  466. update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP
  467. );
  468. CREATE INDEX IF NOT EXISTS idx_std_relations_source ON standard_relations(source_entity_id);
  469. CREATE INDEX IF NOT EXISTS idx_std_relations_target ON standard_relations(target_entity_id);
  470. CREATE INDEX IF NOT EXISTS idx_std_relations_type ON standard_relations(relation_type);
  471. -- ==================== 实体合并记录表 ====================
  472. CREATE TABLE IF NOT EXISTS entity_merge_records (
  473. id VARCHAR(36) PRIMARY KEY,
  474. source_entity_id VARCHAR(36) NOT NULL REFERENCES entity_nodes(id) ON DELETE CASCADE,
  475. target_entity_id VARCHAR(36) NOT NULL REFERENCES standard_entities(id) ON DELETE CASCADE,
  476. similarity_score FLOAT,
  477. merge_type VARCHAR(32) DEFAULT 'auto',
  478. create_by VARCHAR(36),
  479. create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP
  480. );
  481. CREATE INDEX IF NOT EXISTS idx_merge_records_source ON entity_merge_records(source_entity_id);
  482. CREATE INDEX IF NOT EXISTS idx_merge_records_target ON entity_merge_records(target_entity_id);
  483. -- ==================== 规则-标准实体/关系关联(实体图与拖拽搭建规则) ====================
  484. CREATE TABLE IF NOT EXISTS rule_standard_entities (
  485. id VARCHAR(36) PRIMARY KEY,
  486. rule_id VARCHAR(36) NOT NULL REFERENCES rules(id) ON DELETE CASCADE,
  487. standard_entity_id VARCHAR(36) NOT NULL REFERENCES standard_entities(id) ON DELETE CASCADE,
  488. role VARCHAR(32) DEFAULT 'participant',
  489. display_order INT DEFAULT 0,
  490. create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  491. UNIQUE(rule_id, standard_entity_id)
  492. );
  493. CREATE INDEX IF NOT EXISTS idx_rule_std_entities_rule ON rule_standard_entities(rule_id);
  494. CREATE INDEX IF NOT EXISTS idx_rule_std_entities_entity ON rule_standard_entities(standard_entity_id);
  495. CREATE TABLE IF NOT EXISTS rule_standard_relations (
  496. id VARCHAR(36) PRIMARY KEY,
  497. rule_id VARCHAR(36) NOT NULL REFERENCES rules(id) ON DELETE CASCADE,
  498. standard_relation_id VARCHAR(36) NOT NULL REFERENCES standard_relations(id) ON DELETE CASCADE,
  499. display_order INT DEFAULT 0,
  500. create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  501. UNIQUE(rule_id, standard_relation_id)
  502. );
  503. CREATE INDEX IF NOT EXISTS idx_rule_std_relations_rule ON rule_standard_relations(rule_id);
  504. CREATE INDEX IF NOT EXISTS idx_rule_std_relations_relation ON rule_standard_relations(standard_relation_id);
  505. -- ==================== 前端业务:公司 / 项目 / 报告 / 报告附件 ====================
  506. CREATE TABLE IF NOT EXISTS companies (
  507. id VARCHAR(36) PRIMARY KEY,
  508. parent_id VARCHAR(36) REFERENCES companies(id) ON DELETE SET NULL,
  509. name VARCHAR(500) NOT NULL,
  510. short_name VARCHAR(100),
  511. unified_social_credit_code VARCHAR(50),
  512. description TEXT,
  513. metadata JSONB DEFAULT '{}',
  514. del_flag BOOLEAN DEFAULT FALSE,
  515. create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  516. update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP
  517. );
  518. CREATE INDEX IF NOT EXISTS idx_companies_parent ON companies(parent_id);
  519. CREATE INDEX IF NOT EXISTS idx_companies_name ON companies(name);
  520. CREATE TABLE IF NOT EXISTS projects (
  521. id VARCHAR(36) PRIMARY KEY,
  522. company_id VARCHAR(36) REFERENCES companies(id) ON DELETE SET NULL,
  523. project_code VARCHAR(100) NOT NULL,
  524. project_name VARCHAR(500),
  525. review_object VARCHAR(500),
  526. review_object_alias VARCHAR(200),
  527. review_object_summary TEXT,
  528. application_category VARCHAR(100),
  529. request_level VARCHAR(50),
  530. result_level VARCHAR(50),
  531. result_score DECIMAL(10,2),
  532. review_period VARCHAR(200),
  533. work_start_at DATE,
  534. work_end_at DATE,
  535. review_object_certificate2_get_at DATE,
  536. apply_at DATE,
  537. reviewer_company_id VARCHAR(36) REFERENCES companies(id) ON DELETE SET NULL,
  538. metadata JSONB DEFAULT '{}',
  539. del_flag BOOLEAN DEFAULT FALSE,
  540. create_by VARCHAR(36),
  541. create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  542. update_by VARCHAR(36),
  543. update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP
  544. );
  545. CREATE INDEX IF NOT EXISTS idx_projects_company ON projects(company_id);
  546. CREATE INDEX IF NOT EXISTS idx_projects_code ON projects(project_code);
  547. CREATE TABLE IF NOT EXISTS reports (
  548. id VARCHAR(36) PRIMARY KEY,
  549. user_id VARCHAR(36) NOT NULL REFERENCES users(id) ON DELETE CASCADE,
  550. project_id VARCHAR(36) REFERENCES projects(id) ON DELETE SET NULL,
  551. title VARCHAR(500) NOT NULL,
  552. report_type VARCHAR(100),
  553. status VARCHAR(20) NOT NULL DEFAULT 'draft',
  554. content_template TEXT,
  555. content_rendered TEXT,
  556. auto_saved_at TIMESTAMP,
  557. report_score DECIMAL(10,2),
  558. report_level VARCHAR(50),
  559. report_metrics JSONB DEFAULT '{}',
  560. generation_id VARCHAR(36) REFERENCES generations(id) ON DELETE SET NULL,
  561. source_document_id VARCHAR(36) REFERENCES documents(id) ON DELETE SET NULL,
  562. archived_at TIMESTAMP,
  563. published_at TIMESTAMP,
  564. del_flag BOOLEAN DEFAULT FALSE,
  565. create_by VARCHAR(36),
  566. create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  567. update_by VARCHAR(36),
  568. update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP
  569. );
  570. CREATE INDEX IF NOT EXISTS idx_reports_user ON reports(user_id);
  571. CREATE INDEX IF NOT EXISTS idx_reports_project ON reports(project_id);
  572. CREATE INDEX IF NOT EXISTS idx_reports_status ON reports(status);
  573. CREATE INDEX IF NOT EXISTS idx_reports_created ON reports(create_time);
  574. CREATE TABLE IF NOT EXISTS report_attachments (
  575. id VARCHAR(36) PRIMARY KEY,
  576. report_id VARCHAR(36) NOT NULL REFERENCES reports(id) ON DELETE CASCADE,
  577. display_name VARCHAR(255),
  578. file_name VARCHAR(500) NOT NULL,
  579. file_path VARCHAR(500) NOT NULL,
  580. file_type VARCHAR(50),
  581. file_size BIGINT,
  582. sort_order INT DEFAULT 0,
  583. saved_to_knowledge_base BOOLEAN DEFAULT FALSE,
  584. knowledge_base_item_id VARCHAR(36),
  585. uploaded_by VARCHAR(36) REFERENCES users(id) ON DELETE SET NULL,
  586. create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP
  587. );
  588. CREATE INDEX IF NOT EXISTS idx_report_attachments_report ON report_attachments(report_id);
  589. -- ==================== 报告占位符定义表 ====================
  590. CREATE TABLE IF NOT EXISTS placeholder_definitions (
  591. id VARCHAR(36) PRIMARY KEY,
  592. report_type VARCHAR(100),
  593. placeholder_key VARCHAR(200) NOT NULL,
  594. placeholder_group VARCHAR(50),
  595. source_table VARCHAR(100) NOT NULL,
  596. source_column VARCHAR(100) NOT NULL,
  597. description VARCHAR(500),
  598. example_value TEXT,
  599. sort_order INT DEFAULT 0,
  600. is_active BOOLEAN DEFAULT TRUE,
  601. create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  602. update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  603. UNIQUE(placeholder_key)
  604. );
  605. CREATE INDEX IF NOT EXISTS idx_placeholder_definitions_group ON placeholder_definitions(placeholder_group);
  606. CREATE INDEX IF NOT EXISTS idx_placeholder_definitions_report_type ON placeholder_definitions(report_type);
  607. -- ==================== 预置数据 ====================
  608. INSERT INTO entity_types (id, type_code, type_name, category, color, icon, description, sort_order) VALUES
  609. ('et-001', 'PERSON', '人名', 'basic', '#1890ff', 'user', '人物姓名,如:张经理、李总', 1),
  610. ('et-002', 'ORG', '机构', 'basic', '#faad14', 'bank', '组织机构,如:成都检测公司、环保局', 2),
  611. ('et-003', 'LOC', '地点', 'basic', '#52c41a', 'environment', '地理位置,如:成都市高新区', 3),
  612. ('et-004', 'DATE', '日期', 'basic', '#722ed1', 'calendar', '日期时间,如:2024年5月15日', 4),
  613. ('et-005', 'NUMBER', '数值', 'basic', '#13c2c2', 'number', '数值数量,如:50分贝、100万元', 5),
  614. ('et-006', 'DEVICE', '设备', 'domain', '#eb2f96', 'tool', '设备仪器,如:噪音检测设备、光谱仪', 10),
  615. ('et-007', 'PROJECT', '项目', 'domain', '#f5222d', 'project', '项目名称,如:环境监测项目', 11),
  616. ('et-008', 'TERM', '术语', 'domain', '#a0d911', 'book', '专业术语,如:COD、BOD、PM2.5', 12),
  617. ('et-009', 'STANDARD', '标准', 'domain', '#2f54eb', 'file-text', '标准规范,如:GB 3096-2008', 13),
  618. ('et-010', 'MATERIAL', '材料', 'domain', '#fa8c16', 'experiment', '材料物质,如:甲醛、苯', 14),
  619. ('et-011', 'METHOD', '方法', 'domain', '#1890ff', 'api', '检测方法,如:气相色谱法', 15)
  620. ON CONFLICT (id) DO NOTHING;
  621. INSERT INTO relation_types (id, type_code, type_name, source_entity_types, target_entity_types, is_symmetric, description) VALUES
  622. ('rt-001', 'LOCATED_IN', '位于', '["ORG", "PERSON", "PROJECT"]', '["LOC"]', false, '实体位于某地'),
  623. ('rt-002', 'WORKS_FOR', '任职于', '["PERSON"]', '["ORG"]', false, '人员任职于机构'),
  624. ('rt-003', 'BELONGS_TO', '属于', '["ORG", "PROJECT"]', '["ORG"]', false, '隶属关系'),
  625. ('rt-004', 'RESPONSIBLE_FOR', '负责', '["PERSON", "ORG"]', '["PROJECT", "LOC"]', false, '负责某事/某地'),
  626. ('rt-005', 'USES', '使用', '["ORG", "PERSON", "PROJECT"]', '["DEVICE", "METHOD"]', false, '使用设备/方法'),
  627. ('rt-006', 'DETECTS', '检测', '["ORG", "PERSON", "DEVICE"]', '["MATERIAL", "TERM"]', false, '检测某物质/指标'),
  628. ('rt-007', 'CONTAINS', '包含', '["PROJECT", "ORG"]', '["PROJECT", "TERM", "MATERIAL"]', false, '包含关系'),
  629. ('rt-008', 'COMPLIES_WITH', '符合', '["PROJECT", "ORG", "METHOD"]', '["STANDARD"]', false, '符合某标准'),
  630. ('rt-009', 'PRODUCES', '产生', '["ORG", "PROJECT", "DEVICE"]', '["NUMBER", "MATERIAL"]', false, '产生数据/物质'),
  631. ('rt-010', 'COOPERATES', '合作', '["ORG"]', '["ORG"]', true, '机构合作关系'),
  632. ('rt-011', 'OCCURS_AT', '发生于', '["PROJECT"]', '["DATE"]', false, '发生在某时间')
  633. ON CONFLICT (id) DO NOTHING;