- resources/help → A05_EduDetail/guide (git mv · 이력 남김) · 참조 고침(서버 · 시험 · B03 주석 · ui_checks)
- GET /api/help = 모든 페이지 [{page, title, items:[{key, title, text, version}]}] + admin
· 페이지 = ^[BDE]\d{2}$ 폴더 · `_` 파일 · 그림 뺌 · version = sha256 앞 16자 · 페이지 제목 = 00_설명서 제목
- GET /api/help/{page} 는 538-2 까지 살림 · B01 폴더 허용
- 시험: 글 내용 검사(명사형 · 400 자) 걷음 — 시스템 관리자가 화면에서 바로 고친 글이
지킴 시험을 빨갛게 하지 않게(요구서 359 4장 6) · 차례 · 판 · `_` 파일 · 나쁜 폴더 · 경로 탈출 시험 더함
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
115 lines
5.0 KiB
JavaScript
115 lines
5.0 KiB
JavaScript
/* 54-2 — [?] 설명서: B02~B09 좌측 패널 아래 단추 묶음 맨 왼쪽 · 모달 = 왼쪽 차례 · 오른쪽 파일 글 ·
|
|
* 구조물 종류를 고르면 그 항목 먼저 · 패널 안 설명 글 0
|
|
* 시작 화면: 아무 B 화면(로그인 · 환경 배정 storage 프로젝트가 현재 프로젝트)
|
|
* 부르는 법: orca eval --expression "$(cat 이 파일)" (async 식 · JSON 글을 돌려줌) · 1분 넘으면 끊기므로
|
|
* `window.__help542 = ["b02-proj-register", …];` 를 앞에 붙여 네 화면씩 두 번
|
|
* 쓰는 것: 없음(주소 이동 · 누르기 · 모달 닫기 · 끝나면 처음 주소로)
|
|
* 파일 고침 반영: 셸이 `A05_EduDetail/guide/B04/99_임시.md` 를 만들고(글 A) 부름 → 글 B 로 고치고 다시 부름 →
|
|
* `temp` 가 A → B 로 바뀌면 통과 · 뒤에 파일 지움(없으면 temp = null)
|
|
* 기대 수치:
|
|
* - pages 8 · 줄마다 btn = 1 · first = true(묶음 맨 왼쪽) · inLeft = true(B02 는 아래 단추 줄) ·
|
|
* modal = true · toc[0] = 「… 설명서」 · text = 그 설명서 제목 글
|
|
* - B03 toc = 설명서 + 필요한 파일 · 고르는 방법 · 알아 둘 것 · B06 toc 에 「표준 횡단면 설정」
|
|
* - pipeTopic = 「구조물 · 배관」(B05 에서 배관을 고른 채 [?]) · leftovers = 0(옮긴 글이 패널에 없음)
|
|
*/
|
|
(async () => {
|
|
const w = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
const until = async (fn, ms = 15000) => {
|
|
for (let t = 0; t < ms; t += 200) {
|
|
const v = fn();
|
|
if (v) return v;
|
|
await w(200);
|
|
}
|
|
return null;
|
|
};
|
|
const MOVED = [
|
|
"[저장]은 이 폼에 있는 칸만",
|
|
"에서 관리 — 여기서 넣어도",
|
|
"사방기술교본",
|
|
"표준 편절편성 단면 모식도",
|
|
"L형 측구는 각 횡단면도에서",
|
|
"끌어 놓으면 확장자로",
|
|
"shapefile 한 벌",
|
|
"작업 좌표계는 라이다 PRJ",
|
|
"칸이 생기기 전의 동작",
|
|
"소광리 도면 H=2.0",
|
|
];
|
|
const start = location.hash;
|
|
const vis = (n) => n && n.offsetParent !== null;
|
|
const leftText = () =>
|
|
document.querySelector(".ui-workflow-overlay__panel--title")?.innerText ?? "";
|
|
const openModal = async (btn) => {
|
|
btn.click();
|
|
const box = await until(() => document.querySelector(".ui-help .ui-help__text h2"));
|
|
const res = {
|
|
modal: !!box,
|
|
toc: [...document.querySelectorAll(".ui-help__link")].map((b) => b.innerText.trim()),
|
|
text: box?.innerText ?? null,
|
|
active: document.querySelector(".ui-help__text")?.dataset.helpKey ?? null,
|
|
};
|
|
const temp = [...document.querySelectorAll(".ui-help__link")].find((b) =>
|
|
b.dataset.helpKey?.startsWith("99_"),
|
|
);
|
|
if (temp) {
|
|
temp.click();
|
|
res.temp = document.querySelector(".ui-help__text p")?.innerText ?? null;
|
|
}
|
|
document.querySelector(".ui-help .ui-modal__top button")?.click();
|
|
await w(200);
|
|
res.closed = !document.querySelector(".ui-help");
|
|
return res;
|
|
};
|
|
const out = { pages: [] };
|
|
// orca eval 은 한 번에 1분쯤에서 끊김 — 앞에 `window.__help542 = ["b05-profile", …];` 를 붙이면 그 화면만
|
|
const routes = window.__help542 ?? [
|
|
"b02-proj-register",
|
|
"b03-file-input",
|
|
"b04-preprocess",
|
|
"b05-profile",
|
|
"b06-section",
|
|
"b07-design-detail",
|
|
"b08-quantity",
|
|
"b09-estimation",
|
|
];
|
|
let prev = null;
|
|
for (const route of routes) {
|
|
location.hash = `#/${route}`;
|
|
await w(3000); // 불러오는 동안의 임시 틀(B05 등)이 실제 화면으로 바뀔 때까지
|
|
// 앞 화면 단추가 빠지고 이 화면 단추가 설 때까지
|
|
const btn = await until(() =>
|
|
[...document.querySelectorAll(".ui-help-btn")].find((b) => vis(b) && b !== prev),
|
|
);
|
|
prev = btn;
|
|
await w(1500);
|
|
const row = btn?.parentElement;
|
|
const res = {
|
|
page: route.slice(0, 3).toUpperCase(),
|
|
btn: document.querySelectorAll(".ui-help-btn").length,
|
|
first: !!row && row.firstElementChild === btn,
|
|
inLeft: !!btn?.closest(".ui-sidebar-actions") || !!btn?.closest(".b02-proj__actions"),
|
|
leftovers: MOVED.filter((s) => leftText().includes(s)),
|
|
};
|
|
if (btn) Object.assign(res, await openModal(btn));
|
|
if (route === "b05-profile") {
|
|
// 배관 하나를 골라 [?] — 구조물 종류 항목이 먼저 열림(이미 골라져 있으면 그대로 · 끝나면 처음 상태로)
|
|
const picked = () => document.querySelector('[data-help-topic="구조물_배관"]');
|
|
const was = !!picked();
|
|
const item = await until(() =>
|
|
[...document.querySelectorAll(".b05-route__irregular-item")].find((li) =>
|
|
li.innerText.includes("배관"),
|
|
),
|
|
);
|
|
if (!was) item?.click();
|
|
await until(picked, 8000);
|
|
await w(800);
|
|
res.leftoversPipe = MOVED.filter((s) => leftText().includes(s));
|
|
const again = await openModal([...document.querySelectorAll(".ui-help-btn")].find(vis));
|
|
res.pipeTopic = again.text;
|
|
if (!was) item?.click(); // 고름 풂
|
|
}
|
|
out.pages.push(res);
|
|
}
|
|
location.hash = start;
|
|
return JSON.stringify(out);
|
|
})();
|