const fs = require('fs'); const path = require('path'); const { execSync } = require('child_process'); const BASE = __dirname; const DOCX = path.join(BASE, '智配引擎数据库设计文档.docx'); const WORK = path.join(BASE, 'docx_work3'); const OUTPUT = path.join(BASE, '智配引擎数据库设计文档_规范后.docx'); if (fs.existsSync(WORK)) fs.rmSync(WORK, { recursive: true }); fs.mkdirSync(WORK, { recursive: true }); execSync(`unzip -o "${DOCX}" -d "${WORK}"`, { stdio: 'pipe' }); let xml = fs.readFileSync(path.join(WORK, 'word/document.xml'), 'utf-8'); const changes = []; // ============================================================ // Step 1: 合并跨 的 A + 残片模式 // 使用 [\s\S]* 来匹配换行 // ============================================================ const mergePairs = [ { find: 'nnualpowersupply', neu: 'annual_power_supply', label: 'A+nnualpowersupply' }, { find: 'verageelectricityprice', neu: 'average_electricity_price', label: 'A+verageelectricityprice' }, { find: 'nnualincome', neu: 'annual_income', label: 'A+nnualincome' }, { find: 'nnualprofit', neu: 'annual_profit', label: 'A+nnualprofit' }, ]; for (const mp of mergePairs) { const escaped = mp.find.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // Match: A......AnnualpowersupplySUFFIX // where SUFFIX is either :CHINESE or just : alone const regex = new RegExp( 'A[\\s\\S]*?[\\s\\S]*?' + escaped + '([^:<]*)(:[^<]*)<\/w:t>', 'g' ); const matches = [...xml.matchAll(regex)]; if (matches.length > 0) { xml = xml.replace(regex, (m, suffix, rest) => { changes.push(`${mp.label} -> ${mp.neu}`); return `${mp.neu}${rest}`; }); } } // ============================================================ // Step 2: 单 标签替换 // ============================================================ const r = (old, neu) => { if (xml.includes(old)) { xml = xml.split(old).join(neu); changes.push(`"${old.substring(0,30)}" -> "${neu.substring(0,50)}"`); } }; r('assignment_duration:年度作业时长,', 'assignment_duration: (Annual Assignment Duration/年作业时长)'); r('annual_power_supply: 年供电量', 'annual_power_supply: (Annual Power Supply/年供电量)'); r('average_electricity_price: 平均电价', 'average_electricity_price: (Average Electricity Price/平均电价)'); r('年运营成本', 'annual_operating_cost: (Annual Operating Cost/年运营成本)'); r('year:年示例:(第一年)', 'year: (Year Example e.g. Year 1/示例:如第一年)'); r('annual_income: 年收入', 'annual_income: (Annual Income/年收入)'); r('annual_profit: 年利润', 'annual_profit: (Annual Profit/年利润)'); r('annualpretaxprofit年税前利润', 'annual_pre_tax_profit: (Annual Pre-Tax Profit/年税前利润)'); r('annualaftertaxprofit年税后利润', 'annual_after_tax_profit: (Annual After-Tax Profit/年税后利润)'); r('paybackperiod投资回收期', 'pay_back_period: (Payback Period/投资回收期)'); r('irr:内部收益率(IRR)', 'irr: (Internal Rate of Return/内部收益率IRR)'); r('ppv:净现值(NPV)', 'npv: (Net Present Value/净现值NPV)'); r('cumulativeprofit:累计利润', 'cumulative_profit: (Cumulative Profit/累计利润)'); r('Cumulativeinvestment累计投资', 'cumulative_investment: (Cumulative Investment/累计投资)'); r('revenuemodel', 'revenue_model: (Revenue Model/收益模型)'); r('year:', 'year: (Year/年份)'); console.log('Changes:'); changes.forEach(c => console.log(' ', c)); fs.writeFileSync(path.join(WORK, 'word/document.xml'), xml, 'utf-8'); if (fs.existsSync(OUTPUT)) fs.unlinkSync(OUTPUT); execSync(`cd "${WORK}" && zip -r "${OUTPUT}" . -x "*.DS_Store"`, { stdio: 'pipe' }); console.log(`\nSaved: ${OUTPUT}`); fs.rmSync(WORK, { recursive: true });