diff --git a/A05_EduDetail/A05_EduDetail_Guide_Capture.py b/A05_EduDetail/A05_EduDetail_Guide_Capture.py index 4173f70ca..514c861ba 100644 --- a/A05_EduDetail/A05_EduDetail_Guide_Capture.py +++ b/A05_EduDetail/A05_EduDetail_Guide_Capture.py @@ -9,8 +9,8 @@ - --force = `_manual.json` 그림도 찍음 · --headed = 창을 띄워 찍음(헤드리스에서 3D · 지도가 안 그려질 때) - 프로젝트 = A05_EduDetail/guide/_projects.json `{"road": "", "stab": "", "plan": ""}` · --project-id 를 주면 그 id 가 모든 프로젝트 장면에 우선(자기 검증 프로젝트로 시험할 때) - - 로그인 = 장면 칸 account 대로 — sys(기본) = tmp/aislo_cred.json · company_admin · user = tmp/verify_accounts.json - 의 「회사관리자」 · 「일반」 · 계정마다 컨텍스트를 따로 로그인(쓰는 것만 · 처음 쓸 때) · 값은 어디에도 찍지 않음 + - 로그인 = 장면 칸 account 대로 — sys(기본) = tmp/aislo_cred.json · company_admin · user · forest = tmp/verify_accounts.json + 의 「회사관리자」 · 「일반」 · 「산림청」 · 계정마다 컨텍스트를 따로 로그인(쓰는 것만 · 처음 쓸 때) · 값은 어디에도 찍지 않음 - 끝에 표(장면 · 크기 · kB · 걸린 시간 · 실패 까닭) · 실패가 하나라도 있으면 종료 코드 1 `_scenes.json` 꼴 = 장면(그림 하나) 목록 — 이 머리 설명이 기준 @@ -18,7 +18,7 @@ { "name": "B05_00_overview", 필수 · <페이지>_<두 자리>_<영문 소문자·숫자·_> · 그림 = .webp "route": "#/b05-profile", 필수 · 해시 주소("#/…") · vite 주소 뒤에 붙임 - "account": "sys", 선택 · sys(기본 · 시스템 관리자) | company_admin | user · 역할마다 화면이 다른 페이지용 + "account": "sys", 선택 · sys(기본 · 시스템 관리자) | company_admin | user | forest(산림청) · 역할마다 화면이 다른 페이지용 "project": "road", road | stab | plan | none(기본) · none = 현재 프로젝트 비움 "viewport": [1600, 900], 선택 · 화면 크기(CSS px) · 기본 1600×900 · 그림은 늘 2배 "before": [ 단계, … ], 선택 · 찍기 전 조작(아래 단계 꼴) diff --git a/A05_EduDetail/A05_EduDetail_Guide_Capture_Check.py b/A05_EduDetail/A05_EduDetail_Guide_Capture_Check.py index 5a5082a59..581d009dc 100644 --- a/A05_EduDetail/A05_EduDetail_Guide_Capture_Check.py +++ b/A05_EduDetail/A05_EduDetail_Guide_Capture_Check.py @@ -14,6 +14,7 @@ PROJECT_KEYS = ("road", "stab", "plan", "none") ACCOUNT_KEYS = { "company_admin": "회사관리자", "user": "일반", + "forest": "산림청", } # 장면 account → 파일 열쇠 (sys 는 CRED) ACCOUNTS = ("sys", *ACCOUNT_KEYS) STEP_KINDS = ( diff --git a/A05_EduDetail/guide/B01/00_설명서.md b/A05_EduDetail/guide/B01/00_설명서.md index dfbfe9586..9de5ea47a 100644 --- a/A05_EduDetail/guide/B01/00_설명서.md +++ b/A05_EduDetail/guide/B01/00_설명서.md @@ -41,6 +41,16 @@ - 산림청 — 예정노선을 만드는 계정 · [받은 예정노선] 대신 홈에 [예정노선] 칸. - 시스템 관리자 — 모든 메뉴 + [시스템 관리] 묶음 · 머리 줄에서 볼 회사를 바꿈. +산림청 화면 — 왼쪽 메뉴에 [받은 예정노선] · [사람] · [시스템 관리] 가 없음. + +![산림청 화면](B01_00_forest_menu.webp) + +| 번호 | 구역 | 하는 일 | +| --- | --- | --- | +| 1 | 사용자 메뉴 | 산림청 계정의 이름 · 내 정보 · 로그아웃 | +| 2 | 왼쪽 메뉴 | 홈 · 프로젝트 · 임시 보관함 · 회사 정보 · 회사 설계 기본값 · 사용자 가이드 · 지식 챗봇 | +| 3 | 페이지 자리 | [홈] — 오른쪽에 [예정노선] 칸 | + > 참고: 권한 없는 페이지 주소로 들어오면 [홈] 이 열림. ## 작업 순서 diff --git a/A05_EduDetail/guide/B01/01_홈.md b/A05_EduDetail/guide/B01/01_홈.md index a78b7ee88..49f2945d1 100644 --- a/A05_EduDetail/guide/B01/01_홈.md +++ b/A05_EduDetail/guide/B01/01_홈.md @@ -47,3 +47,7 @@ - [작게] = 한 줄 목록(9 넘으면 요약 · 그래프) · [크게] = 큰 · 중간 카드. > 참고: 산림청 계정은 오른쪽에 [예정노선] 칸이 더 있음. + +![산림청 홈](B01_01_home_forest.webp) + +① [예정노선] 칸 — 분석 전 · 분석됨 · 확정 수 + 업체 지정 대기 수. diff --git a/A05_EduDetail/guide/B01/B01_00_forest_menu.webp b/A05_EduDetail/guide/B01/B01_00_forest_menu.webp new file mode 100644 index 000000000..df56f4262 Binary files /dev/null and b/A05_EduDetail/guide/B01/B01_00_forest_menu.webp differ diff --git a/A05_EduDetail/guide/B01/B01_01_home_forest.webp b/A05_EduDetail/guide/B01/B01_01_home_forest.webp new file mode 100644 index 000000000..a88970cd9 Binary files /dev/null and b/A05_EduDetail/guide/B01/B01_01_home_forest.webp differ diff --git a/A05_EduDetail/guide/B01/_scenes.json b/A05_EduDetail/guide/B01/_scenes.json index a84781cff..a012df4ee 100644 --- a/A05_EduDetail/guide/B01/_scenes.json +++ b/A05_EduDetail/guide/B01/_scenes.json @@ -54,6 +54,45 @@ } ] }, + { + "name": "B01_00_forest_menu", + "route": "#/b01-account?view=home", + "account": "forest", + "project": "none", + "viewport": [ + 1600, + 720 + ], + "before": [ + { + "eval": "document.head.insertAdjacentHTML('beforeend','')" + }, + { + "wait": ".b01-shell__page" + }, + { + "wait_ms": 1200 + }, + { + "eval": "(()=>{const W=s=>s\n.replace(/홍길동\\(견본\\)/g,'이민수').replace(/엄상돈|브레인관리자/g,'홍길동').replace(/엄상준|브레인사용자/g,'김영희').replace(/박동철/g,'박철수').replace(/산림청검증/g,'홍길동')\n.replace(/캐미팩토리/g,'예시건설').replace(/브레인검증회사_\\d+/g,'예시설계').replace(/검증_[^\\s)]+/g,'가이드_견본')\n.replace(/\\d{3}-\\d{2}-\\d{5}/g,'000-00-00000').replace(/\\b0\\d{1,2}-?\\d{3,4}-?\\d{4}\\b/g,'010-0000-0000')\n.replace(/대전광역시[^\\n]*/g,'○○시 ○○구 ○○로 1').replace(/[\\w.+-]+@[\\w.-]+\\.\\w+/g,'user@example.com');\nconst fn=()=>{\n document.querySelectorAll('.b01-proj-card,.b01-proj-row').forEach(c=>{const t=c.querySelector('.b01-proj-card__name,td');if(t&&!/^가이드_/.test(t.textContent.trim()))c.style.display='none';});\n const w=document.createTreeWalker(document.body,NodeFilter.SHOW_TEXT);let n;\n while((n=w.nextNode())){const s=n.nodeValue;if(!s||!s.trim())continue;let v=W(s);if(/^\\s*[엄브박]\\s*$/.test(v))v='홍';if(v!==s)n.nodeValue=v;}\n document.querySelectorAll('input').forEach(i=>{const v=W(i.value);if(v!==i.value)i.value=v;});\n document.querySelectorAll('img').forEach(m=>{m.style.visibility='hidden';});};\nfn();setInterval(fn,100);})()" + } + ], + "clip": null, + "callouts": [ + { + "n": 1, + "sel": ".b01-shell__user" + }, + { + "n": 2, + "sel": ".b01-shell__nav" + }, + { + "n": 3, + "sel": ".b01-shell__page" + } + ] + }, { "name": "B01_01_home_first", "route": "#/b01-account?view=home", @@ -96,6 +135,33 @@ } ] }, + { + "name": "B01_01_home_forest", + "route": "#/b01-account?view=home", + "account": "forest", + "project": "none", + "before": [ + { + "eval": "document.head.insertAdjacentHTML('beforeend','')" + }, + { + "wait": ".b01-shell__page" + }, + { + "wait_ms": 1200 + }, + { + "eval": "(()=>{const W=s=>s\n.replace(/홍길동\\(견본\\)/g,'이민수').replace(/엄상돈|브레인관리자/g,'홍길동').replace(/엄상준|브레인사용자/g,'김영희').replace(/박동철/g,'박철수').replace(/산림청검증/g,'홍길동')\n.replace(/캐미팩토리/g,'예시건설').replace(/브레인검증회사_\\d+/g,'예시설계').replace(/검증_[^\\s)]+/g,'가이드_견본')\n.replace(/\\d{3}-\\d{2}-\\d{5}/g,'000-00-00000').replace(/\\b0\\d{1,2}-?\\d{3,4}-?\\d{4}\\b/g,'010-0000-0000')\n.replace(/대전광역시[^\\n]*/g,'○○시 ○○구 ○○로 1').replace(/[\\w.+-]+@[\\w.-]+\\.\\w+/g,'user@example.com');\nconst fn=()=>{\n document.querySelectorAll('.b01-proj-card,.b01-proj-row').forEach(c=>{const t=c.querySelector('.b01-proj-card__name,td');if(t&&!/^가이드_/.test(t.textContent.trim()))c.style.display='none';});\n const w=document.createTreeWalker(document.body,NodeFilter.SHOW_TEXT);let n;\n while((n=w.nextNode())){const s=n.nodeValue;if(!s||!s.trim())continue;let v=W(s);if(/^\\s*[엄브박]\\s*$/.test(v))v='홍';if(v!==s)n.nodeValue=v;}\n document.querySelectorAll('input').forEach(i=>{const v=W(i.value);if(v!==i.value)i.value=v;});\n document.querySelectorAll('img').forEach(m=>{m.style.visibility='hidden';});};\nfn();setInterval(fn,100);})()" + } + ], + "clip": ".b01-shell__page", + "callouts": [ + { + "n": 1, + "sel": ".b01-home__pane:has(h3:text-is('예정노선'))" + } + ] + }, { "name": "B01_01_home_many", "route": "#/b01-account?view=home", diff --git a/resources/tester/test_539_guide_capture.py b/resources/tester/test_539_guide_capture.py index a7f11baba..34591b3cf 100644 --- a/resources/tester/test_539_guide_capture.py +++ b/resources/tester/test_539_guide_capture.py @@ -198,7 +198,7 @@ def test_callout_and_clip_boxes(): assert G.union_clip([{"x": -50, "y": 0, "w": 2000, "h": 10}], 16, 1600, 900)["width"] == 1600 -@pytest.mark.parametrize("acct", ["sys", "company_admin", "user"]) +@pytest.mark.parametrize("acct", ["sys", "company_admin", "user", "forest"]) def test_account_ok(acct): assert G.check_scene(_scene(account=acct), "B05") == []