init_0211_full.sql 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684
  1. -- ============================================================
  2. -- 灵越智报 2.0 数据库完整脚本
  3. -- 基于 2026-02-11 会议讨论设计
  4. --
  5. -- 核心概念:
  6. -- - 静态要素:模板中固定不变的文本
  7. -- - 动态要素:需要通过规则计算填充的内容
  8. -- - 占位符:动态要素在模板中的标识符
  9. -- ============================================================
  10. -- ============================================================
  11. -- 1. 基础表
  12. -- ============================================================
  13. -- ------------------------------------------------------------
  14. -- 1.1 users - 用户表
  15. -- ------------------------------------------------------------
  16. CREATE TABLE IF NOT EXISTS users (
  17. id BIGSERIAL PRIMARY KEY,
  18. username VARCHAR(100) NOT NULL UNIQUE,
  19. password_hash VARCHAR(255) NOT NULL,
  20. email VARCHAR(200),
  21. phone VARCHAR(20),
  22. real_name VARCHAR(100),
  23. avatar_url VARCHAR(500),
  24. status VARCHAR(50) DEFAULT 'active',
  25. created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  26. updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
  27. );
  28. COMMENT ON TABLE users IS '用户表';
  29. COMMENT ON COLUMN users.status IS '状态: active/disabled';
  30. -- ------------------------------------------------------------
  31. -- 1.2 projects - 项目表
  32. -- ------------------------------------------------------------
  33. CREATE TABLE IF NOT EXISTS projects (
  34. id BIGSERIAL PRIMARY KEY,
  35. name VARCHAR(200) NOT NULL,
  36. code VARCHAR(100),
  37. description TEXT,
  38. status VARCHAR(50) DEFAULT 'active',
  39. owner_id BIGINT REFERENCES users(id),
  40. created_by BIGINT REFERENCES users(id),
  41. created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  42. updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
  43. );
  44. COMMENT ON TABLE projects IS '项目表';
  45. -- ============================================================
  46. -- 2. 模板相关表
  47. -- ============================================================
  48. -- ------------------------------------------------------------
  49. -- 2.1 report_templates - 报告模板表
  50. -- ------------------------------------------------------------
  51. CREATE TABLE IF NOT EXISTS report_templates (
  52. id BIGSERIAL PRIMARY KEY,
  53. name VARCHAR(200) NOT NULL,
  54. category VARCHAR(100),
  55. description TEXT,
  56. content_html TEXT,
  57. content_json JSONB,
  58. dynamic_element_count INT DEFAULT 0,
  59. table_element_count INT DEFAULT 0,
  60. status VARCHAR(50) DEFAULT 'active',
  61. created_by BIGINT REFERENCES users(id),
  62. created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  63. updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
  64. );
  65. COMMENT ON TABLE report_templates IS '报告模板表';
  66. COMMENT ON COLUMN report_templates.dynamic_element_count IS '动态要素数量';
  67. COMMENT ON COLUMN report_templates.table_element_count IS '表格型动态要素数量';
  68. -- ------------------------------------------------------------
  69. -- 2.2 template_dynamic_elements - 模板动态要素定义表
  70. -- ------------------------------------------------------------
  71. CREATE TABLE IF NOT EXISTS template_dynamic_elements (
  72. id BIGSERIAL PRIMARY KEY,
  73. template_id BIGINT NOT NULL REFERENCES report_templates(id) ON DELETE CASCADE,
  74. element_key VARCHAR(100) NOT NULL,
  75. element_name VARCHAR(200) NOT NULL,
  76. element_type VARCHAR(50) NOT NULL,
  77. namespace VARCHAR(100),
  78. field_name VARCHAR(100),
  79. table_columns JSONB,
  80. required BOOLEAN DEFAULT false,
  81. default_value TEXT,
  82. description TEXT,
  83. sort_order INT DEFAULT 0,
  84. created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  85. UNIQUE(template_id, element_key)
  86. );
  87. COMMENT ON TABLE template_dynamic_elements IS '模板动态要素定义表';
  88. COMMENT ON COLUMN template_dynamic_elements.element_key IS '占位符key,如 basicInfo.projectCode 或 +review_status';
  89. COMMENT ON COLUMN template_dynamic_elements.element_type IS '类型: text/paragraph/table';
  90. COMMENT ON COLUMN template_dynamic_elements.table_columns IS '表格列定义JSON数组';
  91. -- ============================================================
  92. -- 3. 报告相关表
  93. -- ============================================================
  94. -- ------------------------------------------------------------
  95. -- 3.1 reports - 报告表
  96. -- ------------------------------------------------------------
  97. CREATE TABLE IF NOT EXISTS reports (
  98. id BIGSERIAL PRIMARY KEY,
  99. title VARCHAR(500) NOT NULL,
  100. report_type VARCHAR(100),
  101. template_id BIGINT REFERENCES report_templates(id),
  102. project_id BIGINT REFERENCES projects(id),
  103. content_html TEXT,
  104. status VARCHAR(50) DEFAULT 'draft',
  105. source_report_id BIGINT REFERENCES reports(id),
  106. copy_time TIMESTAMP,
  107. created_by BIGINT REFERENCES users(id),
  108. created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  109. updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
  110. );
  111. COMMENT ON TABLE reports IS '报告表';
  112. COMMENT ON COLUMN reports.status IS '状态: draft/published/archived';
  113. COMMENT ON COLUMN reports.source_report_id IS '源报告ID(复制来源)';
  114. -- ------------------------------------------------------------
  115. -- 3.2 element_values - 动态要素值表
  116. -- ------------------------------------------------------------
  117. CREATE TABLE IF NOT EXISTS element_values (
  118. id BIGSERIAL PRIMARY KEY,
  119. report_id BIGINT NOT NULL REFERENCES reports(id) ON DELETE CASCADE,
  120. element_key VARCHAR(100) NOT NULL,
  121. value_text TEXT,
  122. value_json JSONB,
  123. is_filled BOOLEAN DEFAULT false,
  124. fill_source VARCHAR(50),
  125. created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  126. updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  127. UNIQUE(report_id, element_key)
  128. );
  129. COMMENT ON TABLE element_values IS '动态要素值表';
  130. COMMENT ON COLUMN element_values.element_key IS '占位符key';
  131. COMMENT ON COLUMN element_values.value_text IS '文本值(text/paragraph类型)';
  132. COMMENT ON COLUMN element_values.value_json IS 'JSON值(table类型)';
  133. COMMENT ON COLUMN element_values.fill_source IS '填充来源: manual/rule/import';
  134. -- ------------------------------------------------------------
  135. -- 3.3 element_rules - 动态要素规则表
  136. -- ------------------------------------------------------------
  137. CREATE TABLE IF NOT EXISTS element_rules (
  138. id BIGSERIAL PRIMARY KEY,
  139. report_id BIGINT NOT NULL REFERENCES reports(id) ON DELETE CASCADE,
  140. element_key VARCHAR(100) NOT NULL,
  141. rule_name VARCHAR(200),
  142. description TEXT,
  143. rule_type VARCHAR(50) NOT NULL,
  144. last_output_text TEXT,
  145. last_output_json JSONB,
  146. last_run_status VARCHAR(50),
  147. last_run_time TIMESTAMP,
  148. last_run_error TEXT,
  149. dsl_content TEXT,
  150. status VARCHAR(50) DEFAULT 'active',
  151. created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  152. updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  153. UNIQUE(report_id, element_key)
  154. );
  155. COMMENT ON TABLE element_rules IS '动态要素规则表';
  156. COMMENT ON COLUMN element_rules.rule_type IS '类型: extraction/generation/calculation';
  157. COMMENT ON COLUMN element_rules.dsl_content IS 'DSL语法内容';
  158. -- ------------------------------------------------------------
  159. -- 3.4 rule_inputs - 规则输入表
  160. -- ------------------------------------------------------------
  161. CREATE TABLE IF NOT EXISTS rule_inputs (
  162. id BIGSERIAL PRIMARY KEY,
  163. rule_id BIGINT NOT NULL REFERENCES element_rules(id) ON DELETE CASCADE,
  164. input_key VARCHAR(50) NOT NULL,
  165. input_name VARCHAR(200) NOT NULL,
  166. input_type VARCHAR(50) NOT NULL,
  167. ref_attachment_id BIGINT,
  168. ref_entity_id BIGINT,
  169. ref_element_key VARCHAR(100),
  170. fixed_value TEXT,
  171. sort_order INT DEFAULT 0,
  172. created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
  173. );
  174. COMMENT ON TABLE rule_inputs IS '规则输入表';
  175. COMMENT ON COLUMN rule_inputs.input_type IS '类型: attachment_ref/entity_ref/element_ref/text/number';
  176. COMMENT ON COLUMN rule_inputs.ref_element_key IS '引用其他动态要素的key';
  177. -- ------------------------------------------------------------
  178. -- 3.5 rule_action_config - 规则动作配置表
  179. -- ------------------------------------------------------------
  180. CREATE TABLE IF NOT EXISTS rule_action_config (
  181. id BIGSERIAL PRIMARY KEY,
  182. rule_id BIGINT NOT NULL REFERENCES element_rules(id) ON DELETE CASCADE UNIQUE,
  183. action_type VARCHAR(50) NOT NULL,
  184. config JSONB NOT NULL DEFAULT '{}',
  185. created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  186. updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
  187. );
  188. COMMENT ON TABLE rule_action_config IS '规则动作配置表';
  189. COMMENT ON COLUMN rule_action_config.action_type IS '类型: extract_entity/extract_pattern/llm_generate/extract_table';
  190. -- ============================================================
  191. -- 4. 附件相关表
  192. -- ============================================================
  193. -- ------------------------------------------------------------
  194. -- 4.1 report_attachments - 报告附件表
  195. -- ------------------------------------------------------------
  196. CREATE TABLE IF NOT EXISTS report_attachments (
  197. id BIGSERIAL PRIMARY KEY,
  198. report_id BIGINT NOT NULL REFERENCES reports(id) ON DELETE CASCADE,
  199. display_name VARCHAR(200) NOT NULL,
  200. file_name VARCHAR(500) NOT NULL,
  201. file_path VARCHAR(1000) NOT NULL,
  202. file_type VARCHAR(50),
  203. file_size BIGINT,
  204. parse_status VARCHAR(50) DEFAULT 'pending',
  205. parsed_text TEXT,
  206. entity_count INT DEFAULT 0,
  207. parse_error TEXT,
  208. parsed_at TIMESTAMP,
  209. sort_order INT DEFAULT 0,
  210. created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  211. updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
  212. );
  213. COMMENT ON TABLE report_attachments IS '报告附件表';
  214. COMMENT ON COLUMN report_attachments.parse_status IS '解析状态: pending/processing/completed/failed';
  215. -- ------------------------------------------------------------
  216. -- 4.2 attachment_entities - 附件实体表
  217. -- ------------------------------------------------------------
  218. CREATE TABLE IF NOT EXISTS attachment_entities (
  219. id BIGSERIAL PRIMARY KEY,
  220. attachment_id BIGINT NOT NULL REFERENCES report_attachments(id) ON DELETE CASCADE,
  221. entity_type VARCHAR(50) NOT NULL,
  222. entity_text VARCHAR(500) NOT NULL,
  223. business_label VARCHAR(200),
  224. confidence DECIMAL(5,4) DEFAULT 1.0,
  225. occurrence_count INT DEFAULT 1,
  226. created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  227. updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
  228. );
  229. COMMENT ON TABLE attachment_entities IS '附件实体表';
  230. COMMENT ON COLUMN attachment_entities.entity_type IS '类型: ORG/PERSON/DATE/NUMBER/LOCATION';
  231. COMMENT ON COLUMN attachment_entities.business_label IS '业务标签';
  232. -- ============================================================
  233. -- 5. 其他表
  234. -- ============================================================
  235. -- ------------------------------------------------------------
  236. -- 5.1 report_copy_records - 报告复制记录表
  237. -- ------------------------------------------------------------
  238. CREATE TABLE IF NOT EXISTS report_copy_records (
  239. id BIGSERIAL PRIMARY KEY,
  240. source_report_id BIGINT NOT NULL REFERENCES reports(id),
  241. target_report_id BIGINT NOT NULL REFERENCES reports(id),
  242. copied_by BIGINT REFERENCES users(id),
  243. copy_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  244. elements_copied INT DEFAULT 0,
  245. rules_copied INT DEFAULT 0,
  246. notes TEXT
  247. );
  248. COMMENT ON TABLE report_copy_records IS '报告复制记录表';
  249. -- ============================================================
  250. -- 6. 视图
  251. -- ============================================================
  252. -- ------------------------------------------------------------
  253. -- 6.1 v_report_dynamic_elements - 报告动态要素完整视图
  254. -- ------------------------------------------------------------
  255. CREATE OR REPLACE VIEW v_report_dynamic_elements AS
  256. SELECT
  257. r.id AS report_id,
  258. r.title AS report_title,
  259. te.element_key,
  260. te.element_name,
  261. te.element_type,
  262. te.namespace,
  263. te.field_name,
  264. te.table_columns,
  265. te.required,
  266. ev.value_text,
  267. ev.value_json,
  268. ev.is_filled,
  269. ev.fill_source,
  270. er.id AS rule_id,
  271. er.rule_type,
  272. er.last_run_status,
  273. er.last_run_time,
  274. CASE WHEN er.id IS NOT NULL THEN true ELSE false END AS has_rule
  275. FROM reports r
  276. JOIN report_templates rt ON rt.id = r.template_id
  277. JOIN template_dynamic_elements te ON te.template_id = rt.id
  278. LEFT JOIN element_values ev ON ev.report_id = r.id AND ev.element_key = te.element_key
  279. LEFT JOIN element_rules er ON er.report_id = r.id AND er.element_key = te.element_key;
  280. COMMENT ON VIEW v_report_dynamic_elements IS '报告动态要素完整视图';
  281. -- ------------------------------------------------------------
  282. -- 6.2 v_rule_full_config - 规则完整配置视图
  283. -- ------------------------------------------------------------
  284. CREATE OR REPLACE VIEW v_rule_full_config AS
  285. SELECT
  286. er.id AS rule_id,
  287. er.report_id,
  288. er.element_key,
  289. er.rule_name,
  290. er.rule_type,
  291. er.last_output_text,
  292. er.last_output_json,
  293. er.last_run_status,
  294. er.dsl_content,
  295. er.status,
  296. ac.action_type,
  297. ac.config AS action_config,
  298. (
  299. SELECT json_agg(json_build_object(
  300. 'inputKey', ri.input_key,
  301. 'inputName', ri.input_name,
  302. 'inputType', ri.input_type,
  303. 'refAttachmentId', ri.ref_attachment_id,
  304. 'refEntityId', ri.ref_entity_id,
  305. 'refElementKey', ri.ref_element_key,
  306. 'fixedValue', ri.fixed_value
  307. ) ORDER BY ri.sort_order)
  308. FROM rule_inputs ri
  309. WHERE ri.rule_id = er.id
  310. ) AS inputs
  311. FROM element_rules er
  312. LEFT JOIN rule_action_config ac ON ac.rule_id = er.id;
  313. COMMENT ON VIEW v_rule_full_config IS '规则完整配置视图';
  314. -- ------------------------------------------------------------
  315. -- 6.3 v_report_summary - 报告摘要视图
  316. -- ------------------------------------------------------------
  317. CREATE OR REPLACE VIEW v_report_summary AS
  318. SELECT
  319. r.id,
  320. r.title,
  321. r.report_type,
  322. r.status,
  323. r.created_at,
  324. r.updated_at,
  325. rt.name AS template_name,
  326. p.name AS project_name,
  327. u.real_name AS created_by_name,
  328. (SELECT COUNT(*) FROM element_values ev WHERE ev.report_id = r.id AND ev.is_filled = true) AS filled_count,
  329. (SELECT COUNT(*) FROM template_dynamic_elements te WHERE te.template_id = r.template_id) AS total_elements,
  330. (SELECT COUNT(*) FROM report_attachments ra WHERE ra.report_id = r.id) AS attachment_count
  331. FROM reports r
  332. LEFT JOIN report_templates rt ON rt.id = r.template_id
  333. LEFT JOIN projects p ON p.id = r.project_id
  334. LEFT JOIN users u ON u.id = r.created_by;
  335. COMMENT ON VIEW v_report_summary IS '报告摘要视图';
  336. -- ============================================================
  337. -- 7. 索引
  338. -- ============================================================
  339. -- users
  340. CREATE INDEX IF NOT EXISTS idx_users_username ON users(username);
  341. CREATE INDEX IF NOT EXISTS idx_users_status ON users(status);
  342. -- projects
  343. CREATE INDEX IF NOT EXISTS idx_projects_owner ON projects(owner_id);
  344. CREATE INDEX IF NOT EXISTS idx_projects_status ON projects(status);
  345. -- report_templates
  346. CREATE INDEX IF NOT EXISTS idx_templates_category ON report_templates(category);
  347. CREATE INDEX IF NOT EXISTS idx_templates_status ON report_templates(status);
  348. -- template_dynamic_elements
  349. CREATE INDEX IF NOT EXISTS idx_template_elements_template ON template_dynamic_elements(template_id);
  350. CREATE INDEX IF NOT EXISTS idx_template_elements_type ON template_dynamic_elements(element_type);
  351. CREATE INDEX IF NOT EXISTS idx_template_elements_namespace ON template_dynamic_elements(namespace);
  352. -- reports
  353. CREATE INDEX IF NOT EXISTS idx_reports_template ON reports(template_id);
  354. CREATE INDEX IF NOT EXISTS idx_reports_project ON reports(project_id);
  355. CREATE INDEX IF NOT EXISTS idx_reports_status ON reports(status);
  356. CREATE INDEX IF NOT EXISTS idx_reports_created_by ON reports(created_by);
  357. CREATE INDEX IF NOT EXISTS idx_reports_source ON reports(source_report_id);
  358. -- element_values
  359. CREATE INDEX IF NOT EXISTS idx_element_values_report ON element_values(report_id);
  360. CREATE INDEX IF NOT EXISTS idx_element_values_key ON element_values(element_key);
  361. CREATE INDEX IF NOT EXISTS idx_element_values_filled ON element_values(is_filled);
  362. -- element_rules
  363. CREATE INDEX IF NOT EXISTS idx_element_rules_report ON element_rules(report_id);
  364. CREATE INDEX IF NOT EXISTS idx_element_rules_key ON element_rules(element_key);
  365. CREATE INDEX IF NOT EXISTS idx_element_rules_status ON element_rules(status);
  366. -- rule_inputs
  367. CREATE INDEX IF NOT EXISTS idx_rule_inputs_rule ON rule_inputs(rule_id);
  368. -- report_attachments
  369. CREATE INDEX IF NOT EXISTS idx_attachments_report ON report_attachments(report_id);
  370. CREATE INDEX IF NOT EXISTS idx_attachments_parse_status ON report_attachments(parse_status);
  371. -- attachment_entities
  372. CREATE INDEX IF NOT EXISTS idx_attachment_entities_attachment ON attachment_entities(attachment_id);
  373. CREATE INDEX IF NOT EXISTS idx_attachment_entities_type ON attachment_entities(entity_type);
  374. CREATE INDEX IF NOT EXISTS idx_attachment_entities_label ON attachment_entities(business_label);
  375. -- report_copy_records
  376. CREATE INDEX IF NOT EXISTS idx_copy_records_source ON report_copy_records(source_report_id);
  377. CREATE INDEX IF NOT EXISTS idx_copy_records_target ON report_copy_records(target_report_id);
  378. -- ============================================================
  379. -- 8. Mock 数据
  380. -- ============================================================
  381. -- ------------------------------------------------------------
  382. -- 8.1 用户数据
  383. -- ------------------------------------------------------------
  384. INSERT INTO users (id, username, password_hash, real_name, email, status)
  385. VALUES (1, 'admin', '$2a$10$xxxxx', '管理员', 'admin@lingyue.com', 'active')
  386. ON CONFLICT (id) DO NOTHING;
  387. SELECT setval('users_id_seq', GREATEST((SELECT MAX(id) FROM users), 1));
  388. -- ------------------------------------------------------------
  389. -- 8.2 项目数据
  390. -- ------------------------------------------------------------
  391. INSERT INTO projects (id, name, code, description, owner_id, created_by)
  392. VALUES (1, '电力安全评审项目', 'DLAQ-2026', '电力建设企业安全生产标准化评审项目', 1, 1)
  393. ON CONFLICT (id) DO NOTHING;
  394. SELECT setval('projects_id_seq', GREATEST((SELECT MAX(id) FROM projects), 1));
  395. -- ------------------------------------------------------------
  396. -- 8.3 模板数据
  397. -- ------------------------------------------------------------
  398. INSERT INTO report_templates (id, name, category, description, dynamic_element_count, table_element_count, status, created_by)
  399. VALUES (1, '电力安全生产标准化复审报告', '安全评审', '电力建设企业安全生产标准化达标评级评审报告模板', 45, 4, 'active', 1)
  400. ON CONFLICT (id) DO NOTHING;
  401. SELECT setval('report_templates_id_seq', GREATEST((SELECT MAX(id) FROM report_templates), 1));
  402. -- ------------------------------------------------------------
  403. -- 8.4 模板动态要素数据
  404. -- ------------------------------------------------------------
  405. -- 文本型动态要素
  406. INSERT INTO template_dynamic_elements (id, template_id, element_key, element_name, element_type, namespace, field_name, required, sort_order)
  407. VALUES
  408. (1, 1, 'basicInfo.projectCode', '项目编号', 'text', 'basicInfo', 'projectCode', true, 1),
  409. (2, 1, 'project.reviewObject', '评审对象', 'text', 'project', 'reviewObject', true, 2),
  410. (3, 1, 'project.reviewObjectAlias', '评审对象简称', 'text', 'project', 'reviewObjectAlias', true, 3),
  411. (4, 1, 'basicInfo.requestLevel', '申请级别', 'text', 'basicInfo', 'requestLevel', true, 4),
  412. (5, 1, 'project.resultScore', '评审得分', 'text', 'project', 'resultScore', true, 5),
  413. (6, 1, 'project.resultLevel', '评审级别', 'text', 'project', 'resultLevel', true, 6),
  414. (7, 1, 'project.workStartAt', '评审开始日期', 'text', 'project', 'workStartAt', true, 7),
  415. (8, 1, 'project.workEndAt', '评审结束日期', 'text', 'project', 'workEndAt', true, 8),
  416. (9, 1, 'project.createdAt', '报告日期', 'text', 'project', 'createdAt', true, 9),
  417. (10, 1, 'basicInfo.applyAt', '申请日期', 'text', 'basicInfo', 'applyAt', false, 10),
  418. (11, 1, 'project.reviewPeriod', '评审期', 'text', 'project', 'reviewPeriod', false, 11),
  419. (12, 1, 'basicInfo.reviewObjectCertificateGetAt', '证书获取日期', 'text', 'basicInfo', 'reviewObjectCertificateGetAt', false, 12),
  420. (13, 1, 'basicInfo.reviewObjectCertificate2GetAt', '二次证书获取日期', 'text', 'basicInfo', 'reviewObjectCertificate2GetAt', false, 13)
  421. ON CONFLICT (template_id, element_key) DO NOTHING;
  422. -- 段落型动态要素
  423. INSERT INTO template_dynamic_elements (id, template_id, element_key, element_name, element_type, namespace, field_name, required, sort_order)
  424. VALUES
  425. (20, 1, 'project.reviewObjectSummary', '评审对象概述', 'paragraph', 'project', 'reviewObjectSummary', true, 20),
  426. (21, 1, 'project.reviewObjectDescription', '企业简介', 'paragraph', 'project', 'reviewObjectDescription', true, 21),
  427. (22, 1, 'project.target', '目标', 'paragraph', 'project', 'target', true, 22),
  428. (23, 1, 'project.duty', '组织机构和职责', 'paragraph', 'project', 'duty', true, 23),
  429. (24, 1, 'project.fullParticipation', '全员参与', 'paragraph', 'project', 'fullParticipation', false, 24),
  430. (25, 1, 'project.safetyInvestment', '安全生产投入', 'paragraph', 'project', 'safetyInvestment', false, 25),
  431. (26, 1, 'project.safetyCulture', '安全文化建设', 'paragraph', 'project', 'safetyCulture', false, 26),
  432. (27, 1, 'project.systematicManagement', '制度化管理', 'paragraph', 'project', 'systematicManagement', false, 27),
  433. (28, 1, 'project.employeeTraining', '人员教育培训', 'paragraph', 'project', 'employeeTraining', false, 28),
  434. (29, 1, 'project.assetManagement', '设备设施管理', 'paragraph', 'project', 'assetManagement', false, 29),
  435. (30, 1, 'project.jobSafety', '作业安全', 'paragraph', 'project', 'jobSafety', false, 30),
  436. (31, 1, 'project.safetyStandardizationStatus', '安全生产标准化建设和持续运行情况', 'paragraph', 'project', 'safetyStandardizationStatus', false, 31)
  437. ON CONFLICT (template_id, element_key) DO NOTHING;
  438. -- 表格型动态要素
  439. INSERT INTO template_dynamic_elements (id, template_id, element_key, element_name, element_type, namespace, field_name, required, table_columns, sort_order)
  440. VALUES
  441. (40, 1, '+review_status', '现场复审情况表', 'table', NULL, 'review_status', true, '["序号", "项目", "存在的问题", "扣分标准"]', 40),
  442. (41, 1, '+target_responsibility', '目标职责评审表', 'table', NULL, 'target_responsibility', true, '["序号", "项目", "存在的问题", "扣分标准"]', 41),
  443. (42, 1, '+institutionalized_management', '制度化管理评审表', 'table', NULL, 'institutionalized_management', true, '["序号", "项目", "存在的问题", "扣分标准"]', 42),
  444. (43, 1, '+education_and_training', '教育培训评审表', 'table', NULL, 'education_and_training', true, '["序号", "项目", "存在的问题", "扣分标准"]', 43)
  445. ON CONFLICT (template_id, element_key) DO NOTHING;
  446. SELECT setval('template_dynamic_elements_id_seq', GREATEST((SELECT MAX(id) FROM template_dynamic_elements), 43));
  447. -- ------------------------------------------------------------
  448. -- 8.5 报告数据
  449. -- ------------------------------------------------------------
  450. -- 成都院复审报告(原始报告)
  451. INSERT INTO reports (id, title, report_type, status, template_id, project_id, created_by, created_at)
  452. VALUES (1001, '成都院复审报告', '电力安全生产标准化复审报告', 'draft', 1, 1, 1, '2026-02-10 10:30:00')
  453. ON CONFLICT (id) DO NOTHING;
  454. -- 华东院复审报告(从成都院复制)
  455. INSERT INTO reports (id, title, report_type, status, template_id, project_id, created_by, source_report_id, copy_time, created_at)
  456. VALUES (1002, '华东院复审报告', '电力安全生产标准化复审报告', 'draft', 1, 1, 1, 1001, '2026-02-11 14:00:00', '2026-02-11 14:00:00')
  457. ON CONFLICT (id) DO NOTHING;
  458. SELECT setval('reports_id_seq', GREATEST((SELECT MAX(id) FROM reports), 1002));
  459. -- ------------------------------------------------------------
  460. -- 8.6 附件数据
  461. -- ------------------------------------------------------------
  462. INSERT INTO report_attachments (id, report_id, display_name, file_name, file_path, file_type, file_size, parse_status, entity_count, parsed_at, sort_order)
  463. VALUES
  464. (1, 1001, '01-复审通知', '复审通知.docx', '/uploads/2026/02/复审通知.docx', 'docx', 102400, 'completed', 15, '2026-02-10 10:35:00', 1),
  465. (2, 1001, '02-评审报告原文', '评审报告.pdf', '/uploads/2026/02/评审报告.pdf', 'pdf', 512000, 'completed', 25, '2026-02-10 10:40:00', 2),
  466. (3, 1001, '03-安全标准化达标证书', '达标证书.pdf', '/uploads/2026/02/达标证书.pdf', 'pdf', 256000, 'completed', 8, '2026-02-10 10:45:00', 3)
  467. ON CONFLICT (id) DO NOTHING;
  468. SELECT setval('report_attachments_id_seq', GREATEST((SELECT MAX(id) FROM report_attachments), 3));
  469. -- ------------------------------------------------------------
  470. -- 8.7 附件实体数据
  471. -- ------------------------------------------------------------
  472. INSERT INTO attachment_entities (id, attachment_id, entity_type, entity_text, business_label, confidence, occurrence_count)
  473. VALUES
  474. -- 复审通知中的实体
  475. (1, 1, 'ORG', '中国电建集团成都勘测设计研究院有限公司', '评审对象', 0.95, 15),
  476. (2, 1, 'ORG', '湖北安源安全环保科技有限公司', '评审单位', 0.92, 8),
  477. (3, 1, 'PERSON', '何彦锋', '董事长', 0.88, 3),
  478. (4, 1, 'PERSON', '张世殊', '总经理', 0.88, 2),
  479. (5, 1, 'DATE', '2024年7月13日', '评审开始日期', 0.99, 2),
  480. (6, 1, 'DATE', '2024年10月17日', '评审结束日期', 0.99, 2),
  481. (7, 1, 'DATE', '2024年7月8日', '申请日期', 0.99, 1),
  482. (8, 1, 'DATE', '2019年12月9日', '证书获取日期', 0.99, 1),
  483. (9, 1, 'DATE', '2015年4月7日', '二次证书获取日期', 0.99, 1),
  484. -- 评审报告中的实体
  485. (10, 2, 'NUMBER', '93.33', '评审得分', 0.99, 3),
  486. (11, 2, 'NUMBER', '50', '注册资本(亿)', 0.95, 2),
  487. (12, 2, 'NUMBER', '2887', '员工人数', 0.95, 1),
  488. (13, 2, 'LOCATION', '成都市温江区政和街8号', '公司地址', 0.90, 1),
  489. -- 达标证书中的实体
  490. (14, 3, 'ORG', '中国电建集团成都勘测设计研究院有限公司', NULL, 0.95, 2),
  491. (15, 3, 'DATE', '2019年12月9日', '发证日期', 0.99, 1)
  492. ON CONFLICT (id) DO NOTHING;
  493. SELECT setval('attachment_entities_id_seq', GREATEST((SELECT MAX(id) FROM attachment_entities), 15));
  494. -- ------------------------------------------------------------
  495. -- 8.8 动态要素值数据(成都院)
  496. -- ------------------------------------------------------------
  497. -- 文本型
  498. INSERT INTO element_values (id, report_id, element_key, value_text, is_filled, fill_source)
  499. VALUES
  500. (1, 1001, 'basicInfo.projectCode', 'BZ-0092-2024', true, 'rule'),
  501. (2, 1001, 'project.reviewObject', '中国电建集团成都勘测设计研究院有限公司', true, 'rule'),
  502. (3, 1001, 'project.reviewObjectAlias', '成都院', true, 'rule'),
  503. (4, 1001, 'basicInfo.requestLevel', '一级', true, 'rule'),
  504. (5, 1001, 'project.resultScore', '93.33', true, 'rule'),
  505. (6, 1001, 'project.resultLevel', '一级', true, 'rule'),
  506. (7, 1001, 'project.workStartAt', '2024年7月13日', true, 'rule'),
  507. (8, 1001, 'project.workEndAt', '2024年10月17日', true, 'rule'),
  508. (9, 1001, 'project.createdAt', '2026年02月', true, 'manual'),
  509. (10, 1001, 'basicInfo.applyAt', '2024年7月8日', true, 'rule'),
  510. (11, 1001, 'project.reviewPeriod', '2023年7月8日-2024年7月8日', true, 'rule'),
  511. (12, 1001, 'basicInfo.reviewObjectCertificateGetAt', '2019年12月9日', true, 'rule'),
  512. (13, 1001, 'basicInfo.reviewObjectCertificate2GetAt', '2015年4月7日', true, 'rule')
  513. ON CONFLICT (report_id, element_key) DO NOTHING;
  514. -- 段落型
  515. INSERT INTO element_values (id, report_id, element_key, value_text, is_filled, fill_source)
  516. VALUES
  517. (20, 1001, 'project.reviewObjectSummary', '中国电建集团成都勘测设计研究院有限公司(简称:成都院)成立于2005年,是世界500强企业中国电力建设集团的核心成员企业。作为国家级高新技术企业,成都院以水利水电、新能源和基础设施为核心业务,在水电工程领域承担了金沙江、大渡河、雅砻江等重大河流的规划勘测设计工作,创造了多项"中国第一"和"世界之最"。成都院拥有注册资本50亿元人民币,专业技术人员规模近3000人,累计获得4443项专利和100项行业资质认证,展现了雄厚的技术研发实力。', true, 'rule'),
  518. (21, 1001, 'project.reviewObjectDescription', '中国电建集团成都勘测设计研究院有限公司(简称:成都院)是中国电力建设集团核心成员企业,作为国内领先的清洁能源工程服务商,成都院在水利水电、新能源及基础设施领域具有突出优势。成都院深度参与了国家西部大开发和"西电东送"战略,承担了包括两河口水电站、杨房沟水电站、乌东德水电站等重大工程的勘测设计工作,其中两河口水电站拥有世界最高土石坝的纪录。', true, 'rule'),
  519. (22, 1001, 'project.target', '成都院制定并发布《QHSE"十四五"规划》(安质〔2023〕1号),明确了总体安全生产目标,包括7项安全管理及事故控制目标,总体目标为公司"十四五"规划的子规划,安全生产与职业健康工作目标纳入总体生产经营目标。成都院发布《关于印发<成都院2024年安全生产与职业健康、能源节约与生态环境保护工作目标和重点>的通知》(蓉设安质〔2024〕18号),明确了2024年安全生产与职业健康目标,包括9项安全管理目标和10项事故控制目标。', true, 'rule')
  520. ON CONFLICT (report_id, element_key) DO NOTHING;
  521. -- 表格型
  522. INSERT INTO element_values (id, report_id, element_key, value_json, is_filled, fill_source)
  523. VALUES
  524. (40, 1001, '+target_responsibility', '[
  525. {"序号": 1, "项目": "5.1.1.1 目标制定", "存在的问题": "大邑地勘项目部制定的2024年度安全生产目标,缺少设备设施方面的事故控制目标。", "扣分标准": "依据评估标准②:目标内容有缺失,扣1分/项,共扣1分。"},
  526. {"序号": 2, "项目": "5.1.1.2 目标落实", "存在的问题": "双江口设计项目部项目经理与各专业部门负责人签订的《2024年度安全责任书》中,目标分解不明确,不满足要求。", "扣分标准": "依据评估标准②:签订责任书、目标分解不满足要求,扣1分/单位,共扣1分。"},
  527. {"序号": 3, "项目": "5.1.1.3 目标考核", "存在的问题": "云阳监理项目未对二季度安全生产目标及工作计划完成情况进行考核、监督检查。", "扣分标准": "依据评估标准①:未对目标的完成情况进行评估和考核,扣2分/次,共扣2分。"}
  528. ]', true, 'rule'),
  529. (41, 1001, '+institutionalized_management', '[
  530. {"序号": 1, "项目": "5.2.2 规章制度", "存在的问题": "勘测设计分公司未按成都院《安全风险管控管理办法》的要求制定安全风险管控制度。", "扣分标准": "依据评估标准①:制度不全,扣2分/项,共扣2分"},
  531. {"序号": 2, "项目": "5.2.3 操作规程", "存在的问题": "云阳监理项目1#引水洞汽车吊和下库进出水口挖掘机未张贴安全操作规程。", "扣分标准": "依据评估标准③:设备未悬挂安全操作规程,扣1分/处,共扣2分。"}
  532. ]', true, 'rule'),
  533. (42, 1001, '+education_and_training', '[
  534. {"序号": 1, "项目": "5.3.1 教育培训管理", "存在的问题": "大邑地勘项目部《2024年安全生产教育和培训计划》中,缺少有限空间作业等专项培训内容。", "扣分标准": "依据评估标准③:培训计划未包含职业健康、应急管理及上级要求的培训等内容,内容不全,扣2分。"}
  535. ]', true, 'rule')
  536. ON CONFLICT (report_id, element_key) DO NOTHING;
  537. SELECT setval('element_values_id_seq', GREATEST((SELECT MAX(id) FROM element_values), 42));
  538. -- ------------------------------------------------------------
  539. -- 8.9 动态要素规则数据(成都院)
  540. -- ------------------------------------------------------------
  541. INSERT INTO element_rules (id, report_id, element_key, rule_name, description, rule_type, last_output_text, last_run_status, last_run_time, status)
  542. VALUES
  543. (1, 1001, 'basicInfo.projectCode', '项目编号提取', '从复审通知中提取项目编号', 'extraction', 'BZ-0092-2024', 'success', '2026-02-11 14:00:00', 'active'),
  544. (2, 1001, 'project.reviewObject', '评审对象提取', '从复审通知中提取评审对象', 'extraction', '中国电建集团成都勘测设计研究院有限公司', 'success', '2026-02-11 14:01:00', 'active'),
  545. (3, 1001, 'project.reviewObjectAlias', '评审对象简称提取', '从复审通知中提取评审对象简称', 'extraction', '成都院', 'success', '2026-02-11 14:02:00', 'active'),
  546. (4, 1001, 'project.resultScore', '评审得分提取', '从评审报告中提取评审得分', 'extraction', '93.33', 'success', '2026-02-11 14:03:00', 'active'),
  547. (5, 1001, 'project.workStartAt', '评审开始日期提取', '从复审通知中提取评审开始日期', 'extraction', '2024年7月13日', 'success', '2026-02-11 14:04:00', 'active'),
  548. (6, 1001, 'project.workEndAt', '评审结束日期提取', '从复审通知中提取评审结束日期', 'extraction', '2024年10月17日', 'success', '2026-02-11 14:05:00', 'active'),
  549. (7, 1001, 'project.reviewObjectSummary', '评审对象概述生成', '基于企业简介生成评审对象概述', 'generation', NULL, 'success', '2026-02-11 14:06:00', 'active'),
  550. (8, 1001, 'project.reviewObjectDescription', '企业简介生成', '基于附件内容生成企业简介', 'generation', NULL, 'success', '2026-02-11 14:07:00', 'active'),
  551. (9, 1001, 'project.target', '目标内容生成', '基于附件内容生成目标描述', 'generation', NULL, 'success', '2026-02-11 14:08:00', 'active'),
  552. (10, 1001, '+target_responsibility', '目标职责评审表提取', '从评审报告中提取目标职责评审表', 'extraction', NULL, 'success', '2026-02-11 14:09:00', 'active')
  553. ON CONFLICT (report_id, element_key) DO NOTHING;
  554. SELECT setval('element_rules_id_seq', GREATEST((SELECT MAX(id) FROM element_rules), 10));
  555. -- ------------------------------------------------------------
  556. -- 8.10 规则输入数据
  557. -- ------------------------------------------------------------
  558. INSERT INTO rule_inputs (id, rule_id, input_key, input_name, input_type, ref_attachment_id, ref_entity_id, fixed_value, sort_order)
  559. VALUES
  560. (1, 1, 'input1', '复审通知', 'attachment_ref', 1, NULL, NULL, 1),
  561. (2, 2, 'input1', '复审通知', 'attachment_ref', 1, NULL, NULL, 1),
  562. (3, 3, 'input1', '评审对象', 'entity_ref', NULL, 1, NULL, 1),
  563. (4, 4, 'input1', '评审报告', 'attachment_ref', 2, NULL, NULL, 1),
  564. (5, 5, 'input1', '复审通知', 'attachment_ref', 1, NULL, NULL, 1),
  565. (6, 6, 'input1', '复审通知', 'attachment_ref', 1, NULL, NULL, 1),
  566. (7, 7, 'input1', '评审报告', 'attachment_ref', 2, NULL, NULL, 1),
  567. (8, 7, 'prompt', '提示词', 'text', NULL, NULL, '请根据以下企业信息,生成一段简洁的企业概述。', 2),
  568. (9, 8, 'input1', '评审报告', 'attachment_ref', 2, NULL, NULL, 1),
  569. (10, 8, 'prompt', '提示词', 'text', NULL, NULL, '请根据以下内容,生成详细的企业简介。', 2),
  570. (11, 9, 'input1', '评审报告', 'attachment_ref', 2, NULL, NULL, 1),
  571. (12, 9, 'prompt', '提示词', 'text', NULL, NULL, '请根据以下内容,提取并整理企业的安全生产目标相关内容。', 2),
  572. (13, 10, 'input1', '评审报告', 'attachment_ref', 2, NULL, NULL, 1)
  573. ON CONFLICT (id) DO NOTHING;
  574. SELECT setval('rule_inputs_id_seq', GREATEST((SELECT MAX(id) FROM rule_inputs), 13));
  575. -- ------------------------------------------------------------
  576. -- 8.11 规则动作配置数据
  577. -- ------------------------------------------------------------
  578. INSERT INTO rule_action_config (id, rule_id, action_type, config)
  579. VALUES
  580. (1, 1, 'extract_pattern', '{"pattern": "项目编号[::]\\s*(\\S+)", "group": 1}'),
  581. (2, 2, 'extract_entity', '{"entityType": "ORG", "businessLabel": "评审对象", "selectStrategy": "first"}'),
  582. (3, 3, 'extract_pattern', '{"pattern": "(简称[::](.+?))", "group": 1}'),
  583. (4, 4, 'extract_entity', '{"entityType": "NUMBER", "businessLabel": "评审得分", "selectStrategy": "first"}'),
  584. (5, 5, 'extract_entity', '{"entityType": "DATE", "businessLabel": "评审开始日期", "selectStrategy": "first"}'),
  585. (6, 6, 'extract_entity', '{"entityType": "DATE", "businessLabel": "评审结束日期", "selectStrategy": "first"}'),
  586. (7, 7, 'llm_generate', '{"model": "qwen-max", "temperature": 0.7, "maxTokens": 1000}'),
  587. (8, 8, 'llm_generate', '{"model": "qwen-max", "temperature": 0.7, "maxTokens": 2000}'),
  588. (9, 9, 'llm_generate', '{"model": "qwen-max", "temperature": 0.7, "maxTokens": 2000}'),
  589. (10, 10, 'extract_table', '{"tablePattern": "序号.*项目.*问题", "columns": ["序号", "项目", "存在的问题", "扣分标准"]}')
  590. ON CONFLICT (rule_id) DO NOTHING;
  591. SELECT setval('rule_action_config_id_seq', GREATEST((SELECT MAX(id) FROM rule_action_config), 10));
  592. -- ------------------------------------------------------------
  593. -- 8.12 报告复制记录
  594. -- ------------------------------------------------------------
  595. INSERT INTO report_copy_records (id, source_report_id, target_report_id, copied_by, copy_time, elements_copied, rules_copied, notes)
  596. VALUES (1, 1001, 1002, 1, '2026-02-11 14:00:00', 45, 10, '从成都院复制到华东院')
  597. ON CONFLICT (id) DO NOTHING;
  598. SELECT setval('report_copy_records_id_seq', GREATEST((SELECT MAX(id) FROM report_copy_records), 1));
  599. -- ============================================================
  600. -- 完成
  601. -- ============================================================
  602. SELECT '灵越智报 2.0 数据库完整脚本执行完成' AS result;