migrate-excel-field-gaps-20260904.js 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. /**
  2. * 对照 docs/松江农民土地退补系统字段名称.xlsx 补齐 DMS 缺口(2026-09-04)
  3. *
  4. * 缺口结论:
  5. * 1. 人员表缺独立「死亡状态」字段 c_death_status(原仅靠 c_biz_status=FUNERAL / c_death_date)
  6. * 2. 人员表 c_supplement_start_month 别名损坏(补发��始年月)→ 修成「补发开始年月」
  7. *
  8. * 用法:node migrate-excel-field-gaps-20260904.js
  9. */
  10. const http = require("http");
  11. const qs = require("querystring");
  12. const fs = require("fs");
  13. const path = require("path");
  14. const HOST = "121.43.55.7";
  15. const PORT = 2101;
  16. const PERSONNEL_MODEL = 1970;
  17. function post(urlPath, fields, token) {
  18. return new Promise((resolve, reject) => {
  19. const body = qs.stringify(fields || {});
  20. const headers = {
  21. "Content-Type": "application/x-www-form-urlencoded",
  22. "Content-Length": Buffer.byteLength(body),
  23. };
  24. if (token) {
  25. headers.Token = token;
  26. headers.token = token;
  27. }
  28. const req = http.request(
  29. { hostname: HOST, port: PORT, path: urlPath, method: "POST", headers },
  30. (res) => {
  31. let data = "";
  32. res.on("data", (c) => (data += c));
  33. res.on("end", () => {
  34. try {
  35. resolve(JSON.parse(data));
  36. } catch (e) {
  37. resolve({ raw: data, status: res.statusCode });
  38. }
  39. });
  40. }
  41. );
  42. req.on("error", reject);
  43. req.write(body);
  44. req.end();
  45. });
  46. }
  47. function text(shortName, alias, must, seq) {
  48. return {
  49. alias,
  50. customType: "",
  51. describe: "格式为富文本",
  52. frontType: "content",
  53. id: 2,
  54. must: !!must,
  55. name: "c_" + shortName,
  56. searchType: "2",
  57. sequence: seq || 1,
  58. showParam: "name,alias,desc,type,front_type,must,default_value",
  59. type: "text",
  60. };
  61. }
  62. function normalizeFieldList(raw) {
  63. let fl = raw;
  64. if (typeof fl === "string") fl = JSON.parse(fl);
  65. const out = {};
  66. Object.keys(fl || {}).forEach((k) => {
  67. let v = fl[k];
  68. if (typeof v === "string") v = JSON.parse(v);
  69. out[k] = v;
  70. });
  71. return out;
  72. }
  73. async function getModel(token, modelId) {
  74. const res = await post("/proxy_dms/model/getModelById", { modelId: String(modelId) }, token);
  75. if (res.code != 200) throw new Error("getModel " + modelId + " fail: " + JSON.stringify(res));
  76. return res.content;
  77. }
  78. async function applyUpdates(token, modelId, addMap, renameAliasMap) {
  79. const model = await getModel(token, modelId);
  80. const fieldList = normalizeFieldList(model.fieldList);
  81. if (Object.keys(fieldList).length < 2) {
  82. throw new Error("model " + modelId + " fieldList 异常,拒绝覆盖");
  83. }
  84. const addfieldList = {};
  85. Object.keys(addMap || {}).forEach((shortName) => {
  86. const full = "c_" + shortName;
  87. if (fieldList[full]) return;
  88. const p = addMap[shortName];
  89. p.name = full;
  90. fieldList[full] = p;
  91. addfieldList[shortName] = {
  92. alias: p.alias,
  93. type: p.type,
  94. frontType: p.frontType,
  95. must: p.must,
  96. name: shortName,
  97. describe: p.describe,
  98. searchType: p.searchType,
  99. sortType: p.sortType,
  100. sequence: p.sequence,
  101. showParam: p.showParam,
  102. customType: p.customType || "",
  103. id: p.id,
  104. };
  105. });
  106. // 仅改 alias:只更新 fieldList 元数据,勿走 updatefieldList(生产 DMS 对 rename 会 500)
  107. const aliasFixed = [];
  108. Object.keys(renameAliasMap || {}).forEach((full) => {
  109. if (!fieldList[full]) return;
  110. const nextAlias = renameAliasMap[full];
  111. if (fieldList[full].alias === nextAlias) return;
  112. fieldList[full] = Object.assign({}, fieldList[full], { alias: nextAlias });
  113. aliasFixed.push(full);
  114. });
  115. if (Object.keys(addfieldList).length === 0 && aliasFixed.length === 0) {
  116. return {
  117. modelId,
  118. modelName: model.modelName,
  119. code: 200,
  120. message: "无需变更",
  121. added: [],
  122. updated: [],
  123. };
  124. }
  125. const res = await post(
  126. "/proxy_dms/model/updateFieldList",
  127. {
  128. modelId: String(modelId),
  129. fieldList: JSON.stringify(fieldList),
  130. addfieldList: JSON.stringify(addfieldList),
  131. delfieldList: JSON.stringify({}),
  132. updatefieldList: JSON.stringify({}),
  133. },
  134. token
  135. );
  136. const verify = await getModel(token, modelId);
  137. const vfl = normalizeFieldList(verify.fieldList);
  138. return {
  139. modelId,
  140. modelName: model.modelName,
  141. code: res.code,
  142. message: res.message || res.content,
  143. added: Object.keys(addfieldList),
  144. updated: aliasFixed,
  145. deathStatus: vfl.c_death_status || null,
  146. supplementAlias: vfl.c_supplement_start_month ? vfl.c_supplement_start_month.alias : null,
  147. };
  148. }
  149. async function main() {
  150. const login = await post("/proxy_oauth/user/login", {
  151. userName: "user_liu",
  152. password: "WE176852439@lmx",
  153. clientId: "1",
  154. });
  155. const token = login.message;
  156. if (!token) throw new Error("login failed: " + JSON.stringify(login));
  157. const result = await applyUpdates(
  158. token,
  159. PERSONNEL_MODEL,
  160. {
  161. // 大数据死亡状态匹配专用;与业务态 c_biz_status=FUNERAL 并存
  162. death_status: text("death_status", "死亡状态", false, 40),
  163. },
  164. {
  165. // 仅修复损坏别名;其余 Excel 名与现有 alias 语义等价,不强制改名以免影响管理端展示习惯
  166. c_supplement_start_month: "补发开始年月",
  167. }
  168. );
  169. const outPath = path.join(
  170. __dirname,
  171. "../../docs/_migrate_excel_field_gaps_20260904.json"
  172. );
  173. fs.writeFileSync(outPath, JSON.stringify(result, null, 2), "utf8");
  174. console.log(JSON.stringify(result, null, 2));
  175. }
  176. main().catch((e) => {
  177. console.error(e);
  178. process.exit(1);
  179. });