import { readFileSync } from 'node:fs' import { fileURLToPath } from 'node:url' import { dirname, resolve } from 'node:path' const here = dirname(fileURLToPath(import.meta.url)) const appRoot = resolve(here, '..') const checks = [ { file: 'src/components/erp/ErpAdapterBlock.vue', forbidden: [ { pattern: /\s*预览\s*<|title="预览"|预览模式|页面预览/, message: 'must not expose preview copy' }, { pattern: /迁移|自动迁移|旧入口|旧 URL|旧页面|历史地址|旧屏幕来源|旧 widget/i, message: 'must not expose migration or legacy-bridge copy' }, { pattern: /业务等价|功能等价|旧新报表比对|逐页比对|真实输出比对/, message: 'must not expose parity copy' }, { pattern: /验收|待验收|验收清单|业务回归|待业务回归/, message: 'must not expose acceptance copy' }, { pattern: /页面清单|覆盖率|覆盖台账|待补齐|待输出比对/, message: 'must not expose inventory checklist copy' }, { pattern: /页面定义|页面结构|动作契约|控制规则|模板适配|适配器已覆盖|前端已重写/, message: 'must not expose engineering metadata copy' } ] const failures = [] for (const check of checks) { const source = readFileSync(resolve(appRoot, check.file), 'utf8') for (const item of check.forbidden || []) { if (item.pattern.test(source)) { failures.push(`${check.file}: ${item.message}`) } } for (const item of check.required || []) { if (!item.pattern.test(source)) { failures.push(`${check.file}: ${item.message}`) } } for (const item of visibleLeakageTerms) { if (item.pattern.test(source)) { failures.push(`${check.file}: ${item.message}`) } } } if (failures.length) { console.error('ERP renderer production-copy policy failed:') for (const failure of failures) console.error(`- ${failure}`) process.exit(1) } console.log('ERP renderer production-copy policy passed')