云
2026-09-29 f87ce86307056f63f79312178037cc8714eb2b13
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
// 由 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'})`);