init_mock.sql 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588
  1. -- ============================================================
  2. -- 灵越智报 2.0 - 数据库初始化 & Mock数据
  3. -- 场景: 成都院-安全生产标准化复审报告
  4. -- 生成时间: 2026-02-12
  5. -- ============================================================
  6. -- 使用事务确保原子性
  7. BEGIN;
  8. -- ============================================================
  9. -- 0. 扩展(可选)
  10. -- ============================================================
  11. CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
  12. DO $$
  13. BEGIN
  14. IF EXISTS (SELECT 1 FROM pg_available_extensions WHERE name = 'vector') THEN
  15. EXECUTE 'CREATE EXTENSION IF NOT EXISTS vector';
  16. ELSE
  17. RAISE NOTICE 'pgvector extension not installed, skip vector features';
  18. END IF;
  19. END $$;
  20. -- ============================================================
  21. -- 0.x 基础业务表(auth/document/parse/ai/extract)
  22. -- ============================================================
  23. -- 用户与会话
  24. CREATE TABLE IF NOT EXISTS users (
  25. id VARCHAR(36) PRIMARY KEY,
  26. username VARCHAR(50) NOT NULL UNIQUE,
  27. email VARCHAR(100) UNIQUE,
  28. password_hash VARCHAR(255) NOT NULL,
  29. display_name VARCHAR(100),
  30. avatar_url VARCHAR(500),
  31. role VARCHAR(20) DEFAULT 'user',
  32. preferences TEXT DEFAULT '{}',
  33. is_active BOOLEAN DEFAULT TRUE,
  34. last_login_at TIMESTAMP,
  35. create_by VARCHAR(36),
  36. create_by_name VARCHAR(100),
  37. create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  38. update_by VARCHAR(36),
  39. update_by_name VARCHAR(100),
  40. update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP
  41. );
  42. CREATE INDEX IF NOT EXISTS idx_users_username ON users(username);
  43. CREATE INDEX IF NOT EXISTS idx_users_email ON users(email);
  44. CREATE TABLE IF NOT EXISTS sessions (
  45. id VARCHAR(36) PRIMARY KEY,
  46. user_id VARCHAR(36) NOT NULL REFERENCES users(id) ON DELETE CASCADE,
  47. token_hash VARCHAR(255) NOT NULL,
  48. refresh_token_hash VARCHAR(255),
  49. expires_at TIMESTAMP,
  50. ip_address VARCHAR(100),
  51. user_agent TEXT,
  52. last_used_at TIMESTAMP,
  53. create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP
  54. );
  55. CREATE INDEX IF NOT EXISTS idx_sessions_user ON sessions(user_id);
  56. -- 文档与解析
  57. CREATE TABLE IF NOT EXISTS documents (
  58. id VARCHAR(36) PRIMARY KEY,
  59. user_id VARCHAR(36) NOT NULL REFERENCES users(id) ON DELETE CASCADE,
  60. name VARCHAR(255) NOT NULL,
  61. file_name VARCHAR(500) NOT NULL,
  62. file_path VARCHAR(500) NOT NULL,
  63. file_size BIGINT,
  64. file_type VARCHAR(20) NOT NULL,
  65. status VARCHAR(20) DEFAULT 'uploaded',
  66. parsed_text TEXT,
  67. page_count INT,
  68. word_count INT,
  69. entity_count INT DEFAULT 0,
  70. relation_count INT DEFAULT 0,
  71. rule_count INT DEFAULT 0,
  72. metadata JSONB DEFAULT '{}',
  73. del_flag BOOLEAN DEFAULT FALSE,
  74. create_by VARCHAR(36),
  75. create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  76. update_by VARCHAR(36),
  77. update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP
  78. );
  79. CREATE INDEX IF NOT EXISTS idx_documents_user ON documents(user_id);
  80. CREATE INDEX IF NOT EXISTS idx_documents_type ON documents(file_type);
  81. CREATE INDEX IF NOT EXISTS idx_documents_status ON documents(status);
  82. CREATE TABLE IF NOT EXISTS document_sections (
  83. id VARCHAR(36) PRIMARY KEY,
  84. document_id VARCHAR(36) NOT NULL REFERENCES documents(id) ON DELETE CASCADE,
  85. parent_id VARCHAR(36) REFERENCES document_sections(id) ON DELETE CASCADE,
  86. section_index INT NOT NULL,
  87. level INT NOT NULL DEFAULT 1,
  88. title VARCHAR(500),
  89. content TEXT,
  90. start_page INT,
  91. end_page INT,
  92. start_char INT,
  93. end_char INT,
  94. section_type VARCHAR(32) DEFAULT 'heading',
  95. table_data JSONB,
  96. image_path VARCHAR(500),
  97. image_caption VARCHAR(500),
  98. metadata JSONB DEFAULT '{}',
  99. sort_order INT DEFAULT 0,
  100. create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP
  101. );
  102. CREATE INDEX IF NOT EXISTS idx_doc_sections_document ON document_sections(document_id);
  103. CREATE INDEX IF NOT EXISTS idx_doc_sections_parent ON document_sections(parent_id);
  104. CREATE INDEX IF NOT EXISTS idx_doc_sections_level ON document_sections(level);
  105. CREATE INDEX IF NOT EXISTS idx_doc_sections_type ON document_sections(section_type);
  106. CREATE TABLE IF NOT EXISTS document_chunks (
  107. id VARCHAR(36) PRIMARY KEY,
  108. document_id VARCHAR(36) NOT NULL REFERENCES documents(id) ON DELETE CASCADE,
  109. section_id VARCHAR(36) REFERENCES document_sections(id) ON DELETE SET NULL,
  110. chunk_index INT NOT NULL,
  111. content TEXT NOT NULL,
  112. start_char INT,
  113. end_char INT,
  114. page_number INT,
  115. token_count INT,
  116. metadata JSONB DEFAULT '{}',
  117. create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP
  118. );
  119. CREATE INDEX IF NOT EXISTS idx_doc_chunks_document ON document_chunks(document_id);
  120. CREATE INDEX IF NOT EXISTS idx_doc_chunks_section ON document_chunks(section_id);
  121. CREATE TABLE IF NOT EXISTS parse_tasks (
  122. id VARCHAR(36) PRIMARY KEY,
  123. document_id VARCHAR(36) NOT NULL REFERENCES documents(id) ON DELETE CASCADE,
  124. status VARCHAR(20) DEFAULT 'pending',
  125. progress INT DEFAULT 0,
  126. current_step VARCHAR(32),
  127. error_message TEXT,
  128. options JSONB DEFAULT '{}',
  129. started_at TIMESTAMP,
  130. completed_at TIMESTAMP,
  131. parse_status VARCHAR(20) DEFAULT 'pending',
  132. parse_progress INT DEFAULT 0,
  133. rag_status VARCHAR(20) DEFAULT 'pending',
  134. rag_progress INT DEFAULT 0,
  135. structured_status VARCHAR(20) DEFAULT 'pending',
  136. structured_progress INT DEFAULT 0,
  137. structured_element_count INT,
  138. structured_image_count INT,
  139. structured_table_count INT,
  140. ner_status VARCHAR(20) DEFAULT 'pending',
  141. ner_progress INT DEFAULT 0,
  142. ner_task_id VARCHAR(100),
  143. ner_entity_count INT,
  144. ner_relation_count INT,
  145. ner_message TEXT,
  146. graph_status VARCHAR(20) DEFAULT 'pending',
  147. graph_progress INT DEFAULT 0,
  148. create_by VARCHAR(36),
  149. create_by_name VARCHAR(100),
  150. create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  151. update_by VARCHAR(36),
  152. update_by_name VARCHAR(100),
  153. update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP
  154. );
  155. CREATE INDEX IF NOT EXISTS idx_parse_tasks_document ON parse_tasks(document_id);
  156. CREATE TABLE IF NOT EXISTS document_elements (
  157. id VARCHAR(36) PRIMARY KEY,
  158. document_id VARCHAR(36) NOT NULL REFERENCES documents(id) ON DELETE CASCADE,
  159. element_index INT,
  160. element_type VARCHAR(50),
  161. content TEXT,
  162. style JSONB DEFAULT '{}',
  163. runs JSONB DEFAULT '[]',
  164. image_url VARCHAR(500),
  165. image_path VARCHAR(500),
  166. image_alt VARCHAR(500),
  167. image_width INT,
  168. image_height INT,
  169. image_format VARCHAR(20),
  170. table_index INT,
  171. table_data JSONB,
  172. table_row_count INT,
  173. table_col_count INT,
  174. table_text TEXT,
  175. create_by VARCHAR(36),
  176. create_by_name VARCHAR(100),
  177. create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  178. update_by VARCHAR(36),
  179. update_by_name VARCHAR(100),
  180. update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP
  181. );
  182. CREATE INDEX IF NOT EXISTS idx_document_elements_document ON document_elements(document_id);
  183. CREATE TABLE IF NOT EXISTS document_blocks (
  184. id VARCHAR(36) PRIMARY KEY,
  185. document_id VARCHAR(36) NOT NULL REFERENCES documents(id) ON DELETE CASCADE,
  186. parent_id VARCHAR(36),
  187. children JSONB DEFAULT '[]',
  188. block_index INT,
  189. block_type VARCHAR(50),
  190. text_elements JSONB DEFAULT '[]',
  191. table_data JSONB,
  192. image_path VARCHAR(500),
  193. image_url VARCHAR(500),
  194. metadata JSONB DEFAULT '{}',
  195. create_by VARCHAR(36),
  196. create_by_name VARCHAR(100),
  197. create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  198. update_by VARCHAR(36),
  199. update_by_name VARCHAR(100),
  200. update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP
  201. );
  202. CREATE INDEX IF NOT EXISTS idx_document_blocks_document ON document_blocks(document_id);
  203. -- AI 相关
  204. CREATE TABLE IF NOT EXISTS elements (
  205. id VARCHAR(36) PRIMARY KEY,
  206. document_id VARCHAR(36) REFERENCES documents(id) ON DELETE CASCADE,
  207. user_id VARCHAR(36) REFERENCES users(id) ON DELETE SET NULL,
  208. type VARCHAR(50),
  209. label VARCHAR(200),
  210. value TEXT,
  211. position JSONB DEFAULT '{}',
  212. confidence DECIMAL(10,4),
  213. extraction_method VARCHAR(50),
  214. graph_node_id VARCHAR(36),
  215. metadata JSONB DEFAULT '{}',
  216. create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  217. update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP
  218. );
  219. CREATE INDEX IF NOT EXISTS idx_elements_document ON elements(document_id);
  220. CREATE TABLE IF NOT EXISTS annotations (
  221. id VARCHAR(36) PRIMARY KEY,
  222. document_id VARCHAR(36) REFERENCES documents(id) ON DELETE CASCADE,
  223. user_id VARCHAR(36) REFERENCES users(id) ON DELETE SET NULL,
  224. text TEXT,
  225. position JSONB DEFAULT '{}',
  226. type VARCHAR(50),
  227. suggestion TEXT,
  228. ai_generated BOOLEAN DEFAULT FALSE,
  229. confidence DECIMAL(10,4),
  230. status VARCHAR(20) DEFAULT 'pending',
  231. create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  232. update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP
  233. );
  234. CREATE INDEX IF NOT EXISTS idx_annotations_document ON annotations(document_id);
  235. CREATE TABLE IF NOT EXISTS embeddings (
  236. id VARCHAR(36) PRIMARY KEY,
  237. chunk_id VARCHAR(36) NOT NULL REFERENCES document_chunks(id) ON DELETE CASCADE,
  238. embedding vector(1536),
  239. model_name VARCHAR(100) DEFAULT 'text-embedding-ada-002',
  240. model_version VARCHAR(50),
  241. create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP
  242. );
  243. CREATE INDEX IF NOT EXISTS idx_embeddings_chunk ON embeddings(chunk_id);
  244. CREATE INDEX IF NOT EXISTS idx_embeddings_vector ON embeddings USING ivfflat (embedding vector_cosine_ops) WITH (lists = 100);
  245. -- 提取与模板
  246. CREATE TABLE IF NOT EXISTS extract_projects (
  247. id VARCHAR(36) PRIMARY KEY,
  248. user_id VARCHAR(36) NOT NULL REFERENCES users(id) ON DELETE CASCADE,
  249. name VARCHAR(200) NOT NULL,
  250. description TEXT,
  251. status VARCHAR(50) DEFAULT 'draft',
  252. config JSONB DEFAULT '{}',
  253. create_by VARCHAR(36),
  254. create_by_name VARCHAR(100),
  255. create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  256. update_by VARCHAR(36),
  257. update_by_name VARCHAR(100),
  258. update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP
  259. );
  260. CREATE INDEX IF NOT EXISTS idx_extract_projects_user ON extract_projects(user_id);
  261. CREATE TABLE IF NOT EXISTS rules (
  262. id VARCHAR(36) PRIMARY KEY,
  263. document_id VARCHAR(36) REFERENCES documents(id) ON DELETE SET NULL,
  264. user_id VARCHAR(36) NOT NULL REFERENCES users(id) ON DELETE CASCADE,
  265. name VARCHAR(200) NOT NULL,
  266. description TEXT,
  267. category VARCHAR(50),
  268. rule_type VARCHAR(32) NOT NULL,
  269. source VARCHAR(32) DEFAULT 'auto',
  270. priority INT DEFAULT 0,
  271. status VARCHAR(20) DEFAULT 'draft',
  272. embedding vector(1536),
  273. is_global BOOLEAN DEFAULT FALSE,
  274. del_flag BOOLEAN DEFAULT FALSE,
  275. create_by VARCHAR(36),
  276. create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  277. update_by VARCHAR(36),
  278. update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP
  279. );
  280. CREATE INDEX IF NOT EXISTS idx_rules_document ON rules(document_id);
  281. CREATE INDEX IF NOT EXISTS idx_rules_user ON rules(user_id);
  282. CREATE TABLE IF NOT EXISTS templates (
  283. id VARCHAR(36) PRIMARY KEY,
  284. user_id VARCHAR(36) NOT NULL,
  285. name VARCHAR(200),
  286. description TEXT,
  287. base_document_id VARCHAR(36),
  288. status VARCHAR(20) DEFAULT 'draft',
  289. config JSONB DEFAULT '{}',
  290. is_public BOOLEAN DEFAULT FALSE,
  291. use_count INT DEFAULT 0,
  292. rating DOUBLE PRECISION,
  293. create_by VARCHAR(36),
  294. create_by_name VARCHAR(100),
  295. create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  296. update_by VARCHAR(36),
  297. update_by_name VARCHAR(100),
  298. update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP
  299. );
  300. CREATE INDEX IF NOT EXISTS idx_templates_user ON templates(user_id);
  301. CREATE TABLE IF NOT EXISTS variables (
  302. id VARCHAR(36) PRIMARY KEY,
  303. template_id VARCHAR(36) NOT NULL REFERENCES templates(id) ON DELETE CASCADE,
  304. name VARCHAR(100) NOT NULL,
  305. display_name VARCHAR(200),
  306. variable_group VARCHAR(100),
  307. category VARCHAR(50),
  308. location JSONB,
  309. example_value TEXT,
  310. value_type VARCHAR(20),
  311. source_file_alias VARCHAR(100),
  312. source_type VARCHAR(30),
  313. source_config JSONB DEFAULT '{}',
  314. extract_type VARCHAR(30),
  315. extract_config JSONB DEFAULT '{}',
  316. display_order INT DEFAULT 0,
  317. create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  318. update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP
  319. );
  320. CREATE INDEX IF NOT EXISTS idx_variables_template ON variables(template_id);
  321. CREATE TABLE IF NOT EXISTS source_files (
  322. id VARCHAR(36) PRIMARY KEY,
  323. template_id VARCHAR(36) NOT NULL REFERENCES templates(id) ON DELETE CASCADE,
  324. alias VARCHAR(100) NOT NULL,
  325. description TEXT,
  326. file_types JSONB DEFAULT '[]',
  327. required BOOLEAN DEFAULT TRUE,
  328. example_document_id VARCHAR(36),
  329. display_order INT DEFAULT 0,
  330. create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP
  331. );
  332. CREATE INDEX IF NOT EXISTS idx_source_files_template ON source_files(template_id);
  333. -- 报告/附件
  334. CREATE TABLE IF NOT EXISTS reports (
  335. id VARCHAR(36) PRIMARY KEY,
  336. user_id VARCHAR(36) NOT NULL REFERENCES users(id) ON DELETE CASCADE,
  337. project_id VARCHAR(36),
  338. title VARCHAR(500) NOT NULL,
  339. report_type VARCHAR(100),
  340. status VARCHAR(20) NOT NULL DEFAULT 'draft',
  341. content_template TEXT,
  342. content_rendered TEXT,
  343. auto_saved_at TIMESTAMP,
  344. report_score DECIMAL(10,2),
  345. report_level VARCHAR(50),
  346. report_metrics JSONB DEFAULT '{}',
  347. generation_id VARCHAR(36),
  348. source_document_id VARCHAR(36),
  349. archived_at TIMESTAMP,
  350. published_at TIMESTAMP,
  351. del_flag BOOLEAN DEFAULT FALSE,
  352. create_by VARCHAR(36),
  353. create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  354. update_by VARCHAR(36),
  355. update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP
  356. );
  357. CREATE INDEX IF NOT EXISTS idx_reports_user ON reports(user_id);
  358. CREATE INDEX IF NOT EXISTS idx_reports_status ON reports(status);
  359. CREATE TABLE IF NOT EXISTS report_attachments (
  360. id VARCHAR(36) PRIMARY KEY,
  361. report_id VARCHAR(36) NOT NULL REFERENCES reports(id) ON DELETE CASCADE,
  362. display_name VARCHAR(255),
  363. file_name VARCHAR(500) NOT NULL,
  364. file_path VARCHAR(500) NOT NULL,
  365. file_type VARCHAR(50),
  366. file_size BIGINT,
  367. sort_order INT DEFAULT 0,
  368. saved_to_knowledge_base BOOLEAN DEFAULT FALSE,
  369. knowledge_base_item_id VARCHAR(36),
  370. uploaded_by VARCHAR(36) REFERENCES users(id) ON DELETE SET NULL,
  371. create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP
  372. );
  373. CREATE INDEX IF NOT EXISTS idx_report_attachments_report ON report_attachments(report_id);
  374. -- ============================================================
  375. -- 1. 建表 (DDL)
  376. -- ============================================================
  377. -- 1.1 节点类型定义表
  378. CREATE TABLE IF NOT EXISTS node_types (
  379. id SERIAL PRIMARY KEY,
  380. type_code VARCHAR(50) NOT NULL UNIQUE,
  381. type_name VARCHAR(100) NOT NULL,
  382. description TEXT,
  383. icon VARCHAR(100),
  384. color VARCHAR(20),
  385. created_at TIMESTAMP DEFAULT NOW()
  386. );
  387. -- 1.2 关系类型定义表
  388. CREATE TABLE IF NOT EXISTS edge_types (
  389. id SERIAL PRIMARY KEY,
  390. type_code VARCHAR(50) NOT NULL UNIQUE,
  391. type_name VARCHAR(100) NOT NULL,
  392. from_node_type VARCHAR(50),
  393. to_node_type VARCHAR(50),
  394. description TEXT,
  395. created_at TIMESTAMP DEFAULT NOW()
  396. );
  397. -- 1.3 节点表(核心)
  398. CREATE TABLE IF NOT EXISTS nodes (
  399. id BIGSERIAL PRIMARY KEY,
  400. node_type VARCHAR(50) NOT NULL,
  401. node_key VARCHAR(200),
  402. name VARCHAR(500) NOT NULL,
  403. status VARCHAR(50) DEFAULT 'active',
  404. created_by BIGINT,
  405. created_at TIMESTAMP DEFAULT NOW(),
  406. updated_at TIMESTAMP DEFAULT NOW()
  407. );
  408. -- 1.4 关系表(核心)
  409. CREATE TABLE IF NOT EXISTS edges (
  410. id BIGSERIAL PRIMARY KEY,
  411. edge_type VARCHAR(50) NOT NULL,
  412. from_node_id BIGINT NOT NULL REFERENCES nodes(id),
  413. to_node_id BIGINT NOT NULL REFERENCES nodes(id),
  414. sort_order INT DEFAULT 0,
  415. created_at TIMESTAMP DEFAULT NOW()
  416. );
  417. -- 1.5 节点属性表
  418. CREATE TABLE IF NOT EXISTS node_properties (
  419. id BIGSERIAL PRIMARY KEY,
  420. node_id BIGINT NOT NULL REFERENCES nodes(id),
  421. prop_key VARCHAR(100) NOT NULL,
  422. prop_value TEXT,
  423. prop_json JSONB,
  424. prop_number DECIMAL(20,4),
  425. prop_date TIMESTAMP,
  426. created_at TIMESTAMP DEFAULT NOW(),
  427. updated_at TIMESTAMP DEFAULT NOW()
  428. );
  429. -- 1.6 关系属性表
  430. CREATE TABLE IF NOT EXISTS edge_properties (
  431. id BIGSERIAL PRIMARY KEY,
  432. edge_id BIGINT NOT NULL REFERENCES edges(id),
  433. prop_key VARCHAR(100) NOT NULL,
  434. prop_value TEXT,
  435. prop_json JSONB,
  436. created_at TIMESTAMP DEFAULT NOW()
  437. );
  438. -- 1.7 属性定义表
  439. CREATE TABLE IF NOT EXISTS property_definitions (
  440. id SERIAL PRIMARY KEY,
  441. owner_type VARCHAR(20) NOT NULL,
  442. target_type VARCHAR(50) NOT NULL,
  443. prop_key VARCHAR(100) NOT NULL,
  444. prop_name VARCHAR(200) NOT NULL,
  445. data_type VARCHAR(50) NOT NULL,
  446. required BOOLEAN DEFAULT false,
  447. default_value TEXT,
  448. description TEXT,
  449. created_at TIMESTAMP DEFAULT NOW()
  450. );
  451. -- ============================================================
  452. -- 1.x 兼容字段与触发器(兼容后端实体字段命名)
  453. -- ============================================================
  454. -- node_properties: 兼容 graph-service 使用 prop_text 字段
  455. ALTER TABLE node_properties ADD COLUMN IF NOT EXISTS prop_text TEXT;
  456. CREATE OR REPLACE FUNCTION sync_node_properties_text() RETURNS trigger AS $$
  457. BEGIN
  458. IF NEW.prop_text IS NULL AND NEW.prop_value IS NOT NULL THEN
  459. NEW.prop_text := NEW.prop_value;
  460. ELSIF NEW.prop_value IS NULL AND NEW.prop_text IS NOT NULL THEN
  461. NEW.prop_value := NEW.prop_text;
  462. END IF;
  463. RETURN NEW;
  464. END;
  465. $$ LANGUAGE plpgsql;
  466. DROP TRIGGER IF EXISTS trg_sync_node_properties_text ON node_properties;
  467. CREATE TRIGGER trg_sync_node_properties_text
  468. BEFORE INSERT OR UPDATE ON node_properties
  469. FOR EACH ROW EXECUTE FUNCTION sync_node_properties_text();
  470. -- edge_properties: 兼容 graph-service 使用 prop_text 字段
  471. ALTER TABLE edge_properties ADD COLUMN IF NOT EXISTS prop_text TEXT;
  472. CREATE OR REPLACE FUNCTION sync_edge_properties_text() RETURNS trigger AS $$
  473. BEGIN
  474. IF NEW.prop_text IS NULL AND NEW.prop_value IS NOT NULL THEN
  475. NEW.prop_text := NEW.prop_value;
  476. ELSIF NEW.prop_value IS NULL AND NEW.prop_text IS NOT NULL THEN
  477. NEW.prop_value := NEW.prop_text;
  478. END IF;
  479. RETURN NEW;
  480. END;
  481. $$ LANGUAGE plpgsql;
  482. DROP TRIGGER IF EXISTS trg_sync_edge_properties_text ON edge_properties;
  483. CREATE TRIGGER trg_sync_edge_properties_text
  484. BEFORE INSERT OR UPDATE ON edge_properties
  485. FOR EACH ROW EXECUTE FUNCTION sync_edge_properties_text();
  486. -- property_definitions: 兼容 graph-service 使用 type_code/is_required 字段
  487. ALTER TABLE property_definitions ADD COLUMN IF NOT EXISTS type_code VARCHAR(50);
  488. ALTER TABLE property_definitions ADD COLUMN IF NOT EXISTS is_required BOOLEAN;
  489. CREATE OR REPLACE FUNCTION sync_property_definitions_fields() RETURNS trigger AS $$
  490. BEGIN
  491. IF NEW.type_code IS NULL AND NEW.target_type IS NOT NULL THEN
  492. NEW.type_code := NEW.target_type;
  493. ELSIF NEW.target_type IS NULL AND NEW.type_code IS NOT NULL THEN
  494. NEW.target_type := NEW.type_code;
  495. END IF;
  496. IF NEW.is_required IS NULL AND NEW.required IS NOT NULL THEN
  497. NEW.is_required := NEW.required;
  498. ELSIF NEW.required IS NULL AND NEW.is_required IS NOT NULL THEN
  499. NEW.required := NEW.is_required;
  500. END IF;
  501. RETURN NEW;
  502. END;
  503. $$ LANGUAGE plpgsql;
  504. DROP TRIGGER IF EXISTS trg_sync_property_definitions_fields ON property_definitions;
  505. CREATE TRIGGER trg_sync_property_definitions_fields
  506. BEFORE INSERT OR UPDATE ON property_definitions
  507. FOR EACH ROW EXECUTE FUNCTION sync_property_definitions_fields();
  508. -- ============================================================
  509. -- ============================================================
  510. -- 初始化管理员账号
  511. -- ============================================================
  512. INSERT INTO users (
  513. id,
  514. username,
  515. email,
  516. password_hash,
  517. display_name,
  518. role,
  519. is_active
  520. ) VALUES (
  521. '1',
  522. 'admin',
  523. 'admin@lingyue.com',
  524. '$2a$10$0AUCG2mG7a6JXErOTI.Pg.Q/R04plOXvc.TDMeWzwwZQ23ZmrtJxC',
  525. '管理员',
  526. 'admin',
  527. true
  528. ) ON CONFLICT (username) DO UPDATE SET
  529. password_hash = EXCLUDED.password_hash,
  530. email = EXCLUDED.email,
  531. display_name = EXCLUDED.display_name,
  532. role = EXCLUDED.role;
  533. -- ============================================================
  534. -- 提交事务
  535. -- ============================================================
  536. COMMIT;
  537. -- ============================================================
  538. -- 验证数据
  539. -- ============================================================
  540. SELECT '数据库初始化完成' as message;
  541. SELECT COUNT(*) as node_count FROM nodes;
  542. SELECT COUNT(*) as template_count FROM templates;
  543. SELECT COUNT(*) as user_count FROM users;