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>
158 lines
6.3 KiB
JavaScript
158 lines
6.3 KiB
JavaScript
/**
|
||
* apply-remark-fix-496626.js
|
||
* ------------------------------------------------------------
|
||
* SiteId 496626 の一覧画面スクリプト(Id:4 new03_一覧画面自動処理)を、
|
||
* 備考の3文字省略+独自ポップアップ表示に対応した修正版へ差し替える。
|
||
*
|
||
* 対象は desired_config.json(build-desired-config.js が
|
||
* configs/site-496626_新・着工要因(東京)v2/ 配下から再構成したもの)の
|
||
* SiteSettings.Scripts/Styles/ServerScripts/Processes をそのまま送信する。
|
||
* 事前に確認した通り、実際に内容が変わるのは Scripts の Id:4 のみ
|
||
* (他はキー順序が変わるだけでBodyは現状と完全一致)。
|
||
*
|
||
* ユーザーがその場で「直接適用してよい」と明示的に許可した場合に限り実行する
|
||
* 一回限りの専用スクリプト(.claude/skills/pleasanter-site-spec/SKILL.md
|
||
* 「クロスサイト構造変更」節の運用に準拠)。
|
||
*
|
||
* 使い方:
|
||
* node apply-remark-fix-496626.js … 差分表示のみ(送信なし)
|
||
* node apply-remark-fix-496626.js --execute … 上記に加えて実際に送信する
|
||
* ------------------------------------------------------------
|
||
*/
|
||
|
||
const fs = require("fs");
|
||
const path = require("path");
|
||
const { latestJsonPath, newModifyDir, latestModifyDir, findSiteDir } = require("../../site-paths");
|
||
const { REPO_ROOT, loadServerConfig } = require("../../resolve-project");
|
||
|
||
const PROJECT_NAME = "新・着工要因システム";
|
||
const ENV = "production";
|
||
const SITE_ID = 496626;
|
||
const baseDir = path.join(REPO_ROOT, PROJECT_NAME);
|
||
const configsDir = path.join(baseDir, "configs", ENV);
|
||
const execute = process.argv.includes("--execute");
|
||
|
||
function loadJson(p, required = true) {
|
||
if (!fs.existsSync(p)) {
|
||
if (required) {
|
||
console.error(`[エラー] ファイルが見つかりません: ${p}`);
|
||
process.exit(1);
|
||
}
|
||
return null;
|
||
}
|
||
return JSON.parse(fs.readFileSync(p, "utf-8"));
|
||
}
|
||
|
||
function maskApiKey(key) {
|
||
if (!key) return key;
|
||
return key.length > 8 ? key.slice(0, 4) + "****" + key.slice(-4) : "****";
|
||
}
|
||
|
||
function timestamp() {
|
||
return new Date().toISOString().replace(/[:.]/g, "-");
|
||
}
|
||
|
||
const config = loadServerConfig(ENV);
|
||
const desired = loadJson(path.join(baseDir, "desired_config.json"));
|
||
|
||
if (desired.SiteId !== SITE_ID) {
|
||
console.error(`[エラー] desired_config.json の SiteId (${desired.SiteId}) が ${SITE_ID} ではありません。`);
|
||
console.error(`先に node build-desired-config.js site-${SITE_ID}_新・着工要因(東京)v2 を実行してください。`);
|
||
process.exit(1);
|
||
}
|
||
|
||
const currentPath = latestJsonPath(configsDir, SITE_ID);
|
||
const current = loadJson(currentPath, false);
|
||
const currentScripts = current?.Response?.Data?.SiteSettings?.Scripts || [];
|
||
const desiredScripts = desired.SiteSettings.Scripts || [];
|
||
|
||
const curScript4 = currentScripts.find((s) => s.Id === 4);
|
||
const newScript4 = desiredScripts.find((s) => s.Id === 4);
|
||
|
||
console.log("========================================");
|
||
console.log(` 一覧画面スクリプト(Id:4)の差し替え${execute ? "(実行)" : "(プレビューのみ)"}`);
|
||
console.log("========================================");
|
||
console.log(`対象: SiteId ${SITE_ID}("${current?.Response?.Data?.Title || ""}")`);
|
||
console.log("");
|
||
console.log(`Script Id:4 現状の文字数: ${curScript4 ? curScript4.Body.length : "(取得できず)"}`);
|
||
console.log(`Script Id:4 変更後の文字数: ${newScript4 ? newScript4.Body.length : "(取得できず)"}`);
|
||
console.log(`Script Id:4 以外のScripts/Styles/ServerScripts/Processesは内容変更なし(キー順序のみ変わる場合あり)`);
|
||
|
||
const siteDir = findSiteDir(configsDir, SITE_ID);
|
||
const modifyDir = latestModifyDir(siteDir) || newModifyDir(siteDir, "remark-truncate-fix");
|
||
const ts = timestamp();
|
||
|
||
const diffOutPath = path.join(modifyDir, `site-${SITE_ID}_remark_fix_diff_${ts}.txt`);
|
||
fs.writeFileSync(
|
||
diffOutPath,
|
||
[
|
||
`SiteId ${SITE_ID} 一覧画面スクリプト(Id:4)差し替えプレビュー (${ts})`,
|
||
"",
|
||
"--- 現状のBody ---",
|
||
curScript4 ? curScript4.Body : "(取得できず)",
|
||
"",
|
||
"--- 変更後のBody ---",
|
||
newScript4 ? newScript4.Body : "(取得できず)",
|
||
].join("\n"),
|
||
"utf-8"
|
||
);
|
||
console.log(`\n[OK] 差分プレビューを保存しました: ${diffOutPath}`);
|
||
|
||
const url = `${config.BaseUrl.replace(/\/+$/, "")}/api/items/${SITE_ID}/updatesitesettings`;
|
||
const body = {
|
||
ApiVersion: config.ApiVersion || "1.1",
|
||
ApiKey: config.ApiKey,
|
||
SiteId: SITE_ID,
|
||
SiteSettings: desired.SiteSettings,
|
||
};
|
||
|
||
const maskedBody = { ...body, ApiKey: maskApiKey(body.ApiKey) };
|
||
console.log("\n--- 送信されるBody(APIキーはマスク表示) ---");
|
||
console.log(
|
||
JSON.stringify(
|
||
{
|
||
...maskedBody,
|
||
SiteSettings: {
|
||
Scripts: `${desired.SiteSettings.Scripts.length}件(Id:4のみ内容変更)`,
|
||
Styles: `${desired.SiteSettings.Styles.length}件(変更なし)`,
|
||
ServerScripts: `${desired.SiteSettings.ServerScripts.length}件(変更なし)`,
|
||
Processes: `${desired.SiteSettings.Processes.length}件(変更なし)`,
|
||
},
|
||
},
|
||
null,
|
||
2
|
||
)
|
||
);
|
||
|
||
if (!execute) {
|
||
console.log("\n[注意] --execute が指定されていないため、送信は行っていません。");
|
||
console.log("内容を確認の上、問題なければ次を実行してください: node apply-remark-fix-496626.js --execute");
|
||
process.exit(0);
|
||
}
|
||
|
||
(async () => {
|
||
console.log("\n実際に送信します...");
|
||
const res = await fetch(url, {
|
||
method: "POST",
|
||
headers: { "Content-Type": "application/json" },
|
||
body: JSON.stringify(body),
|
||
});
|
||
const text = await res.text();
|
||
const resultOutPath = path.join(modifyDir, `site-${SITE_ID}_remark_fix_result_${ts}.json`);
|
||
fs.writeFileSync(resultOutPath, text, "utf-8");
|
||
|
||
console.log(`HTTP ${res.status} ${res.statusText}`);
|
||
console.log(`[OK] 応答を保存しました: ${resultOutPath}`);
|
||
|
||
try {
|
||
const json = JSON.parse(text);
|
||
if (json.StatusCode === 200) {
|
||
console.log("[OK] 適用に成功しました。管理画面・一覧画面で表示を確認してください。");
|
||
} else {
|
||
console.error("[エラー] 適用に失敗した可能性があります。応答内容を確認してください。");
|
||
}
|
||
} catch {
|
||
console.log(text);
|
||
}
|
||
})();
|