// 由 config_export_all_20260928.sql 生成 config_export_all_20260929.sql(增量补丁) // 用法:node _patch_0929.js import fs from 'node:fs'; import path from 'node:path'; const DIR = process.cwd(); const SRC = path.join(DIR, 'config_export_all_20260928.sql'); const DST = path.join(DIR, 'config_export_all_20260929.sql'); const EXPORT = path.join(DIR, '_finance_bpm_export.sql'); const raw = fs.readFileSync(SRC, 'utf8'); const crlf = raw.includes('\r\n'); let sql = crlf ? raw.replace(/\r\n/g, '\n') : raw; const exp = fs.readFileSync(EXPORT, 'utf8').replace(/\r\n/g, '\n'); function sub(oldStr, newStr, label) { const n = sql.split(oldStr).length - 1; if (n !== 1) throw new Error(`[${label}] 期望唯一匹配,实际 ${n} 次`); sql = sql.replace(oldStr, newStr); console.log(` OK ${label}`); } // ---------- 从部署导出文件里取 INSERT 行 ---------- function insertsOf(table) { return exp .split('\n') .filter((l) => l.startsWith(`INSERT INTO \`${table}\``)) .map((l) => l.trim()); } const procdefIns = insertsOf('act_re_procdef'); const deployIns = insertsOf('act_re_deployment'); const byteIns = insertsOf('act_ge_bytearray'); const modelIns = insertsOf('act_re_model'); const infoIns = insertsOf('bpm_process_definition_info'); if (procdefIns.length !== 1 || deployIns.length !== 1 || byteIns.length !== 3 || modelIns.length !== 1 || infoIns.length !== 1) { throw new Error(`导出文件行数不符:procdef=${procdefIns.length} deploy=${deployIns.length} byte=${byteIns.length} model=${modelIns.length} info=${infoIns.length}`); } console.log('1) 文件头'); sub('-- 文件:config_export_all_20260928.sql', '-- 文件:config_export_all_20260929.sql', '文件名'); sub( '-- 本次为**补丁版**:基于 0918 文件增量修改,未重跑全库导出(避免把无关表一起搅动)。', '-- 本次为**补丁版**:20260929 基于 20260928 增量修改(20260928 又基于 0918),未重跑全库导出(避免把无关表一起搅动)。', '补丁说明', ); sub( '-- research_fund_status(待拨付/已拨付)', '-- research_fund_status(待拨付/已拨付;2026-09-29 扩为 待拨付/报销审批中/已拨付/已驳回)', '头部字典说明', ); sub( '-- ⚠ 该流程的 BPMN 为手写三节点,**不是** bpm_deploy_flow_from_template 生成的单节点流程。', '-- ⚠ 该流程的 BPMN 为手写三节点,**不是** bpm_deploy_flow_from_template 生成的单节点流程。\n' + '-- 补丁内容(2026-09-29,课题经费拨付对接财务报销):\n' + '-- ① research_fund_record 增 4 列(reimbursement_id / reimbursement_no / reject_reason / reject_time)\n' + '-- + status 列注释改为「0-待拨付 15-报销审批中 20-已拨付 30-已驳回」+ idx_reimbursement_id 索引。\n' + '-- **无新增表**:全库仍 427 张(finance_reimbursement 表已在 0928 版建立)。\n' + '-- ② research_fund_status 字典由 2 条扩为 4 条(待拨付 0 / 报销审批中 15 / 已拨付 20 / 已驳回 30),\n' + '-- system_dict_type.remark 同步改为「课题经费待拨付/报销审批中/已拨付/已驳回」。\n' + '-- ③ 补 1 条 BPM 流程定义(财务报销两级审批:财务审核 → 财务主管审批),流程 key=\'finance_reimbursement_approve\',\n' + '-- 分别落 act_re_procdef / act_re_deployment / act_ge_bytearray(3 条) / act_re_model /\n' + '-- bpm_process_definition_info 五张表(bpm_process_definition_info.id=42)。\n' + '-- form_type=20(自定义表单),form_custom_create_path=/finance/reimbursement/index、\n' + '-- form_custom_view_path=/finance/reimbursement/detail/approve/index.vue。\n' + '-- bpm_category(id=216, code=\'finance_reimbursement_approve\') 已存在,无需新增。\n' + '-- ⚠ 该流程的 BPMN 为手写两节点,**不是** bpm_deploy_flow_from_template 生成的单节点流程。\n' + '-- ④ **阶段二不动**:本次无菜单/角色/用户变更。', '新增补丁段', ); sub( '-- ⚠ 本 0928 版为在其之上的补丁,**尚未在空库整份跑过**;上线/初始化前请先在可覆盖空库验证。', '-- ⚠ 本 0929 版为在其之上的补丁,**尚未在空库整份跑过**;上线/初始化前请先在可覆盖空库验证。', '验证说明', ); console.log('2) research_fund_record 表结构'); sub( " `status` tinyint NOT NULL DEFAULT '0' COMMENT '状态:0-待拨付 20-已拨付',\n" + " `remark` varchar(512) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '备注',\n" + " `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '创建者',\n" + ' `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT \'创建时间\',\n' + " `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '更新者',\n" + ' `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT \'更新时间\',\n' + " `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',\n" + ' PRIMARY KEY (`id`) USING BTREE,\n' + ' KEY `idx_application_id` (`application_id`) USING BTREE\n' + ") ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='课题-经费拨付记录';", " `status` tinyint NOT NULL DEFAULT '0' COMMENT '状态:0-待拨付 15-报销审批中 20-已拨付 30-已驳回',\n" + " `reimbursement_id` bigint DEFAULT NULL COMMENT '关联财务报销单 ID(finance_reimbursement.id)',\n" + " `reimbursement_no` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '关联财务报销单号',\n" + " `reject_reason` varchar(512) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '报销驳回原因(BPM 回写)',\n" + " `reject_time` datetime DEFAULT NULL COMMENT '报销驳回时间',\n" + " `remark` varchar(512) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '备注',\n" + " `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '创建者',\n" + ' `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT \'创建时间\',\n' + " `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '更新者',\n" + ' `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT \'更新时间\',\n' + " `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',\n" + ' PRIMARY KEY (`id`) USING BTREE,\n' + ' KEY `idx_application_id` (`application_id`) USING BTREE,\n' + ' KEY `idx_reimbursement_id` (`reimbursement_id`) USING BTREE\n' + ") ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='课题-经费拨付记录';", 'DDL 4 列 + 注释 + 索引', ); console.log('3) 字典'); sub( "('81004', '经费拨付状态', 'research_fund_status', '0', '课题经费待拨付/已拨付', '1', '2026-09-28 20:00:00', '1', '2026-09-28 20:00:00', X'00', NULL);", "('81004', '经费拨付状态', 'research_fund_status', '0', '课题经费待拨付/报销审批中/已拨付/已驳回', '1', '2026-09-29 10:00:00', '1', '2026-09-29 10:00:00', X'00', NULL);", 'dict_type remark', ); const ts = '2026-09-29 10:00:00'; sub( `('8100401', '1', '待拨付', '0', 'research_fund_status', '0', 'warning', '', '', '1', '2026-09-28 20:00:00', '1', '2026-09-28 20:00:00', X'00'),\n` + `('8100402', '2', '已拨付', '20', 'research_fund_status', '0', 'success', '', '', '1', '2026-09-28 20:00:00', '1', '2026-09-28 20:00:00', X'00');`, `('8100401', '1', '待拨付', '0', 'research_fund_status', '0', 'warning', '', '', '1', '${ts}', '1', '${ts}', X'00'),\n` + `('8100403', '2', '报销审批中', '15', 'research_fund_status', '0', 'processing', '', '', '1', '${ts}', '1', '${ts}', X'00'),\n` + `('8100402', '3', '已拨付', '20', 'research_fund_status', '0', 'success', '', '', '1', '${ts}', '1', '${ts}', X'00'),\n` + `('8100404', '4', '已驳回', '30', 'research_fund_status', '0', 'danger', '', '', '1', '${ts}', '1', '${ts}', X'00');`, 'dict_data 4 条', ); console.log('4) BPM 五张表'); function appendBefore(marker, lines, label) { const i = sql.indexOf(marker); if (i < 0) throw new Error(`[${label}] 未找到锚点`); sql = sql.slice(0, i) + lines.join('\n') + '\n\n' + sql.slice(i); console.log(` OK ${label}`); } appendBefore( '-- ============ 表:act_re_deployment(导出 22 行) ============', procdefIns, 'act_re_procdef', ); appendBefore( '-- ============ 表:act_ge_bytearray(导出 25 行) ============', deployIns, 'act_re_deployment', ); appendBefore('-- ============ 表:act_re_model(导出 22 行) ============', byteIns, 'act_ge_bytearray'); appendBefore( '-- ============ 表:bpm_process_definition_info(导出 22 行) ============', modelIns, 'act_re_model', ); appendBefore( '-- ***********************************************************************\n-- ② 协同(业务附件配置 + 分类 + 表单 + 扩展配置)', infoIns, 'bpm_process_definition_info', ); console.log('5) 表头行数'); sub('表:act_re_procdef(导出 22 行)', '表:act_re_procdef(导出 23 行)', 'procdef 行数'); sub('表:act_re_deployment(导出 22 行)', '表:act_re_deployment(导出 23 行)', 'deployment 行数'); sub('表:act_ge_bytearray(导出 25 行)', '表:act_ge_bytearray(导出 28 行)', 'bytearray 行数'); sub('表:act_re_model(导出 22 行)', '表:act_re_model(导出 23 行)', 'model 行数'); sub( '表:bpm_process_definition_info(导出 22 行)', '表:bpm_process_definition_info(导出 23 行)', 'procinfo 行数', ); const out = crlf ? sql.replace(/\n/g, '\r\n') : sql; fs.writeFileSync(DST, out, 'utf8'); console.log(`\n已写出 ${DST}(${sql.split('\n').length} 行,EOL=${crlf ? 'CRLF' : 'LF'})`);