import fs from "fs"; import path from "path"; import { fileURLToPath } from "url"; const __dirname = path.dirname(fileURLToPath(import.meta.url)); const IDS = [ "TextField_1BBYI1OFDJA80", "TextField_FRLYG3CQ3CG0", "InnerContactField_9DSIOI7Y7AO0", "DDDateField_1BHYQ7T5N5TS0", "DDDateField_YYD1HAMKFXS0", "DDSelectField_1VS1BX17O9MO0", "InnerContactField_U886PC45AO00", "TextField_1HXMC0VO5TCW0", "TextField_QBMQQBNCTA80", "DDSelectField_845RKMRCBNC", "DDSelectField_1XTHOHPHULNK0", "TextField_1EIAVY538AM80", "ColumnLayout_N0ZDGQT4UJ40", "TextareaField_GO981AG879K0", "InnerContactField_1TXM18E414740", "InnerContactField_SHOIEPZ1X8W0", "DDDateField_1107GY4FF5R40", "TextareaField_1JNZ7QFU4GLC0", "ColumnLayout_5UK9OEEPNQG0", "TextNote_14QFWOA0NXUK", "TextField_7KHHS2KML4G0", "TextField_17ONU2GWWQQK0", "TextField_1D66PIGUHPEO0", "TextField_2E68TAT1P2B", "TextField_1FVHYJIFC9340", "DDSelectField_12J1O9KUMFK00", "DDSelectField_1CTHXMP1W6000", "DDSelectField_1QQEC44I00G00", "TextField_1X4ISVYJ2E000", "TextareaField_9MIMABZEHW40", "TextField_1N728V92Z1LS0", "DDSelectField_4JP6PT1HB480", "TextareaField_1WLKQPZU8UF40", "TextareaField_ZCRQZCLP3800", "ColumnLayout_704TMWHBUK00", "DDAttachment_XJYUB17OFGW0", "TextNote_1S3AH8USXUU80", "TextNote_1S2UFGJ55CDC0", "TextField_1JWDW5KVN95S0", "TextField_1CTQW75A6XK00", "TextField_23GWUBGROXWG0", "TextField_SIM35ICCGOW0", "TextField_18UFLIYK2G0W", "TextField_EEO52079YWG0", "TextField_17J58EEU17DS0", "TextField_F05H5U3N9NC0", "TextField_J84FK4ALUOG0", "TextField_3IXTW5EOSTK0", "ColumnLayout_OWD8CAEIPCW0", "DDAttachment_ZVUJAK8ZRVK0", "TextNote_196NEZF2GKQO0", "TextareaField_1BXA83S0L9Q80", "DDSelectField_1J17P5TOEU0W0", "TextField_1ED24R0QOG4G0", "TextField_62OWJDX5J780", "TextField_W509DMUVT0W0", "TextField_IR0XM2QFI4G0", "TextField_MWLXHEAJYDS0", "TextField_GZISO77XGU80", "DDSelectField_1XGOO6QI7YE80", "TextareaField_15N86B1OM9R40", "ColumnLayout_13OIS5R5G4G00", "DDAttachment_Y0KM7E71JY80", "TextNote_65FUYS6PMOG0", "TextField_1WOIAN7UXMXS0", "TextField_1B349K9H85FK0", "TextField_V3UBXSM0V400", "TextField_1N6AOCMUFXXC0", "TextField_5B1TRAUGUP80", "DDSelectField_R805UL353UO0", "TextField_210LMWSH8CCG0", "TextareaField_6JU2QSEND4G0", "ColumnLayout_1OBP4JCUUC1S0", "DDAttachment_1OQ414MMSQE80", "TextNote_7USWEJCWOHO0", "TextField_10A0OELOA9CW0", "TextField_1F35DOLS3GJK0", "TextField_G2N28LNPOKO0", "DDSelectField_Y8AKWL5T20G0", "TextField_1X0CJO3BBELC0", "TextField_1DCKMEARM96O0", "TextareaField_8ZYS78VXXKG0", "DDSelectField_1UNDZ9DNXIN4", "TextareaField_902TJ8AC3BO0", "ColumnLayout_1V6324DSHDMO0", "DDAttachment_19GLQ5UABT9C0", "TextNote_1JGD3A0EBOU80", "DDSelectField_JDD37MSAU7K0", "TextField_1ODO49P4QIOW0", "TextField_15YXLN28VYWW0", "TextField_N3EEZETOMLS0", "TextField_MZLNE0WXSYO0", "DDSelectField_1D1NY47OPRY80", "TextField_CO3RY4XTL800", "TextField_1LJRN85YYW680", "TextareaField_1W3YXGM2WVWG0", "ColumnLayout_FVVK6OHVSMO0", "DDAttachment_NISKKTWA4LC0", "TextNote_18NMSNM15JLS0", "TextField_YON75A1BPDS0", "TextField_1LA4D1ZNJCO00", "TextField_QZAR20YC9DC0", "TextField_W5VDI6TJE0W0", "DDSelectField_JQFNCPP9Q8G0", "TextField_X7WT90RW88W0", "TextareaField_XVWU129IDG00", "TextField_21CFZH9VCESG0", "TextareaField_20MIUBGWHAYO0", "ColumnLayout_7E01AAY4TUO0", "DDAttachment_PVHB9480IPS0", "TextareaField_I623WTCGKBK0", "DDDateField_1QY4LG6SI9FK0", "DDSelectField_W8ZTK2TQHHS0", ]; const createSql = `\ -- 钉钉「技术方案申请表」审批通过后落库(业务 MySQL 执行一次) -- 宽表字段改为单列 wf_values_json(避免 InnoDB 行大小 >8126):key=控件 id,value={ "value","ext" } -- 与 form_label_map(id->中文名)键一致,均为钉钉 componentId CREATE TABLE IF NOT EXISTS ding_scheme_application ( id BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键', process_instance_id VARCHAR(64) NOT NULL COMMENT '钉钉审批实例 ID', business_id VARCHAR(64) DEFAULT NULL COMMENT '钉钉 businessId', process_code VARCHAR(128) DEFAULT NULL COMMENT '审批模板 processCode', title VARCHAR(512) DEFAULT NULL COMMENT '审批标题', instance_result VARCHAR(32) DEFAULT NULL COMMENT '实例审批结果 agree/refuse 等', ding_process_status VARCHAR(32) DEFAULT NULL COMMENT '钉钉实例状态 COMPLETED 等', originator_user_id VARCHAR(64) DEFAULT NULL COMMENT '发起人 userId', originator_dept_name VARCHAR(256) DEFAULT NULL COMMENT '发起人部门', ding_instance_create_time DATETIME DEFAULT NULL COMMENT '钉钉实例创建时间', ding_instance_finish_time DATETIME DEFAULT NULL COMMENT '钉钉实例结束时间', trigger_event_type VARCHAR(64) DEFAULT NULL COMMENT '触发入库的事件类型', form_json MEDIUMTEXT COMMENT '表单控件快照 JSON(完整备份)', form_label_map MEDIUMTEXT COMMENT '控件 id -> 中文 name(JSON)', wf_values_json LONGTEXT COMMENT '控件 id -> {value,ext}(JSON,与 gen-ding-scheme-wide IDS 顺序写入)', scheme_apply_no VARCHAR(128) DEFAULT NULL COMMENT '方案申请编号(冗余)', overview_name VARCHAR(1000) DEFAULT NULL COMMENT '概述名称(冗余)', filler_name VARCHAR(128) DEFAULT NULL COMMENT '填表人展示名(冗余)', fill_date DATE DEFAULT NULL COMMENT '填表日期(冗余)', need_date DATE DEFAULT NULL COMMENT '需求日期(冗余)', customer_full_name VARCHAR(512) DEFAULT NULL COMMENT '客户全称(冗余)', contact_and_phone VARCHAR(512) DEFAULT NULL COMMENT '联系人及电话(冗余)', project_category VARCHAR(128) DEFAULT NULL COMMENT '项目分类(冗余)', product_name VARCHAR(256) DEFAULT NULL COMMENT '产品名称(冗余)', task_detail VARCHAR(2000) DEFAULT NULL COMMENT '任务详情(冗余)', scheme_submit_date DATE DEFAULT NULL COMMENT '方案提交日期(冗余)', scheme_received VARCHAR(32) DEFAULT NULL COMMENT '是否收到方案(冗余)', plm_push_status VARCHAR(32) DEFAULT 'PENDING' COMMENT 'PLM 推送状态 PENDING/SUCCESS/FAIL 等', plm_push_time DATETIME DEFAULT NULL COMMENT 'PLM 推送时间', plm_push_message VARCHAR(1000) DEFAULT NULL COMMENT 'PLM 推送结果说明', create_by VARCHAR(64) DEFAULT '', create_time DATETIME DEFAULT NULL, update_by VARCHAR(64) DEFAULT '', update_time DATETIME DEFAULT NULL, PRIMARY KEY (id), UNIQUE KEY uk_process_instance (process_instance_id), KEY idx_scheme_apply_no (scheme_apply_no), KEY idx_business_id (business_id), KEY idx_plm_push_status (plm_push_status) ) ENGINE = InnoDB ROW_FORMAT = DYNAMIC DEFAULT CHARSET = utf8mb4 COMMENT ='钉钉技术方案申请表审批归档'; `; const alterAddWfJson = `\ -- 已有旧表(含大量 wf_* 列导致 1118)时:先加 JSON 列、升级应用后再按需删除旧 wf_* 列 -- 若 wf_values_json 已存在则跳过本段 ALTER TABLE ding_scheme_application ADD COLUMN wf_values_json LONGTEXT NULL COMMENT '控件 id -> {value,ext} JSON' AFTER form_label_map; `; const drops = []; for (const cid of IDS) { const c = "wf_" + cid.toLowerCase(); drops.push(`ALTER TABLE ding_scheme_application DROP COLUMN \`${c}\`;`); drops.push(`ALTER TABLE ding_scheme_application DROP COLUMN \`${c}_ext\`;`); } const dropSql = "-- 仅当表上曾创建过数百个 wf_* 列且已成功添加 wf_values_json、应用已改为写 JSON 后执行。\n" + "-- 列不存在时会报错,可忽略该条。\n\n" + drops.join("\n") + "\n"; fs.writeFileSync(path.join(__dirname, "ding-scheme-application.sql"), createSql, "utf8"); fs.writeFileSync(path.join(__dirname, "ding-scheme-application-alter-wf-values-json.sql"), alterAddWfJson, "utf8"); fs.writeFileSync(path.join(__dirname, "ding-scheme-application-drop-old-wf-columns.sql"), dropSql, "utf8"); // 旧版「逐列 ADD wf_*」已不再使用,保留空说明文件避免误执行 fs.writeFileSync( path.join(__dirname, "ding-scheme-application-alter-wide.sql"), "-- 已废弃:数百个 wf_* 列会触发 MySQL [1118] Row size too large。\n" + "-- 请使用 ding-scheme-application.sql(新装)或 ding-scheme-application-alter-wf-values-json.sql + wf_values_json。\n", "utf8" ); const javaPath = path.join( __dirname, "..", "..", "..", "ruoyi-system", "src", "main", "java", "com", "ruoyi", "system", "constant", "DingSchemeFormWideColumns.java" ); const javaBody = `package com.ruoyi.system.constant; import java.util.Arrays; import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Locale; import java.util.Set; /** * 与 event.json formComponentValues(146-843) 及 gen-ding-scheme-wide.mjs 的 IDS 一致。 * 表单宽数据写入 {@code wf_values_json}:JSON 的 key 为钉钉控件 id(原始大小写),与 {@code form_label_map} 的 key 一致。 */ public final class DingSchemeFormWideColumns { private DingSchemeFormWideColumns() { } public static final List ORDERED_IDS = Collections.unmodifiableList(Arrays.asList( ${IDS.map((id) => ` "${id}"`).join(",\n")} )); private static final Set ID_SET = new HashSet<>(ORDERED_IDS); public static boolean isKnownComponentId(String componentId) { return componentId != null && ID_SET.contains(componentId); } /** JSON 中的控件 id key(与钉钉一致) */ public static String jsonKey(String componentId) { return componentId; } /** 兼容旧「列名」思路:wf_ + id 小写,仅用于文档/SQL 排查,不再建物理列 */ public static String legacyPhysicalColumnName(String componentId) { return "wf_" + componentId.toLowerCase(Locale.ROOT); } } `; fs.mkdirSync(path.dirname(javaPath), { recursive: true }); fs.writeFileSync(javaPath, javaBody, "utf8"); console.log("OK", javaPath);