GitHub(nextgroup2706/ken_nogi)は今後使わず自社Gitea運用に切替え。 NodeSrvは旧リポジトリの履歴を破棄しファイルのみ統合(Dokploy用サービスアカウントは 別途mygit-admin/NodeSrv.gitに履歴あり)。notepmエクスポート(12GB)とPleasanter インストーラzip(208MB)はサイズが大きいため.gitignoreで除外。 Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
68 lines
3.2 KiB
JavaScript
68 lines
3.2 KiB
JavaScript
// Excel定義書の展開データとサイトの実Columnsデータを突き合わせ、差分を出力する。
|
||
// 読み取り専用の調査用スクリプト(ファイルへの書き込みは行わない)。
|
||
const fs = require("fs");
|
||
|
||
const [, , excelJsonPath, siteJsonPath, outPath] = process.argv;
|
||
const excelRecords = JSON.parse(fs.readFileSync(excelJsonPath, "utf8"));
|
||
const siteRecords = JSON.parse(fs.readFileSync(siteJsonPath, "utf8"));
|
||
|
||
const excelByCol = new Map();
|
||
for (const r of excelRecords) {
|
||
if (!excelByCol.has(r.ColumnName)) excelByCol.set(r.ColumnName, r);
|
||
}
|
||
const siteByCol = new Map(siteRecords.map((r) => [r.ColumnName, r]));
|
||
|
||
const excelOnly = [];
|
||
const siteOnly = [];
|
||
const mismatches = [];
|
||
|
||
for (const [col, ex] of excelByCol) {
|
||
if (["状況", "タイトル", "コメント"].includes(col)) continue; // 固定列(Status/Title/Comments)は別名管理のためスキップ
|
||
const isBlankTemplateRow = !ex.label; // ラベル未記入=未使用項目のテンプレート行(tab/other等に列名メモが残っている場合がある)
|
||
if (isBlankTemplateRow) continue;
|
||
const s = siteByCol.get(col);
|
||
if (!s) {
|
||
excelOnly.push({ ColumnName: col, label: ex.label, note: ex.note });
|
||
continue;
|
||
}
|
||
const diffs = [];
|
||
const exShow = ex.show || "";
|
||
const wantHide = exShow.includes("非表示");
|
||
if (wantHide !== s.Hide) diffs.push(`表示有無: Excel="${exShow}" / サイトHide=${s.Hide}`);
|
||
|
||
const exReq = !!(ex.req || "").trim();
|
||
const siteReq = s.ValidateRequired || s.ProcessRequired;
|
||
if (exReq !== siteReq) diffs.push(`入力必須: Excel="${ex.req}" / サイトValidateRequired=${s.ValidateRequired} ProcessRequired=${s.ProcessRequired}`);
|
||
|
||
const exRo = !!(ex.readOnly || "").trim();
|
||
const siteRo = !!s.ExtendedFieldCss;
|
||
if (exRo !== siteRo) diffs.push(`読み取り専用: Excel="${ex.readOnly}" / サイトExtendedFieldCss="${s.ExtendedFieldCss}"`);
|
||
|
||
const exLock = !!(ex.lock || "").trim();
|
||
if (exLock !== s.StatusLocked) diffs.push(`編集不可(ロック): Excel="${ex.lock}" / サイトStatusLocked=${s.StatusLocked}`);
|
||
|
||
if (ex.label && ex.label !== s.LabelText && ex.label !== s.GridLabelText) {
|
||
diffs.push(`ラベル: Excel="${ex.label}" / サイトLabelText="${s.LabelText}" GridLabelText="${s.GridLabelText}"`);
|
||
}
|
||
|
||
const exStyle = (ex.style || "").trim();
|
||
const siteStyleWide = s.FieldCss === "field-wide";
|
||
if (exStyle === "ワイド" && !siteStyleWide) diffs.push(`スタイル: Excel="ワイド" / サイトFieldCss="${s.FieldCss}"`);
|
||
if (exStyle === "ノーマル" && siteStyleWide) diffs.push(`スタイル: Excel="ノーマル" / サイトFieldCss="${s.FieldCss}"`);
|
||
|
||
if (diffs.length) mismatches.push({ ColumnName: col, diffs });
|
||
}
|
||
|
||
for (const [col, s] of siteByCol) {
|
||
if (!excelByCol.has(col)) {
|
||
siteOnly.push({ ColumnName: col, LabelText: s.LabelText, GridLabelText: s.GridLabelText, Hide: s.Hide, Tab: s.Tab });
|
||
}
|
||
}
|
||
|
||
const result = { excelOnly, siteOnly, mismatches };
|
||
fs.writeFileSync(outPath, JSON.stringify(result, null, 2), "utf8");
|
||
console.log("Excelのみ(サイト側に無い→削除候補):", excelOnly.length);
|
||
console.log("サイトのみ(Excel未記載→追加候補):", siteOnly.length);
|
||
console.log("属性不一致:", mismatches.length);
|
||
console.log("詳細:", outPath);
|