Compare commits

..
Author SHA1 Message Date
jcchoi c2396f093b 필수입력 안내 메세지
Deploy Frontend / deploy (push) Successful in 8m31s
2026-10-07 19:43:06 +09:00
jcchoi bdf65dcfd1 설치인가 사업구분 팝업 사이즈 조정 2026-10-07 19:42:42 +09:00
jcchoi 2aefbe17ee 웹접근성 2차 수정 2026-10-07 19:42:20 +09:00
jcchoi 4482b92ccd 메뉴간 탭이동
Deploy Frontend / deploy (push) Successful in 7m33s
2026-10-06 17:41:39 +09:00
jcchoi d3c39caefb 웹 접근성 조치 2026-10-06 14:32:26 +09:00
jcchoi 24c5dce24d 대체 텍스트 적용 2026-10-06 13:18:58 +09:00
jcchoi d4d9eaf773 CM 로그인
Deploy Frontend / deploy (push) Successful in 5m32s
하단 메뉴 링크
2026-10-06 11:13:46 +09:00
jcchoi 68a800cdfc 메인페이지 탭이동
Deploy Frontend / deploy (push) Successful in 2m54s
2026-10-02 21:52:10 +09:00
jcchoi ff45d1a875 스킵 네비게이션 2026-10-02 21:51:56 +09:00
jcchoi 49000c6140 FAQ 웹접근성(툴팁) 2026-10-02 21:25:44 +09:00
jcchoi 24bba484ca Merge branch 'main' into deploy
Deploy Frontend / deploy (push) Successful in 3m49s
2026-10-02 19:43:52 +09:00
jcchoi c8d0d85937 Merge branch 'deploy' of https://www.onasys.co.kr:3000/ONAANDALL/frontend into deploy 2026-10-02 19:42:49 +09:00
jcchoi c692f7c647 Merge branch 'main' of https://www.onasys.co.kr:3000/ONAANDALL/frontend 2026-10-02 19:40:06 +09:00
jcchoi 080463458b 도움말 표시 2026-10-02 19:38:00 +09:00
jcchoi 08aaf4dd62 누락 리소스 추가 2026-10-02 19:29:13 +09:00
chanii8 ad1e517472 Merge branch 'main' into deploy
Deploy Frontend / deploy (push) Successful in 3m56s
2026-10-02 17:55:30 +09:00
chanii8 17ed5eb46b Merge branch 'iipbs/as/dev' 2026-10-02 17:54:53 +09:00
chanii8 1a2faf02da [as] feat: 알림톡발송 페이지 구현 2026-10-02 17:54:25 +09:00
chanii8 d6522338aa [as] chore: 행정지원 숫자 폼 최대자릿수 제한 2026-10-02 16:37:26 +09:00
chanii8 df154a45b6 Merge branch 'main' into deploy
Deploy Frontend / deploy (push) Successful in 4m3s
2026-10-02 15:16:46 +09:00
chanii8 c5dbea334d Merge branch 'iipbs/as/dev' 2026-10-02 15:15:36 +09:00
chanii8 85f535eb5d [as] chore: 행정지원 숫자 폼 음수 입력 제한 2026-10-02 15:14:22 +09:00
chanii8 9334514c71 [as] chore: 행정지원 폼 사업기간 스키마 수정 2026-10-02 14:55:42 +09:00
chanii8 d438755616 Merge branch 'main' into deploy
Deploy Frontend / deploy (push) Successful in 7m37s
2026-10-02 13:12:44 +09:00
chanii8 54595fb7b6 Merge remote-tracking branch 'origin/iipbs/st/dev' 2026-10-02 13:07:41 +09:00
chanii8 4ee8d5a099 Merge branch 'deploy' of https://www.onasys.co.kr:3000/ONAANDALL/frontend into deploy 2026-10-02 13:05:57 +09:00
chanii8 abe5fae4c4 Merge branch 'iipbs/as/dev' 2026-10-02 13:03:56 +09:00
chanii8 aeb48661b1 [as] chore: 보완 요청 사항 적용
- 사업기간 폼 포매팅
2026-10-02 13:03:24 +09:00
jcchoi 4bdf68c2b6 좌측메뉴 탭 이동 처리 2026-10-02 11:39:49 +09:00
chanii8 c5a0e378fd [as] feat: 보완 요청 사항 적용
- 실무협의서 내 보완요청 버튼 추가
- 대시보드 수정
2026-10-02 11:37:45 +09:00
jcchoi 538f656640 Merge branch 'main' into deploy
Deploy Frontend / deploy (push) Canceled after 6m27s
2026-10-01 22:25:22 +09:00
jcchoi a323c42acf 테이블에 scope="col" 및 캡션 추가
Deploy Frontend / deploy (push) Successful in 4m16s
2026-10-01 22:15:11 +09:00
jcchoi 095101ad2f 필수항목 tooltip 2026-10-01 22:14:28 +09:00
jcchoi 7ee5ebd506 글자 확대 축소 2026-10-01 20:26:45 +09:00
jcchoi f90ef6297d 상단메뉴 클릭 표준 2026-10-01 18:03:03 +09:00
chanii8 4167107a91 [as] feat: 파일 업로드 에러 로직 수정 2026-10-01 16:41:10 +09:00
kiminchan 90c1cb1f52 Merge branch 'iipbs/sn/dev' 2026-10-01 16:40:10 +09:00
mind-one001 8c614b84a7 merge(sn): preserve modular map entry with remote import cleanup 2026-10-01 16:22:02 +09:00
kiminchan 7d1a501ad8 관망도 페이지 import 병합 충돌 해소 2026-10-01 16:03:12 +09:00
mind-one001 48589274c8 merge(sn): integrate latest survey layers and upload guidance 2026-10-01 15:59:43 +09:00
kiminchan 83f7676db4 조사 레이어 표출 및 조사결과 업로드 안내 개선 2026-10-01 15:55:29 +09:00
mind-one001 c8b30810f6 style(sn): format integrated map modules 2026-10-01 15:54:43 +09:00
mind-one001 f71fa7d97a merge(sn): retain remote layer and flood updates after refactoring 2026-10-01 15:53:30 +09:00
mind-one001 4c7c4c00ab refactor(sn): modularize map and features and standardize file naming 2026-10-01 15:47:57 +09:00
chanii8 d2645a9c08 [as] feat: 파일 업로드 확장자 제한 정책 적용 2026-10-01 15:36:02 +09:00
mind-one005 ae341d66ba sn: 침수예측 오버레이 수정 2026-10-01 15:02:53 +09:00
chanii8 fce4def951 [as] feat: 행정지원 숫자 폼 소숫점 자리 제한 2026-10-01 14:26:22 +09:00
chanii8 ba0964f772 [as] feat: useTus > handleError 수정 2026-10-01 13:44:46 +09:00
kiminchan e346417c29 Merge branch 'iipbs/sn/dev' 2026-10-01 10:15:58 +09:00
kiminchan 5fcc184a88 노후관로 레이어를 DB 설정 기반으로 전환 2026-10-01 09:46:16 +09:00
mind-one005 f6d3f89b5b Merge branch 'iipbs/sn/dev' of https://www.onasys.co.kr:3000/ONAANDALL/frontend into iipbs/sn/dev 2026-10-01 00:26:53 +09:00
mind-one005 106e09a7a2 sn: 도시침수예방사업 지정일 수정 2026-10-01 00:26:36 +09:00
mind-one005 d1b4600392 sn: 도시침수예방사업 수정화면 사업순번 단계 수정 불가 2026-10-01 00:16:07 +09:00
kiminchan 4204dfa624 Merge branch 'iipbs/sn/dev' of https://www.onasys.co.kr:3000/ONAANDALL/frontend into iipbs/sn/dev 2026-09-30 18:15:15 +09:00
kiminchan d7fd5be068 관로분석 및 통수위험 기본 조회조건 개선 2026-09-30 18:13:31 +09:00
mind-one005 735bb397ec sn: 침수예측현황 분석시각 조건 초기화 2026-09-30 18:09:20 +09:00
mind-one005 8b5a2b713c sn: 도시침수지도 자동선택 2026-09-30 17:53:50 +09:00
rsone001 f2ec9327fd feat: [ST] - eval 제거 2026-09-30 17:17:01 +09:00
yangsein 5331e10c96 [refactor] 대시보드 - 통계처리현황 반려되어 제출중인 상태 구분 처리 포함 2026-09-30 16:59:05 +09:00
chanii8 7090f02a52 [as] feat: 보완 요청 사항 반영 (260930_1128) 2026-09-30 11:28:28 +09:00
chanii8 12152a6810 [as] chore: 파일보완 다이얼로그 컨텐츠 최대 높이 지정 2026-09-29 17:41:37 +09:00
chanii8 c0c2d3d1c9 Merge remote-tracking branch 'origin/iipbs/as/dev' 2026-09-29 17:32:18 +09:00
chanii8 858844e81a [as] chore: 설계자문 진행상태 모델 수정 2026-09-29 16:58:01 +09:00
chanii8 1ff2731121 Merge branch 'iipbs/cs/dev' 2026-09-29 15:37:15 +09:00
chanii8 70db7662bb [cs] chore: 모듈API관리 폼 수정 2026-09-29 15:36:37 +09:00
chanii8 bb57ff72e7 [cs] feat: 모듈API관리 "API URL" 검색 조건 추가 2026-09-29 15:19:42 +09:00
chanii8 8df79fd624 Merge branch 'main' into deploy
Deploy Frontend / deploy (push) Successful in 3m47s
2026-09-29 14:40:09 +09:00
chanii8 7946c08c72 Merge branch 'iipbs/as/dev' 2026-09-29 14:29:32 +09:00
chanii8 6f20ef7273 [as] feat: 보완 요청 사항 반영 (260929_1429) 2026-09-29 14:29:13 +09:00
mind-one005 657ae77dde Merge branch 'iipbs/sn/dev' 2026-09-29 14:03:36 +09:00
mind-one005 4ff80dd257 cm: 유역별 정보 수정 2026-09-29 11:38:47 +09:00
mind-one005 9bb1069d26 cm: 노후 하수관로 현황 수정 2026-09-29 11:17:52 +09:00
chanii8 730be25948 Merge remote-tracking branch 'origin/main' into deploy
Deploy Frontend / deploy (push) Successful in 5m4s
2026-09-28 17:17:08 +09:00
chanii8 78d8fea7f5 Merge branch 'iipbs/as/dev' 2026-09-28 16:44:05 +09:00
chanii8 22ed78c87b [as] feat: 행정지원 페이지 useSearchParamsState 적용 2026-09-28 16:37:20 +09:00
mind-one005 f5331d4c50 cm: 유역별 정보 div 수정 2026-09-28 16:32:16 +09:00
mind-one005 f32fe0ec5b cm: 유역별 정보 2026-09-28 16:07:52 +09:00
chanii8 3b914fbc2e [as] feat: 보완 요청 사항 반영 (20260928_1521) 2026-09-28 15:21:19 +09:00
kiminchan 533df0eb16 Merge branch 'iipbs/sn/dev' 2026-09-28 13:23:36 +09:00
chanii8 9c38165afb Merge branch 'main' into deploy
Deploy Frontend / deploy (push) Successful in 7m25s
2026-09-28 11:24:12 +09:00
mind-one001 7b506320b4 서버페이징 변경 2026-09-28 11:22:22 +09:00
chanii8 2b7c497c3e Merge branch 'iipbs/as/dev' 2026-09-28 11:20:57 +09:00
chanii8 4dee1309eb [as] feat: 보완 요청 사항 반영 (260928_1120) 2026-09-28 11:20:31 +09:00
kiminchan f3f8909e45 Merge branch 'iipbs/sn/dev' 2026-09-28 10:00:24 +09:00
mind-one001 d45cd79422 테스트코드 삭제 2026-09-23 16:00:28 +09:00
mind-one001 7cbb58ff32 노후관로 조회 기능 보완 2026-09-23 14:58:14 +09:00
chanii8 9242e1fb47 Merge branch 'main' into deploy
Deploy Frontend / deploy (push) Successful in 12m36s
2026-09-23 14:44:23 +09:00
chanii8 f5ce74d0ee Merge remote-tracking branch 'origin/iipbs/as/dev' 2026-09-23 14:39:57 +09:00
chanii8 3114280e83 [as] chore: 알림이력 배지 크기 조정 2026-09-23 14:39:24 +09:00
chanii8 c7b8b36f4a Merge branch 'iipbs/common/dev' 2026-09-23 14:17:15 +09:00
chanii8 60ee194cc9 [common/components] design: NoticePopover 스타일 수정 2026-09-23 13:55:16 +09:00
mind-one001 4f50593eac Merge branch 'iipbs/sn/dev' of https://www.onasys.co.kr:3000/ONAANDALL/frontend into iipbs/sn/dev 2026-09-23 13:50:59 +09:00
mind-one001 8818dd21c6 관망도 레이어 전체켜기 기능 추가 2026-09-23 13:50:50 +09:00
chanii8 db8ee298d9 Merge branch 'iipbs/cs/dev' 2026-09-23 11:40:04 +09:00
chanii8 9eef99a435 [cs] chore: 게시판 댓글 사용 여부 적용 2026-09-23 11:39:32 +09:00
chanii8 3d027ed374 [common/features] chore: 게시판 댓글 사용 여부 적용 2026-09-23 11:37:16 +09:00
chanii8 271b5d445d [as] chore: 재원협의 버튼 수정
Deploy Frontend / deploy (push) Successful in 3m57s
2026-09-23 11:12:26 +09:00
chanii8 2457d14ae9 Merge branch 'main' into deploy
Deploy Frontend / deploy (push) Successful in 6m32s
2026-09-23 09:51:39 +09:00
chanii8 d70eb17a72 Merge branch 'iipbs/as/dev' 2026-09-23 09:50:30 +09:00
chanii8 ddd619babc [as] feat: 행정지원 문서 체크리스트 레이블 변경 2026-09-23 09:48:08 +09:00
chanii8 5d27ee830e [as] feat: 행정지원 문서 체크리스트 탭 노출 알고리즘 수정 2026-09-23 09:35:35 +09:00
mind-one005 b73b83a49f Merge branch 'iipbs/sn/dev' of https://www.onasys.co.kr:3000/ONAANDALL/frontend into iipbs/sn/dev 2026-09-23 09:08:05 +09:00
mind-one005 549debf8bf sn: 노후하수관로정비사업 검색조건 추가 2026-09-23 09:07:56 +09:00
mind-one005 212b9a43a9 Merge branch 'iipbs/wr/dev' 2026-09-22 20:49:40 +09:00
mind-one005 f092a23ee4 wr: font 크기 조정 2026-09-22 20:45:22 +09:00
chanii8 25c357a423 [as] chore: 보완요청 섹션 첨부파일 관련 코드 수정 2026-09-22 16:21:13 +09:00
chanii8 a77246a1db [as] fix: 타입 에러 2026-09-22 15:39:06 +09:00
chanii8 f00ce31648 [as] refactor: zod 스키마 .optional()-> .nullish() 변경 2026-09-22 15:12:28 +09:00
chanii8 dc57a491dd [as] chore: 재원협의 코드 수정 2026-09-22 15:02:36 +09:00
mind-one005 c9b7266959 wr: 재이용실적 수정 2026-09-22 11:24:32 +09:00
chanii8 0dd2111cb9 [as] refactor: 재원협의 폼 useWatch + Controller 방식 제거 2026-09-22 10:57:41 +09:00
mind-one005 c39b048398 Merge branch 'iipbs/wr/dev' 2026-09-22 10:25:49 +09:00
chanii8 87fbf15e2b [as] feat: 재원협의 수정 2026-09-22 10:23:10 +09:00
mind-one005 db1cfaa1a6 wr: label 위치 조정 2026-09-22 10:05:49 +09:00
mind-one005 905b750877 Merge branch 'iipbs/sn/dev' 2026-09-22 09:28:50 +09:00
mind-one005 be14fe2603 Merge branch 'iipbs/sn/dev' of https://www.onasys.co.kr:3000/ONAANDALL/frontend into iipbs/sn/dev 2026-09-22 09:06:39 +09:00
chanii8 9739609de4 Merge branch 'main' into deploy
Deploy Frontend / deploy (push) Successful in 4m15s
2026-09-21 17:51:47 +09:00
mind-one005 d7f101ee30 wr: 시도,시군구 전체"0" 2건 조회현상 수정 2026-09-21 17:51:09 +09:00
chanii8 20f7d595a1 Merge branch 'iipbs/as/dev' 2026-09-21 17:50:59 +09:00
chanii8 e909dc81ad [as] chore: 재원협의 버튼 노출 조건 수정 2026-09-21 17:50:23 +09:00
chanii8 a510779ea1 [as] feat: AI 만족도 평가 기능 구현 2026-09-21 17:24:01 +09:00
chanii8 c799c199c5 Merge branch 'main' into deploy
Deploy Frontend / deploy (push) Successful in 8m28s
2026-09-21 16:58:49 +09:00
chanii8 0818e9ade2 Merge branch 'iipbs/as/dev' 2026-09-21 16:57:46 +09:00
chanii8 e60a8bed8b fix: 빌드 에러 2026-09-21 16:57:16 +09:00
chanii8 17fdcd7d1f fix: 빌드 에러 2026-09-21 16:56:46 +09:00
chanii8 6412e1a997 Merge branch 'iipbs/as/dev' 2026-09-21 16:36:58 +09:00
chanii8 1674598480 [as] design: RHFDevtool 스타일 수정 2026-09-21 16:36:28 +09:00
chanii8 23ebf36244 [as] feat: "@hookform/devtools" 추가 2026-09-21 16:04:19 +09:00
chanii8 342db06685 [as] refactor: 행정지원 문서 저장 payload 스키마 수정 2026-09-21 15:18:42 +09:00
mind-one001 35b9f813c4 로그삭제 2026-09-21 15:08:07 +09:00
mind-one005 aafb326662 Merge branch 'iipbs/sn/dev' of https://www.onasys.co.kr:3000/ONAANDALL/frontend into iipbs/sn/dev 2026-09-21 14:46:02 +09:00
mind-one005 aa1b309b26 wr: 중수도 단위, 모달 조회 순서, 시설구분 조회 2026-09-21 14:45:50 +09:00
100JM 2c355525df [il] - DB 표준화로 인한 소스 수정 2026-09-21 13:55:37 +09:00
chanii8 bd20a499d3 [as] feat: AI 수동 검증 버튼 추가 2026-09-21 13:34:26 +09:00
chanii8 5fec5d5239 [as] feat: RAG 인덱싱 상태일 때 검토자 지정 버튼 분기 처리 2026-09-21 11:33:59 +09:00
chanii8 5b3aaa463d Merge branch 'main' into deploy
Deploy Frontend / deploy (push) Successful in 3m27s
2026-09-21 11:03:48 +09:00
chanii8 a14b22b1ef Merge branch 'iipbs/as/dev' 2026-09-21 11:02:55 +09:00
chanii8 50aa549311 [as] feat: 공단 실무협의서 관리 버튼 노출 조건 수정 2026-09-21 11:02:22 +09:00
kiminchan bf0aef59cd Merge remote-tracking branch 'origin/iipbs/sn/dev' into iipbs/sn/dev_kic 2026-09-21 10:06:26 +09:00
kiminchan b2ddcd0cf3 sn : 통수위험 결과 안내문에 위험 판정기준 및 상태 색상 표시 2026-09-21 09:55:55 +09:00
chanii8 947dba5934 Merge branch 'main' into deploy
Deploy Frontend / deploy (push) Successful in 3m43s
2026-09-18 17:38:37 +09:00
chanii8 572ef04bb4 Merge branch 'iipbs/as/dev' 2026-09-18 17:37:31 +09:00
chanii8 110d6c689c [as] feat: UploadedFileChip 컴포넌트 props 추가(onDownload) 2026-09-18 17:33:45 +09:00
chanii8 f40d6fd5e8 [as] feat: AttachmentDownloadLink 컴포넌트 구현 및 적용 2026-09-18 16:51:00 +09:00
mind-one001 49ace44c9b 테스트 파일 삭제 2026-09-18 16:35:21 +09:00
chanii8 cc3bc548c9 [as] feat: 재원협의 코드 수정 2026-09-18 16:27:51 +09:00
chanii8 4816a512bf Merge branch 'main' into deploy
Deploy Frontend / deploy (push) Successful in 3m40s
2026-09-17 17:08:09 +09:00
chanii8 cc3d7ccd7b Merge remote-tracking branch 'origin/iipbs/as/dev' 2026-09-17 17:05:08 +09:00
chanii8 43bc7db7d5 [as] chore: useAplnRows 수정 2026-09-17 17:04:31 +09:00
chanii8 b0672aead5 Merge branch 'iipbs/as/dev' 2026-09-17 16:48:50 +09:00
chanii8 086d5a18e8 [as] chore: 재원협의 코드 수정 2026-09-17 16:48:13 +09:00
mind-one005 91576f401b sn: 침수예측오버레이 수정 2026-09-17 15:41:08 +09:00
mind-one005 febcd18eda Merge branch 'iipbs/sn/dev' of https://www.onasys.co.kr:3000/ONAANDALL/frontend into iipbs/sn/dev 2026-09-17 14:05:11 +09:00
mind-one005 8cc9f0d291 sn: 침수예측현황 침수위험도 수정 2026-09-17 14:04:51 +09:00
chanii8 41643563f8 [as] chore: 수정사항 반영 2026-09-17 10:55:51 +09:00
chanii8 b6b58eaeba feat: 재원협의&실무협의서 로직 사이클 2026-09-17 10:00:00 +09:00
chanii8 e8a5701e73 [as] feat: 웹기안기 다이얼로그 내 금액검증결과 섹션 구현 2026-09-16 17:37:44 +09:00
kiminchan a8f2c8f41a GIS 편집 신규 관로 미리보기 표시 보완 2026-09-16 17:32:02 +09:00
100JM 241222dcd1 [il] - 연계 db 표준화로 인한 소스 수정 2026-09-16 14:52:38 +09:00
chanii8 380575dae0 [as] feat: 실무협의서 검토 로직(RR, RK) 작업 2026-09-16 14:19:39 +09:00
mind-one001 4d685d5a67 Merge remote-tracking branch 'origin/iipbs/sn/dev' into iipbs/sn/dev 2026-09-16 11:15:30 +09:00
mind-one001 96196229f4 fix(sn): align business form limits with standardized database 2026-09-16 11:15:18 +09:00
chanii8 5e54039028 [as] feat: 실무협의서 검토자 지정(EV) 로직 작업 2026-09-15 16:42:21 +09:00
mind-one005 94b2e84c10 Merge branch 'iipbs/sn/dev' of https://www.onasys.co.kr:3000/ONAANDALL/frontend into iipbs/sn/dev 2026-09-15 16:28:23 +09:00
mind-one001 80d2230c9a 불필요 파일 삭제 2026-09-15 10:00:42 +09:00
chanii8 4fad163b14 Merge branch 'main' into deploy
Deploy Frontend / deploy (push) Successful in 4m4s
2026-09-14 17:56:23 +09:00
chanii8 4d20a68f93 Merge branch 'iipbs/as/dev' 2026-09-14 17:52:41 +09:00
chanii8 90a1d6fdff [as] feat: 웹기안기 '열기' 기능 추가(개발용) 2026-09-14 17:52:16 +09:00
chanii8 00e1cb707e [as] feat: 재원협의 환경청 조치결과 검토 의뢰(RA) 로직 작업 2026-09-14 17:35:00 +09:00
chanii8 6eeb774a21 [as] feat: 재원협의 지자체 조치완료(RB) 로직 작업 2026-09-14 13:36:23 +09:00
chanii8 6c4b8a52dc [as] chore: 보완요청 사항 적용 2026-09-14 10:16:16 +09:00
chanii8 a7e0d8f826 [as] feat: 첨부파일 컴포넌트 생성 및 적용 2026-09-11 17:23:45 +09:00
chanii8 d1ccddc1d3 [as] feat: 재원협의 기술검토 로직 작업 2026-09-11 17:02:09 +09:00
mind-one005 d5f0c3bc95 sn: 침수발생이력, 침수예측현황 팝업크기 변경 외 2026-09-11 11:01:55 +09:00
chanii8 da2191f365 Merge branch 'main' into deploy
Deploy Frontend / deploy (push) Successful in 3m43s
2026-09-11 10:38:12 +09:00
chanii8 056643bd96 Merge branch 'iipbs/as/dev' 2026-09-11 10:36:03 +09:00
chanii8 01d5ed297e [as] chore: 재원협의 상세화면 게이트 수정 2026-09-11 10:35:33 +09:00
chanii8 55ab2b8562 Merge remote-tracking branch 'origin/main' into deploy
Deploy Frontend / deploy (push) Successful in 3m33s
2026-09-10 17:53:02 +09:00
chanii8 dae5d0a9f5 Merge remote-tracking branch 'origin/iipbs/as/dev' 2026-09-10 17:52:46 +09:00
chanii8 41ad33310a [as] feat: 실무협의서 관리 다이얼로그 내 첨부파일 섹션 추가 2026-09-10 17:50:56 +09:00
chanii8 526392c370 Merge branch 'main' into deploy
Deploy Frontend / deploy (push) Successful in 3m39s
2026-09-10 15:44:08 +09:00
chanii8 b38ee9c7c7 Merge branch 'iipbs/as/dev' 2026-09-10 15:43:30 +09:00
chanii8 9f7f1db9b8 [as] feat: 기안기 저장 코드 수정 2026-09-10 14:50:09 +09:00
mind-one001 b7134cb3e4 노후관로현황 그리드 수정 2026-09-10 14:06:24 +09:00
mind-one001 ec78658e46 시도별 노후관로현황 그리드 수정 2026-09-10 14:01:58 +09:00
mind-one001 44361af392 그리드 css 통합 2026-09-10 13:51:42 +09:00
mind-one001 76130caa6d Merge branch 'iipbs/sn/dev' of https://www.onasys.co.kr:3000/ONAANDALL/frontend into iipbs/sn/dev 2026-09-10 11:30:58 +09:00
mind-one001 352a78a0c5 gis 업로드 오류 기능 수정 2026-09-10 11:30:52 +09:00
chanii8 6020c80a7a Merge branch 'main' into deploy
Deploy Frontend / deploy (push) Successful in 10m6s
2026-09-09 18:09:33 +09:00
chanii8 a2a165a42b Merge branch 'iipbs/as/dev' 2026-09-09 18:08:35 +09:00
chanii8 0f27c1e5ce [as] chore: 웹기안기 다이얼로그 수정 2026-09-09 18:08:08 +09:00
chanii8 e944ad4369 [as] feat: 실무협의서 웹기안기에 렌더링 2026-09-09 17:38:40 +09:00
kiminchan 65bee9586d 도시침수지도 목록 이동 운영 보완 기록 2026-09-09 16:45:12 +09:00
mind-one001 31cda8579a Merge branch 'iipbs/sn/dev' of https://www.onasys.co.kr:3000/ONAANDALL/frontend into iipbs/sn/dev 2026-09-09 15:42:53 +09:00
mind-one001 1dc40b9efc 빈 레이어 트리로 지도만 재사용하는 화면에서는 패널 외곽과 제목도 표시하지 않는다. 2026-09-09 15:42:31 +09:00
mind-one005 6cb3d8ad65 Merge branch 'iipbs/wr/dev' into iipbs/sn/dev 2026-09-09 14:06:31 +09:00
LEEKYUHYUN 225e2732d1 사이드패널 패딩 조정 및 스크롤바 수정 2026-09-09 11:35:59 +09:00
chanii8 768ad001d2 [as] feat: 재원협의 쿼리 무효화 로직 수정 2026-09-09 10:30:29 +09:00
mind-one005 866d11988d Merge branch 'iipbs/sn/dev' 2026-09-09 09:27:53 +09:00
mind-one005 d82ae99b6a sn: 오류 수정 2026-09-09 09:09:09 +09:00
mind-one005 eb4f6f1b09 Merge branch 'iipbs/sn/dev' 2026-09-08 22:29:39 +09:00
mind-one005 23341b93c7 sn: 침수흔적심선/위선 화살표 연속 scroll 추가 2026-09-08 18:15:40 +09:00
chanii8 32b778f961 Merge branch 'main' into deploy
Deploy Frontend / deploy (push) Successful in 3m47s
2026-09-08 17:14:51 +09:00
mind-one005 b99f4904b0 sn: featureClickEventPopup에서 침수흔적도 관련 분리 2026-09-08 17:13:36 +09:00
chanii8 17b1c12286 Merge branch 'iipbs/st/dev' 2026-09-08 17:01:32 +09:00
chanii8 c79824e358 [as] feat: 보완요청 파일 첨부 로직 수정 2026-09-08 17:01:02 +09:00
mind-one005 f742feca4b sn: 상단 주석 외 침수흔적도 관련 수정 2026-09-08 15:12:40 +09:00
rsone001 de8971bea6 [ST] fix: 대시보드 통계 처리 현황 panel css 수정 2026-09-08 13:43:26 +09:00
mind-one005 569e003827 sn: 팝업 화면 여백 조정 2026-09-08 11:01:53 +09:00
chanii8 c47c130fc3 [as] feat: 파일보완 요청 기능 구현 2026-09-08 10:29:27 +09:00
mind-one005 2db5dd59af Merge branch 'iipbs/wr/dev' into iipbs/sn/dev 2026-09-07 18:15:04 +09:00
mind-one005 8a8504dca9 sn: 운영정보 버튼 위치 수정 2026-09-07 17:51:36 +09:00
LEEKYUHYUN 7e82c6a802 "디지털하수관로" UI 수정 2026-09-07 17:44:46 +09:00
chanii8 3946fda013 Merge branch 'main' into deploy
Deploy Frontend / deploy (push) Successful in 4m42s
2026-09-07 17:27:45 +09:00
chanii8 db30b45267 Merge branch 'deploy' of https://www.onasys.co.kr:3000/ONAANDALL/frontend into deploy 2026-09-07 17:27:38 +09:00
chanii8 01377b6013 Merge remote-tracking branch 'origin/iipbs/st/dev' 2026-09-07 17:26:39 +09:00
chanii8 b38be38169 [as] feat: AI 자동 진행 단계 대기 상태 텍스트 추가 2026-09-07 17:25:40 +09:00
chanii8 b9ac4a1c18 [as] feat: 재원협의 서비스(fnrsCnsltnService) 수정 2026-09-07 17:05:59 +09:00
mind-one005 bdc6251474 Merge branch 'iipbs/sn/dev' of https://www.onasys.co.kr:3000/ONAANDALL/frontend into iipbs/sn/dev 2026-09-07 17:01:46 +09:00
mind-one005 479cf5c4a0 sn: 다단header 묶음 처리 외 2026-09-07 16:56:35 +09:00
chanii8 dbea497cc5 [as] feat: 웹한글 기안기 데모 페이지 생성 2026-09-07 15:24:06 +09:00
chanii8 94af73a810 [as] docs: 실무협의 로직 개발 가이드 추가 2026-09-07 15:22:21 +09:00
rsone001 a7fd6a8e16 [ST] - fix: 취약점 점검 관련 조치 2026-09-07 14:26:00 +09:00
mind-one001 2b3502161c 시설물 상세창 깨짐 수정 2026-09-04 17:16:32 +09:00
rsone001 8039ab8281 [ST] - refactor: 2-5 맨홀 지표 변경된 테이블에 맞게 수정, 일반검증 항목 입력기간일 시 등록/수정 불가 2026-09-04 16:05:26 +09:00
mind-one001 0544a72011 Merge branch 'iipbs/sn/dev' of https://www.onasys.co.kr:3000/ONAANDALL/frontend into iipbs/sn/dev 2026-09-04 15:27:18 +09:00
mind-one001 34ba09ce1b 준설관리 기능 보완 2026-09-04 15:24:17 +09:00
chanii8 2bfe653ac0 [as] feat: 'dcrag-to' API 구현 2026-09-04 15:18:32 +09:00
mind-one005 aa5a71ae68 sn: 침입수, RDII 제목란 조금 넓게 외 2026-09-04 14:52:11 +09:00
mind-one005 9067e645b3 sn: 정보검색 기본정보 구분란 화면이 줄었을 때, 디자인 외 2026-09-04 14:33:25 +09:00
mind-one005 10d3fc096a sn: 시도 전체일 때, 시군구 목록 비우기 2026-09-04 11:00:38 +09:00
mind-one005 7fd95ba6f9 sn: src/shared/util/util.ts 적용 외 2026-09-04 10:32:36 +09:00
kiminchan b4982e07b8 Merge branch 'iipbs/sn/dev' 2026-09-04 10:22:18 +09:00
jcchoi 6cc2a02df4 Merge branch 'main' into deploy
Deploy Frontend / deploy (push) Successful in 1m9s
2026-09-03 18:31:48 +09:00
jcchoi 351e1091ce Merge remote-tracking branch 'origin/iipbs/st/dev'
Deploy Frontend / deploy (push) Successful in 5m9s
2026-09-03 18:23:16 +09:00
mind-one005 e707637c88 수정 2026-09-03 17:10:11 +09:00
mind-one005 5da89e8ee7 sn: appendApiSearchParams() 함수 적용 2026-09-03 17:09:58 +09:00
rsone001 794691f05e [ST] - fix: 제출결과(검증)화면에 시설명 컬럼 추가 2026-09-03 16:29:40 +09:00
rsone001 e58b84a01b [ST] - fix: input 제출 - 시계열 검증 요청 response & request 수정, 대시보드 구성 수정 2026-09-03 15:27:19 +09:00
rsone001 3d51f003c0 Merge remote-tracking branch 'origin/feature/sein' into iipbs/st/dev 2026-09-03 13:52:34 +09:00
yangsein b5a99e5f59 [feat] 대쉬 보드 일정관리 제거 , 통계 현황상태 추가 2026-09-03 13:44:09 +09:00
rsone001 afca685fd4 [ST] - fix: 2-3 매설연장 관리자일시 수정 가능하도록 적용, SearchFrom 로직 수정 2026-09-03 11:26:23 +09:00
mind-one005 f9ff279895 Merge branch 'iipbs/sn/dev' into iipbs/wr/dev 2026-09-02 18:18:01 +09:00
mind-one005 4cde9b67c1 sn: util.ts 추가 정리 2026-09-02 18:10:50 +09:00
rsone001 261941452a [ST] fix - 2-2 지표 컬럼 설정 및 저장 제출 로직 수정 2026-09-02 16:41:12 +09:00
chanii8 0f107ff29d Merge branch 'main' into deploy
Deploy Frontend / deploy (push) Successful in 6m16s
2026-09-02 16:32:42 +09:00
chanii8 a860650dfb Merge remote-tracking branch 'origin/iipbs/as/dev' 2026-09-02 16:24:39 +09:00
chanii8 63d2dd1f4f [as] feat: 결재선 지정 API 파라미터 추가 2026-09-02 11:54:52 +09:00
kiminchan 8d765c2825 Merge branch 'iipbs/sn/dev' 2026-09-02 09:43:30 +09:00
mind-one005 80d93c1631 Merge branch 'iipbs/sn/dev' of https://www.onasys.co.kr:3000/ONAANDALL/frontend into iipbs/sn/dev 2026-09-01 18:14:16 +09:00
mind-one005 872b3d08c0 sn: 선택 레이어 전체 디자인 수정 2026-09-01 18:10:31 +09:00
chanii8 5e69a9b6f0 Merge branch 'main' into deploy
Deploy Frontend / deploy (push) Successful in 3m44s
2026-09-01 17:20:52 +09:00
chanii8 47cb11d07b Merge remote-tracking branch 'origin/iipbs/st/dev' 2026-09-01 17:19:02 +09:00
rsone001 8576ef83b5 [ST] - refactor: 6-1 중심처리시설 row는 위탁계약기간 직접 수정 못하도록 적용 2026-09-01 16:25:55 +09:00
kiminchan cb191817a8 Merge branch 'iipbs/sn/dev' into iipbs/sn/dev_kic 2026-09-01 16:01:37 +09:00
kiminchan 8198fda45b 공통코드 조회 기반 업무 화면 표시 적용 2026-09-01 15:55:02 +09:00
mind-one005 37374cb754 sn: 선택 레이어 설정 - 침수흔적도 2026-09-01 15:38:25 +09:00
rsone001 e80b8953a0 [ST] - fix: 일반검증 수식 사용자 직접입력 등록시 공백제거 2026-09-01 14:41:49 +09:00
mind-one005 9e36edec7f sn: 침수흔적위선/심선 정보 닫을 때 지도처리 2026-09-01 11:10:27 +09:00
mind-one005 3204bba71b Merge branch 'iipbs/sn/dev' of https://www.onasys.co.kr:3000/ONAANDALL/frontend into iipbs/sn/dev 2026-08-31 23:17:20 +09:00
mind-one005 3cdcf6a6f7 sn: 침수흔적위선 심선/위선 모두 나오도록 2026-08-31 23:16:57 +09:00
chanii8 ec9311c76b Merge branch 'main' into deploy
Deploy Frontend / deploy (push) Successful in 3m36s
2026-08-31 17:23:27 +09:00
chanii8 1d1141b59a Merge branch 'iipbs/as/dev' 2026-08-31 17:22:46 +09:00
chanii8 8fd1d59fe2 [as] feat: 파일 양식 다운로드 API 수정 2026-08-31 17:18:39 +09:00
kiminchan 922861c872 통수위험 행 선택 시 초단기예보격자망 자동 활성화 2026-08-31 13:42:57 +09:00
mind-one005 4a3945f1e4 Merge branch 'iipbs/sn/dev' of https://www.onasys.co.kr:3000/ONAANDALL/frontend into iipbs/sn/dev 2026-08-31 11:36:15 +09:00
mind-one005 a1caa1b860 sn: .env.local 원복 2026-08-31 11:36:05 +09:00
mind-one005 166dea2b86 sn: 침수흔적도 layer 수정 2026-08-31 11:34:19 +09:00
kiminchan 3f7262e213 Merge branch 'iipbs/sn/dev' of https://www.onasys.co.kr:3000/ONAANDALL/frontend into iipbs/sn/dev 2026-08-31 11:06:24 +09:00
kiminchan 231ee10ff8 조사사업 양식 버튼 병합 충돌 오류 수정 2026-08-31 11:05:22 +09:00
mind-one005 5aa9ab4f39 Merge branch 'iipbs/sn/dev' of https://www.onasys.co.kr:3000/ONAANDALL/frontend into iipbs/sn/dev 2026-08-31 11:00:02 +09:00
kiminchan 8c46f7ca06 Merge branch 'iipbs/sn/dev' of https://www.onasys.co.kr:3000/ONAANDALL/frontend into iipbs/sn/dev 2026-08-31 10:46:38 +09:00
kiminchan 23e15daa37 조사사업 등록·수정 양식 다운로드 흐름 보완 2026-08-31 10:35:05 +09:00
mind-one005 dd56ed60ad sn: 용어 변경 - 수위, 깊이 > 위선,심선 2026-08-31 10:23:37 +09:00
mind-one005 18129905d8 sn: 연도버튼 및 침수흔적깊이 2026-08-29 11:21:26 +09:00
chanii8 4c85a7d249 Merge branch 'main' into deploy
Deploy Frontend / deploy (push) Successful in 3m37s
2026-08-28 17:45:20 +09:00
chanii8 f54ce13711 Merge branch 'iipbs/as/dev' 2026-08-28 17:44:06 +09:00
chanii8 fb12eadf65 [as] feat: 필수첨부파일 섹션 수정(파일 양식 컬럼) 2026-08-28 17:43:47 +09:00
chanii8 09d4c2d26e Merge branch 'main' into deploy
Deploy Frontend / deploy (push) Successful in 4m6s
2026-08-28 17:13:45 +09:00
chanii8 bb3179f0e4 Merge remote-tracking branch 'origin/iipbs/st/dev' 2026-08-28 17:12:54 +09:00
rsone001 e8b309460e [ST] input 특광역시 로직 수정, 일반검증 엑셀 다운로드 추가, 모든 number 타입 컬럼에 footer 추가 2026-08-28 17:08:20 +09:00
chanii8 b8dac5dc72 Merge branch 'main' into deploy
Deploy Frontend / deploy (push) Successful in 3m47s
2026-08-28 17:08:08 +09:00
chanii8 ed0736dcde Merge branch 'iipbs/as/dev' 2026-08-28 17:06:34 +09:00
chanii8 edc5bb52af Merge branch 'iipbs/st/dev' 2026-08-28 17:06:20 +09:00
chanii8 37ac927c45 [st] feat: 시계열 검토 이력 > 지자체 진입 시 시도/시군구 자동 선택 2026-08-28 17:05:40 +09:00
mind-one005 d03263a3c6 Merge branch 'iipbs/sn/dev' of https://www.onasys.co.kr:3000/ONAANDALL/frontend into iipbs/sn/dev 2026-08-28 16:48:17 +09:00
mind-one005 be46bcbd17 sn: 침수흔적깊이 정보 추가 2026-08-28 16:08:47 +09:00
chanii8 bf9a34cbe8 [st] feat: 하수도 통계 검증 > 시도/시군구 셀렉트에 '전체' 옵션 추가 2026-08-28 15:55:05 +09:00
mind-one001 201dbf577f 관망도 업로드 수정 2026-08-28 15:45:43 +09:00
chanii8 fc961e2946 [as] feat: 필수첨부파일관리 등록 다이얼로그 > 양식파일 첨부 로직 수정 2026-08-28 15:14:44 +09:00
chanii8 73cafc9786 Merge remote-tracking branch 'origin/main' into deploy
Deploy Frontend / deploy (push) Successful in 3m40s
2026-08-28 14:34:02 +09:00
chanii8 e401455f31 Merge remote-tracking branch 'origin/iipbs/as/dev' 2026-08-28 14:32:59 +09:00
chanii8 254986b48b [as] 필수펌부파일관리 내 양식파일 컬럼 추가 2026-08-28 14:31:54 +09:00
chanii8 4c1615853c [as] docs: 실무협의서 개발가이드 문서 추가 2026-08-28 11:11:32 +09:00
mind-one001 884dd71ca7 Merge branch 'iipbs/sn/dev' of https://www.onasys.co.kr:3000/ONAANDALL/frontend into iipbs/sn/dev
# Conflicts:
#	apps/sn/app/(map-layout)/map/components/popupComponent/featureClickEventPopup.tsx
2026-08-28 10:00:36 +09:00
mind-one001 70efdc9db5 유하방향 표출 수정 2026-08-28 09:52:41 +09:00
mind-one005 36549e7281 Merge branch 'iipbs/sn/dev' of https://www.onasys.co.kr:3000/ONAANDALL/frontend into iipbs/sn/dev 2026-08-27 22:34:15 +09:00
mind-one005 c1ffc33834 sn: 침수예측지도 오버레이 & 침수흔적깊이 2026-08-27 22:33:37 +09:00
chanii8 c276ae0c5e Merge branch 'main' into deploy
Deploy Frontend / deploy (push) Successful in 4m2s
2026-08-27 17:25:06 +09:00
chanii8 f67e065c5e Merge branch 'iipbs/st/dev' of https://www.onasys.co.kr:3000/ONAANDALL/frontend 2026-08-27 17:23:40 +09:00
rsone001 18a11ab5fa [ST] - refactor: 입력화면 전용 시도 조회 api 추가 2026-08-27 17:22:34 +09:00
chanii8 6a7eb1f584 Merge branch 'iipbs/st/dev' of https://www.onasys.co.kr:3000/ONAANDALL/frontend 2026-08-27 17:17:25 +09:00
rsone001 214ff1a435 [ST] - fix: 일반 검증 타입 총계 검증일 시 group by 항목 렌더링 되지 않게 수정 2026-08-27 15:44:45 +09:00
rsone001 d7cc579335 [ST] - refactor: 지난검증결과 불러오기 필드 추가(시설명) 2026-08-27 15:32:12 +09:00
mind-one005 2c3961644c sn: 침수예측지도 오버레이 표시1 2026-08-27 14:10:44 +09:00
rsone001 9b53c1ae08 [ST] - fix: 일반검증 항목 관리, 참조 지표(컬럼) 오류 로직 수정 2026-08-27 13:07:33 +09:00
chanii8 b4ed061a53 Merge branch 'main' into deploy
Deploy Frontend / deploy (push) Successful in 3m40s
2026-08-27 11:36:49 +09:00
chanii8 4840a95097 Merge branch 'iipbs/as/dev' of https://www.onasys.co.kr:3000/ONAANDALL/frontend 2026-08-27 11:31:13 +09:00
chanii8 08a7a4d6bc [as] feat: 재원협의 내 실무협의서 관련 버튼 추가 2026-08-27 11:30:52 +09:00
chanii8 ddaaa8fc92 Merge branch 'main' into deploy
Deploy Frontend / deploy (push) Successful in 3m55s
2026-08-26 17:14:14 +09:00
chanii8 c02ac6f425 Merge branch 'iipbs/as/dev' of https://www.onasys.co.kr:3000/ONAANDALL/frontend 2026-08-26 17:12:36 +09:00
mind-one001 2fe3631a0d Merge branch 'iipbs/sn/dev' of https://www.onasys.co.kr:3000/ONAANDALL/frontend into iipbs/sn/dev 2026-08-26 16:26:19 +09:00
mind-one001 e0cdba00be 그리드 정렬기능 2026-08-26 16:25:29 +09:00
kiminchan 5e206dd210 Merge branch 'iipbs/sn/dev' into iipbs/sn/dev_kic 2026-08-26 14:44:57 +09:00
kiminchan 2008a5a9ee 통수위험 지도 안내 및 과거이력 조회 동작 보완 2026-08-26 14:43:27 +09:00
chanii8 8bda55c653 [as] feat: 행정지원 신청 패널 전체접기/펼침 기능 2026-08-26 14:04:36 +09:00
mind-one005 53aeeccc2a Merge branch 'iipbs/sn/dev' of https://www.onasys.co.kr:3000/ONAANDALL/frontend into iipbs/sn/dev 2026-08-26 13:11:52 +09:00
mind-one005 c7738a6d6c sn: 침수예측현황 지도이동시 도시침수지도 layer점검 2026-08-26 13:11:40 +09:00
kiminchan baf29df950 통수위험 매핑 시설 지도 표출 및 과거이력 행 식별 보완 2026-08-26 13:07:01 +09:00
mind-one005 0a13f34092 Merge branch 'iipbs/sn/dev' of https://www.onasys.co.kr:3000/ONAANDALL/frontend into iipbs/sn/dev 2026-08-26 11:11:30 +09:00
mind-one005 0b45361135 sn: 침수예측현황 팝업에서 지도이동 2026-08-26 11:11:18 +09:00
chanii8 cff7b7da30 [as] feat: 행정지원 패널 전체접기/펼침 기능 2026-08-26 11:04:37 +09:00
kiminchan 83420c76b8 Merge remote-tracking branch 'origin/iipbs/sn/dev' into iipbs/sn/dev_kic 2026-08-26 10:38:51 +09:00
mind-one005 42f83bcd24 sn: 침수예측현황 목록 항목 순서 변경 2026-08-26 10:06:55 +09:00
chanii8 3a253df58a Merge branch 'main' into deploy
Deploy Frontend / deploy (push) Successful in 7m10s
2026-08-25 17:11:23 +09:00
chanii8 197c2583ed Merge remote-tracking branch 'origin/iipbs/st/dev' 2026-08-25 17:06:40 +09:00
chanii8 10f5d42122 Merge branch 'iipbs/as/dev' 2026-08-25 17:06:19 +09:00
chanii8 816b6b2ca8 [as] chore: 재원협의 폼 페이지 내 쿼리 무효화 코드 수정 2026-08-25 16:58:31 +09:00
mind-one001 ccfbe6ae32 팝업 병합 그리드 기능 추가 2026-08-25 16:43:07 +09:00
rsone001 64ed53cf4d [ST] refactor: input - 자동 계산 cell 부동소수점 문제 해결을 위해 decimal.js 라이브러리 추가 및 계산 로직 수정, 6-2 지표 로직 수정 2026-08-25 16:04:31 +09:00
mind-one005 c8e9fc54ed Merge branch 'iipbs/wr/dev' 2026-08-25 15:48:05 +09:00
chanii8 21debe2f77 Merge branch 'main' into deploy
Deploy Frontend / deploy (push) Successful in 3m22s
2026-08-25 15:45:10 +09:00
chanii8 6927f77f86 Merge branch 'iipbs/as/dev' 2026-08-25 15:44:20 +09:00
chanii8 9c86058fe1 [as] chore: 설계자문 삭제 시 목록 쿼리 무효화 2026-08-25 15:43:47 +09:00
mind-one001 8126fb844a Merge branch 'iipbs/sn/dev' of https://www.onasys.co.kr:3000/ONAANDALL/frontend into iipbs/sn/dev 2026-08-25 15:30:01 +09:00
mind-one001 23c9ddf4ce ui 버튼 동작 통일 2026-08-25 15:29:55 +09:00
chanii8 c4291ceda5 [as] refactor: 행정지원 쿼리키 관리 방식 변경 2026-08-25 15:29:27 +09:00
chanii8 8dfd7cc290 [as] feat: 설치인가 저장 시 목록/상세 쿼리 무효화 2026-08-25 15:01:19 +09:00
chanii8 0e4f662dfd Merge branch 'main' into deploy
Deploy Frontend / deploy (push) Successful in 4m19s
2026-08-25 10:34:34 +09:00
chanii8 e5498ef04b Merge branch 'iipbs/as/dev' 2026-08-25 10:33:14 +09:00
chanii8 7baebf2cbc [as] feat: 부동소수점 처리 2026-08-25 10:31:40 +09:00
chanii8 a4c14433cd [as] feat: 행정지원 문서 파일 첨부 로직 수정 2026-08-25 09:42:05 +09:00
mind-one005 63388ccc90 dm: env 수정 2026-08-24 17:45:53 +09:00
rsone001 043fd3d4a8 [ST] - 입력 6-1 공공하수처리시설 컬럼 설정 변경 2026-08-24 17:19:33 +09:00
chanii8 4a797808c1 Merge branch 'main' into deploy
Deploy Frontend / deploy (push) Successful in 4m1s
2026-08-24 17:18:45 +09:00
LGS bda3228d0f 물 재이용 소개 / 물 재이용 현황 [이미지 수정 및 텍스트 수정] 2026-08-24 16:57:15 +09:00
jcchoi eda0b6b813 Merge remote-tracking branch 'origin/iipbs/st/dev' 2026-08-24 16:51:28 +09:00
rsone001 6dd09971f1 [ST] - 컬럼 자동 계산식 오류 수정 2026-08-24 16:39:24 +09:00
LGS 95ca40913f 물 재이용 소개[우리나라의 수자원 현황 및 물이용 여건] 이미지 교체 2026-08-24 16:16:41 +09:00
chanii8 23424b5eee [st] chore: 통계 검증 리포트 초기 조회 파라미터 수정 2026-08-24 14:09:12 +09:00
kiminchan 8bfe1c9ab2 강우관측소 지도 클릭 비활성화 2026-08-24 11:23:40 +09:00
chanii8 4bd5276fc5 [as] rename: 스펙 문서 폴더 이동 2026-08-24 09:32:46 +09:00
chanii8 92ed3233af [as] design: 대시보드 스타일 수정 2026-08-24 09:21:30 +09:00
chanii8 3a81b822f2 Merge branch 'main' into deploy
Deploy Frontend / deploy (push) Successful in 3m54s
2026-08-21 17:29:09 +09:00
chanii8 2c1e4d18fc Merge branch 'iipbs/st/dev' 2026-08-21 17:28:11 +09:00
chanii8 3f190dfff6 Merge branch 'iipbs/st/dev' of https://www.onasys.co.kr:3000/ONAANDALL/frontend into iipbs/st/dev 2026-08-21 17:27:37 +09:00
chanii8 6cc02da7a4 [st] feat: 통계 검증 리포트 목록 조회 API 수정 2026-08-21 17:27:30 +09:00
kiminchan 0dc981819f 강우 레이어 프록시와 관측소 아이콘 추가 2026-08-21 17:22:25 +09:00
rsone001 c87ccf8788 [ST] - fix: 입력 저장&제출시 빈값 null처리 2026-08-21 14:56:34 +09:00
chanii8 dcaa2d5ef3 Merge branch 'iipbs/as/dev' 2026-08-21 11:42:18 +09:00
chanii8 e0715ce177 [as] feat: 증감액, 증감률 서버 데이터 매핑(사업규모, 총사업비, 재원분담) 2026-08-21 11:38:43 +09:00
chanii8 3333f1c8e6 [as] style: 행정지원 문서 진행 상태 테이블 스타일 수정 2026-08-21 09:59:14 +09:00
mind-one001 4b7ada9362 Merge remote-tracking branch 'origin/iipbs/sn/dev' into iipbs/sn/dev
# Conflicts:
#	apps/sn/app/(map-layout)/map/components/waterRisk/WaterRiskPopupPage.tsx
#	apps/sn/src/features/windowPopup/model/popupDefinitions.ts
2026-08-20 17:16:33 +09:00
mind-one001 71c5dfb8dd fix(sn): 조사관리 팝업 레이아웃과 등록 흐름 개선 2026-08-20 17:14:07 +09:00
mind-one001 7e3911dbd6 feat(sn): 침수예측 및 통수위험 팝업 UI 보완 2026-08-20 17:13:54 +09:00
kiminchan 839d31b9ca 통수위험 결과조회 공통 그리드 및 지도 표출 보완 2026-08-20 17:09:33 +09:00
rsone001 8e757ab9db Merge branch 'iipbs/st/dev' of https://www.onasys.co.kr:3000/ONAANDALL/frontend into iipbs/st/dev 2026-08-20 16:31:13 +09:00
rsone001 de7e66afb4 [ST] - fix: 11-4 데이터 체크 수정 2026-08-20 16:31:00 +09:00
chanii8 63050b0efa [as] design: 대시보드 전국 행정지원 지도 레이아웃 구현 2026-08-20 15:13:18 +09:00
mind-one001 386fdade59 Merge remote-tracking branch 'origin/iipbs/sn/dev' into iipbs/sn/dev 2026-08-20 15:10:36 +09:00
mind-one001 0cbbc3b934 feat(sn): CS 기준 UI 통일 및 지도 팝업 표준화 2026-08-20 14:57:20 +09:00
chanii8 f5a7efb324 Merge branch 'main' into deploy
Deploy Frontend / deploy (push) Successful in 4m2s
2026-08-20 13:12:39 +09:00
chanii8 c4592a026a Merge branch 'iipbs/st/dev' 2026-08-20 13:08:24 +09:00
chanii8 c981b83284 Merge branch 'iipbs/st/dev' of https://www.onasys.co.kr:3000/ONAANDALL/frontend into iipbs/st/dev 2026-08-20 13:07:50 +09:00
chanii8 927bb7cb3a [st] chore: eslint 해결 2026-08-20 11:48:18 +09:00
chanii8 725976b5c0 [st] feat: 시도/시군구 조회 쿼리 변경 2026-08-20 11:47:50 +09:00
rsone001 cdbe6a855f [ST] - fix: 검토 하수관로 컬럼 수정 및 엑셀 내보내기 셀 스타일 수정 2026-08-19 12:31:37 +09:00
chanii8 a1c96e9e98 Merge branch 'iipbs/st/dev' of https://www.onasys.co.kr:3000/ONAANDALL/frontend into iipbs/st/dev 2026-08-19 11:58:06 +09:00
chanii8 1488805242 [as] feat: 통계 검증 리포트 새로고침 버튼 추가 2026-08-19 11:57:58 +09:00
chanii8 cf681125a6 [as] docs: 문서 수정 2026-08-19 11:40:13 +09:00
chanii8 abc3ca184d Merge branch 'main' into deploy
Deploy Frontend / deploy (push) Successful in 4m49s
2026-08-18 18:03:01 +09:00
chanii8 7dcef46829 Merge branch 'iipbs/st/dev' of https://www.onasys.co.kr:3000/ONAANDALL/frontend 2026-08-18 18:02:05 +09:00
chanii8 36a7654973 Merge branch 'iipbs/as/dev' 2026-08-18 18:01:37 +09:00
rsone001 5b12f81b8f [ST] - fix: 통계 집계표 조회 기본값 수정, 엑셀 다운로드 스타일 적용, 요약표 마우스 툴팁 추가 / 입력단 오류 수정 및 검토단 컬럼 설정 수정 2026-08-18 17:44:22 +09:00
chanii8 7c88b609f7 [as] feat: 대시보드 공지사항 섹션 구현 2026-08-18 17:35:54 +09:00
kiminchan f5051225ea 통수위험 결과조회 및 지도 시각화 프로토타입 구현 2026-08-18 17:28:48 +09:00
chanii8 5af4f0f27b [as] feat: 대시보드 페이지 구현 2026-08-18 16:40:21 +09:00
mind-one005 f7218fc98a sn: 침수예측현황-단위 엑셀다운로드 수정 2026-08-18 13:31:22 +09:00
chanii8 267c022d58 Merge branch 'main' into deploy
Deploy Frontend / deploy (push) Successful in 3m36s
2026-08-13 17:52:39 +09:00
chanii8 cf115b769f Merge branch 'iipbs/as/dev' 2026-08-13 17:50:18 +09:00
chanii8 774144846d [as] chore: 하수도기본계획 게이트 코드 수정 2026-08-13 17:49:57 +09:00
chanii8 0fc2844928 Merge branch 'main' into deploy
Deploy Frontend / deploy (push) Successful in 3m56s
2026-08-13 17:22:37 +09:00
chanii8 3b2f6c386d Merge branch 'iipbs/st/dev' of https://www.onasys.co.kr:3000/ONAANDALL/frontend 2026-08-13 17:21:09 +09:00
chanii8 987e5fcbfd [as] chore: 알림이력 notiUrl 리졸버 추가 2026-08-13 17:20:30 +09:00
chanii8 335872eaec [as] feat: 행정지원 문서 상세페이지 게이트 구현 2026-08-13 17:11:13 +09:00
rsone001 df24e7c2a8 [ST] - fix: 일반 검증 수식 안내 문구 수정 2026-08-13 16:20:54 +09:00
rsone001 3b5fee047b [ST] - fix: qa 조치, 일반 검증 개발 수정 2026-08-13 15:30:00 +09:00
chanii8 9bcc8b95e7 [as] feat: 알림이력 페이지 구현 2026-08-13 11:51:21 +09:00
mind-one001 c9e3ff0d91 Merge branch 'iipbs/sn/dev' of https://www.onasys.co.kr:3000/ONAANDALL/frontend into iipbs/sn/dev 2026-08-12 11:14:05 +09:00
mind-one001 474ad1ab26 GIS관리 기능 보완 2026-08-12 11:13:49 +09:00
jcchoi 9ea3474d43 Merge branch 'main' of https://www.onasys.co.kr:3000/ONAANDALL/frontend 2026-08-11 18:00:02 +09:00
jcchoi a26bd5ea5b 이미지 정리 2026-08-11 17:59:52 +09:00
chanii8 7f1fe42ace Merge branch 'main' of https://www.onasys.co.kr:3000/ONAANDALL/frontend into deploy
Deploy Frontend / deploy (push) Successful in 3m36s
2026-08-11 17:46:50 +09:00
chanii8 4ee0eab653 Merge branch 'iipbs/as/dev' of https://www.onasys.co.kr:3000/ONAANDALL/frontend 2026-08-11 17:45:56 +09:00
chanii8 fe92ba3c27 [as] feat: 내행정지원 페이지 2026-08-11 17:45:28 +09:00
mind-one005 099e000f88 sn: 분석도구 - 침수예측현황 2026-08-11 15:09:30 +09:00
mind-one005 7fa4538667 sn: 도시침수예방사업 다운로드 header 수정 2026-08-11 14:34:47 +09:00
mind-one005 91e11a7857 Merge branch 'iipbs/sn/dev' of https://www.onasys.co.kr:3000/ONAANDALL/frontend into iipbs/sn/dev 2026-08-11 14:33:20 +09:00
chanii8 e8870d3bcb [as] chore: 불필요한 상수 제거 2026-08-11 11:43:18 +09:00
mind-one001 d582293e5f 보수이력 목록 조회 항목 추가 2026-08-11 11:28:52 +09:00
jcchoi 9152782a65 Merge branch 'main' of https://www.onasys.co.kr:3000/ONAANDALL/frontend 2026-08-11 11:14:20 +09:00
jcchoi 0dc378285c 전화번호 수정 2026-08-11 11:14:08 +09:00
mind-one001 d8c5344451 관망도 분석도구 위치 조정 2026-08-11 11:11:09 +09:00
mind-one001 d23a16905d Merge branch 'iipbs/sn/dev' of https://www.onasys.co.kr:3000/ONAANDALL/frontend into iipbs/sn/dev 2026-08-11 10:32:45 +09:00
mind-one001 2649ce286b 보수이력 기능 개발 2026-08-11 10:32:35 +09:00
mind-one005 2f9e97b65b sn: 도시침수예방사업01 2026-08-10 22:04:36 +09:00
chanii8 c83a13d680 Merge branch 'main' into deploy
Deploy Frontend / deploy (push) Successful in 4m7s
2026-08-10 18:06:03 +09:00
chanii8 403946c50a Merge branch 'iipbs/st/dev' 2026-08-10 18:01:40 +09:00
chanii8 bdc7c64c61 Merge branch 'iipbs/as/dev' 2026-08-10 18:01:33 +09:00
rsone001 181730bcde [ST] - fix: 입력: 새로고침 시 열려있는 모든 텝의 공통 api가 실행되는 현상 수정, 하수도보급률 저장&제출 request 수정(외국인총인구 제거, 총면적 추가), 검증 툴팁 max-width 추가, 지난 검증 결과 및 제출 결과 데이터 마우스 툴팁 추가 2026-08-10 17:58:05 +09:00
chanii8 d79e0e585a [as] feat: 행정지원 업무별 상세페이지 내 진행상태 섹션 추가 2026-08-10 17:57:39 +09:00
chanii8 678af2f06e [st] chore: 승인 정보 입력 폼 수정 2026-08-10 15:48:19 +09:00
chanii8 dbda77a75b [as] feat: 결재현황 ui 수정 2026-08-10 15:27:53 +09:00
chanii8 0459c0b231 [as] feat: 행정지원 업무별 목록 내 진행상황 ui 수정 2026-08-10 10:26:27 +09:00
mind-one005 e1940043e9 sn: 노후 하수관로 정비사업 등록/수정 입력란 수정 2026-08-07 22:49:44 +09:00
mind-one005 7f1c804a0c dm: LoginModal 사업자등록번호 입력 수정 2026-08-07 20:59:05 +09:00
mind-one005 d07bb6074d sn: 노후하수관로정비사업 시군구 필수 아님 2026-08-07 18:22:08 +09:00
rsone001 82d67bb4c6 [ST] - fix: 검증 항목 명칭 변경 2026-08-07 17:22:08 +09:00
chanii8 3d7dcb6d0e Merge branch 'main' into deploy
Deploy Frontend / deploy (push) Successful in 4m17s
2026-08-07 17:03:11 +09:00
chanii8 ed54fe9646 Merge branch 'iipbs/st/dev' of https://www.onasys.co.kr:3000/ONAANDALL/frontend 2026-08-07 17:02:06 +09:00
rsone001 85ef1805e5 [ST] - 공단 오류 및 개선 요청사항 처리 2026-08-07 16:24:39 +09:00
mind-one005 4109691eea Merge branch 'iipbs/sn/dev_ljp' into iipbs/sn/dev 2026-08-07 15:58:28 +09:00
mind-one005 4eaac5dbf1 sn: 노후하수관로정비사업 - 팝업 2026-08-07 15:57:14 +09:00
chanii8 07a625e03b [as] rename: SectionCollapsible 컴포넌트 shared 레이어로 이동 2026-08-07 15:34:26 +09:00
mind-one001 b99fe8daf1 Merge branch 'iipbs/sn/dev' of https://www.onasys.co.kr:3000/ONAANDALL/frontend into iipbs/sn/dev 2026-08-07 15:28:49 +09:00
mind-one001 3f4e3581dd 준설관리 개발완료 2026-08-07 15:28:33 +09:00
mind-one005 f00627270f sn: 최종확정예산사업 popup 2026-08-06 18:40:19 +09:00
chanii8 a46f24d6d7 Merge branch 'main' into deploy
Deploy Frontend / deploy (push) Successful in 3m44s
2026-08-06 17:12:47 +09:00
chanii8 ee19f9ca59 Merge branch 'iipbs/cm/dev' 2026-08-06 17:11:52 +09:00
chanii8 b9e9814664 Merge branch 'iipbs/st/dev' 2026-08-06 17:11:50 +09:00
chanii8 8303fa3860 Merge branch 'iipbs/as/dev' 2026-08-06 17:11:38 +09:00
chanii8 6d9042ac0f [cm] typo: 404 페이지 문구 수정 2026-08-06 17:06:58 +09:00
chanii8 26f64988ef [st] typo: 404 페이지 문구 수정 2026-08-06 17:06:00 +09:00
chanii8 12a0a37d24 [as] typo: 404 페이지 문구 수정 2026-08-06 17:04:56 +09:00
chanii8 2e4f2428f0 Merge branch 'main' into deploy
Deploy Frontend / deploy (push) Successful in 4m41s
2026-08-06 16:50:33 +09:00
chanii8 c8c11b19de Merge branch 'iipbs/as/dev' 2026-08-06 16:49:45 +09:00
chanii8 45a500817f [as] chore: 검토인력관리 인원배치 api 수정 2026-08-06 16:39:36 +09:00
chanii8 706cebfeae Merge branch 'main' into deploy 2026-08-06 16:22:09 +09:00
chanii8 8a352a8e69 Merge remote-tracking branch 'origin/iipbs/as/dev' 2026-08-06 16:18:00 +09:00
chanii8 999fd610af [as] feat: 결재선 검증 로직 수정 2026-08-06 16:17:44 +09:00
chanii8 dd6aff5ebf Merge remote-tracking branch 'origin/iipbs/as/dev' 2026-08-06 15:52:02 +09:00
chanii8 bc3c841b89 Merge remote-tracking branch 'origin/iipbs/st/dev' 2026-08-06 15:51:58 +09:00
chanii8 99ea453d23 Merge remote-tracking branch 'origin/iipbs/cm/dev' 2026-08-06 15:51:46 +09:00
chanii8 71389a104c Merge remote-tracking branch 'origin/iipbs/cs/dev' 2026-08-06 15:51:34 +09:00
chanii8 6e2ebe9025 [as] feat: 결재선관리 > 결재구분 변경 시 결재자 초기화 2026-08-06 15:39:33 +09:00
chanii8 29e39f98af Merge branch 'iipbs/st/dev' of https://www.onasys.co.kr:3000/ONAANDALL/frontend into iipbs/st/dev 2026-08-06 15:15:09 +09:00
chanii8 5192f3e3c0 [st] feat: 404 페이지 구현 2026-08-06 15:15:04 +09:00
chanii8 95c8416754 [cm] feat: 404 페이지 구현 2026-08-06 15:14:46 +09:00
chanii8 b102c4feba [as] feat: 404 페이지 구현 2026-08-06 15:14:26 +09:00
chanii8 daff1610e3 [cs] feat: 404 페이지 구현 2026-08-06 15:12:48 +09:00
chanii8 ee7f5e3a07 Merge branch 'main' into deploy 2026-08-06 13:42:33 +09:00
chanii8 054dcc4eee [common/components] chore: 모듈 참조 경로 수정 2026-08-06 13:40:02 +09:00
chanii8 1f1f72451b [common/components] feat: 페이지 타이틀 내 도움말 다이얼로그 구현 2026-08-06 13:37:31 +09:00
mind-one005 1858739bb9 sn: 노후하수관로정비사업 조회조건 유지 2026-08-06 10:46:47 +09:00
kiminchan 3d320d0e19 맨홀 선택 시 기존 심볼이 유지되도록 보완 2026-08-06 09:42:41 +09:00
kiminchan 9d2c0afb98 조사 지도 조건과 노후관로 범례 보완 2026-08-06 09:14:56 +09:00
chanii8 3d0160f21f Merge branch 'main' into deploy 2026-08-05 17:23:37 +09:00
chanii8 ae51b8273f Merge branch 'iipbs/as/dev' 2026-08-05 17:22:50 +09:00
chanii8 defe2a8e9b [as] fix: 타입 에러 2026-08-05 17:22:28 +09:00
chanii8 28aa932676 Merge branch 'iipbs/as/dev' 2026-08-05 17:20:23 +09:00
chanii8 4aa2d0a62c [as] chore: 행정지원 메뉴 수정 2026-08-05 17:18:38 +09:00
mind-one001 29f2a9169e Merge branch 'iipbs/sn/dev' of https://www.onasys.co.kr:3000/ONAANDALL/frontend into iipbs/sn/dev
# Conflicts:
#	apps/sn/src/features/windowPopup/model/popupDefinitions.ts
#	apps/sn/src/features/windowPopup/registry.tsx
2026-08-05 16:24:52 +09:00
mind-one001 493acc9ebd 통수능/준설관리 2026-08-05 16:05:07 +09:00
chanii8 1d8d9c7b3d [as] feat: 행정지원 메뉴(설치인가, 재원협의, 설계자문, 하수도기본계획) 수정 2026-08-05 15:58:48 +09:00
mind-one005 d3bdc58994 sn: 순번 삭제 외 2026-08-05 15:49:55 +09:00
kiminchan 20efccb4d9 Merge branch 'iipbs/sn/dev_kic' into iipbs/sn/dev 2026-08-05 13:58:16 +09:00
kiminchan f58daf3bac 침수지도 목록보기 및 WMS 표출 구현 2026-08-05 13:55:22 +09:00
rsone001 83de317308 Merge branch 'iipbs/st/dev' of https://www.onasys.co.kr:3000/ONAANDALL/frontend into iipbs/st/dev 2026-08-05 10:09:58 +09:00
rsone001 84b1fd07ae [ST] - management service code refresh 로직 추가 2026-08-05 10:08:26 +09:00
mind-one005 b42810d29a sn: 노후하수관로정비사업1 2026-08-04 20:30:26 +09:00
chanii8 e105f52fea [as] feat: 기본계획 상세 페이지 구현 2026-08-04 17:22:21 +09:00
mind-one005 2e6a75141b sn: 노후 하수관로 정비사업 2026-08-03 18:16:42 +09:00
chanii8 0aa0126caf Merge branch 'main' into deploy
Deploy Frontend / deploy (push) Successful in 5m43s
2026-08-03 17:47:39 +09:00
chanii8 f637f096f9 chore: x-device-id 제거 코드 수정 (domain 옵션 추가) 2026-08-03 17:45:10 +09:00
chanii8 5ecdd37187 Merge branch 'main' into deploy
Deploy Frontend / deploy (push) Successful in 3m52s
2026-08-03 17:28:33 +09:00
chanii8 7f497f60af Merge branch 'iipbs/st/dev' 2026-08-03 17:24:35 +09:00
chanii8 7a019b063b Merge branch 'iipbs/cs/dev' 2026-08-03 17:24:30 +09:00
chanii8 e5e20a789a Merge branch 'iipbs/as/dev' 2026-08-03 17:24:24 +09:00
chanii8 8883f5ba55 Merge branch 'iipbs/cm/dev' 2026-08-03 17:24:18 +09:00
chanii8 d64a694e20 docs: authService 리팩토링 문서 업데이트 2026-08-03 17:24:02 +09:00
chanii8 a88f8ab33e [st] feat: 로그아웃 라우트 핸들러 적용 2026-08-03 15:56:48 +09:00
chanii8 5e3d263750 [cs] feat: 로그아웃 라우트 핸들러 적용 2026-08-03 15:40:48 +09:00
chanii8 70136aa65d [as] feat: 로그아웃 라우트 핸들러 적용 2026-08-03 14:57:47 +09:00
chanii8 b514bdc472 [cm] feat: 로그아웃 라우트 핸들러 적용 2026-08-03 14:53:42 +09:00
chanii8 20cc2ca248 Merge branch 'main' into deploy
Deploy Frontend / deploy (push) Successful in 3m48s
2026-08-03 11:45:43 +09:00
chanii8 5031f0c582 Merge branch 'iipbs/as/dev' of https://www.onasys.co.kr:3000/ONAANDALL/frontend 2026-08-03 11:36:57 +09:00
chanii8 25287dc3d9 [as] chore: 기본계획 스키마 수정 2026-08-03 11:36:45 +09:00
chanii8 5527ad8c41 Merge branch 'iipbs/st/dev' 2026-08-03 11:20:13 +09:00
chanii8 75525ec7a8 Merge branch 'iipbs/cs/dev' 2026-08-03 11:20:04 +09:00
chanii8 21e967473b Merge branch 'iipbs/as/dev' 2026-08-03 11:19:50 +09:00
chanii8 c67b5844b6 [st] chore: metadata 수정 2026-08-03 11:14:48 +09:00
chanii8 ced62ec0c4 [cs] chore: metadata 수정 2026-08-03 11:12:06 +09:00
chanii8 84bbaa09da [as] chore: metadata 수정 2026-08-03 11:08:42 +09:00
chanii8 dfa35542c5 [cm] chore: metadata 수정 2026-08-03 11:06:43 +09:00
chanii8 a6348050fd [as] refactor: 로그인 페이지 auth 그룹으로 분리 2026-08-03 11:03:03 +09:00
chanii8 4d700c3566 Merge branch 'main' of https://www.onasys.co.kr:3000/ONAANDALL/frontend into iipbs/as/dev 2026-08-03 10:55:33 +09:00
chanii8 f2d7e947d7 [cm] refactor: 로그인 페이지 auth 그룹으로 분리 2026-08-03 10:52:01 +09:00
chanii8 3c65e6f8f5 chore: css 모듈 처리 2026-08-03 10:43:17 +09:00
kiminchan ce60e5f5fb Merge branch 'iipbs/sn/dev' into iipbs/sn/dev_kic 2026-08-03 10:12:47 +09:00
kiminchan c9d85a8ce4 조사결과 관로·맨홀 지도 레이어와 보고서 조회 연동 2026-08-03 10:11:48 +09:00
chanii8 5cfd7d65ec Merge branch 'main' into deploy
Deploy Frontend / deploy (push) Successful in 7m45s
2026-07-31 18:00:11 +09:00
chanii8 1efe2dbe89 remove: ClientIpGuard 제거 2026-07-31 17:56:21 +09:00
chanii8 b2260e0b61 [as] chore: 기본계획 신청 페이지 수정 2026-07-31 17:32:25 +09:00
chanii8 3c2ca24dea [as] feat: 하수도기본계획 > 이전기본계획조회 다이얼로그 구현 2026-07-31 16:58:46 +09:00
chanii8 2acbeb83d0 [as] feat: 행정지원 업무 신청 시 시도/구군 선택 로직 추가 2026-07-31 13:50:07 +09:00
chanii8 e0956e05a6 [as] chore: 설치인가 조회 조건 수정 2026-07-31 09:55:05 +09:00
chanii8 e67492853c [as] WIP: 기본계획조회 다이얼로그 구현 2026-07-31 09:30:09 +09:00
mind-one001 0f8b6cd6d0 Merge branch 'iipbs/sn/dev' of https://www.onasys.co.kr:3000/ONAANDALL/frontend into iipbs/sn/dev
# Conflicts:
#	apps/sn/app/(map-layout)/map/components/gisManagement/GisManagementPopupPage.tsx
#	apps/sn/app/(map-layout)/map/components/waterRisk/WaterRiskPopupPage.tsx
2026-07-30 17:26:41 +09:00
mind-one001 b11658e1d6 준설관리 초안 2026-07-30 17:18:59 +09:00
kiminchan bcf5d3caec 조사관리 팝업 UI와 관로 상세 등급 표시 보정 2026-07-30 16:53:30 +09:00
kiminchan 474676af17 조사 상세현황 배수방식·관종 명칭 표시 2026-07-30 13:17:16 +09:00
chanii8 3b8307b674 Merge branch 'main' into deploy 2026-07-30 11:37:16 +09:00
chanii8 36e56dcaef Merge branch 'iipbs/st/dev' 2026-07-30 11:28:08 +09:00
chanii8 e42e28d062 [st] chore: 통계검증리포트 > 승인정보입력 다이얼로그 수정 2026-07-30 11:27:36 +09:00
chanii8 0786053022 Merge remote-tracking branch 'origin/iipbs/st/dev' 2026-07-30 11:24:13 +09:00
chanii8 e56938f7ff [as] WIP: 하수도기본계획 신청 페이지(이전기본계획조회) 2026-07-30 11:23:44 +09:00
rsone001 791ec1ae2d [ST] - code-refresh 로직 추가 2026-07-30 11:01:02 +09:00
kiminchan 3cc0e9de14 조사 상세조회 및 집계 엑셀 다운로드 연동 2026-07-30 10:53:32 +09:00
chanii8 b8b0b24b0e [as] feat: dc service 추가 2026-07-29 15:39:37 +09:00
kiminchan ff7be74437 Merge branch 'iipbs/sn/dev' into iipbs/sn/dev_kic 2026-07-29 13:31:01 +09:00
kiminchan f52f22e80f 조사결과 검토·저장 및 사업보고서 목록 표시 개선 2026-07-29 13:22:59 +09:00
mind-one005 86e00d48dc sn: 지도 침수흔적도 우측 정보에 강우분석 추가 2026-07-29 11:43:51 +09:00
chanii8 afbebb9dfc [as] feat: 하수도기본계획 목록 페이지 구현 2026-07-29 10:24:38 +09:00
mind-one005 bf61f6f76a sn: 침수발생이력 팝업 수정 2026-07-28 17:51:47 +09:00
kiminchan 62c41297c4 조사사업 수정 및 조사양식 다운로드 연동 2026-07-28 13:28:15 +09:00
rsone001 4e4942313a [ST] - fix: 통계일정관리 불필요 컬럼 제거 2026-07-28 11:34:46 +09:00
mind-one005 09b5cc3798 sn: 시도별 노후관로현황 2026-07-27 17:51:33 +09:00
chanii8 fe76864a05 [as] feat: 하수도기본계획 등록 폼 레이아웃 구현 2026-07-27 17:29:23 +09:00
kiminchan 155a727a77 처리분구 인라인 편집 및 저장 후 목록 동기화 2026-07-27 14:18:02 +09:00
kiminchan a52dacf500 조사사업 등록의 사업차수 입력과 행정구역 배치 보완 2026-07-27 11:29:48 +09:00
mind-one005 e8e38310ee Merge branch 'iipbs/sn/dev' of https://www.onasys.co.kr:3000/ONAANDALL/frontend into iipbs/sn/dev 2026-07-27 10:32:25 +09:00
mind-one005 2652e2cfe0 sn: components.css 통합 2026-07-27 10:29:45 +09:00
kiminchan 5a76ae8a88 Merge branch 'iipbs/sn/dev' into iipbs/sn/dev_kic 2026-07-27 10:20:27 +09:00
kiminchan 7d9b97aac9 조사상세 본단위구간 모드 및 결함별 엑셀 다운로드 구현 2026-07-27 10:15:06 +09:00
mind-one005 69c3183e35 sn: 침수흔적도 지도표출 2026-07-24 18:13:54 +09:00
chanii8 2f800c960d Merge branch 'main' into deploy
Deploy Frontend / deploy (push) Successful in 10m24s
2026-07-24 16:59:38 +09:00
chanii8 e6fcbfbde4 chore: tsserver 용량 관리 2026-07-24 16:25:55 +09:00
chanii8 ed4d1b73cb refactor: X-Device-Id 공통 로직으로 변경 2026-07-24 15:53:23 +09:00
mind-one005 5e6477cddd Merge branch 'iipbs/sn/dev' of https://www.onasys.co.kr:3000/ONAANDALL/frontend into iipbs/sn/dev 2026-07-24 15:23:41 +09:00
mind-one005 c13cab394a sn: 침수발생이력 변수명 수정 2026-07-24 15:23:35 +09:00
kiminchan 73f1940cb0 Merge branch 'iipbs/sn/dev' into iipbs/sn/dev_kic 2026-07-24 15:12:08 +09:00
mind-one005 8a35d232ef sn: 침수발생이력 팝업 api 적용 2026-07-24 14:22:41 +09:00
kiminchan 728981cfe6 조사 결함 분류별 상세보기 및 등록 팝업 개선 2026-07-24 14:08:25 +09:00
kiminchan 11cb2b9044 조사사업 관로·맨홀 상세보기 팝업 구현 2026-07-24 13:05:26 +09:00
chanii8 2728b4058b Merge branch 'main' into deploy
Deploy Frontend / deploy (push) Successful in 4m8s
2026-07-24 10:57:06 +09:00
chanii8 e3dac52d7e Merge branch 'iipbs/st/dev' 2026-07-24 10:56:09 +09:00
chanii8 d1d8a1eff3 [st] feat: 통계 검증 리포트 시도/시군구 셀렉트 로직 수정 2026-07-24 10:47:57 +09:00
chanii8 cae9f94388 [as] docs: 설계자문 구현 문서 생성 2026-07-24 09:57:40 +09:00
jcchoi 4502d55ce1 Merge remote-tracking branch 'origin/iipbs/st/dev' 2026-07-23 20:49:31 +09:00
chanii8 cad87496ac [as] feat: 기본계획 엔티티 생성 2026-07-23 17:41:16 +09:00
kiminchan c1d6cd7b8e 조사사업 보고서 다운로드 및 상세현황 그리드 보정 2026-07-23 17:26:08 +09:00
kiminchan 477426c384 조사사업 등록·결과 업로드 및 관로·맨홀 종합집계 화면 구현 2026-07-23 17:06:01 +09:00
rsone001 3d3b978070 [st] - fix: 검토이력조회 request 누락 수정 2026-07-23 16:36:29 +09:00
rsone001 117082c862 [st] - fix: 입력 메뉴 데이터 항목 추가 시 해당사항없음 false로 갱신되지 않던 오류 수정 2026-07-23 14:26:11 +09:00
chanii8 b842905572 Merge branch 'main' into deploy
Deploy Frontend / deploy (push) Successful in 4m28s
2026-07-23 11:44:35 +09:00
chanii8 bfa03aabc0 Merge branch 'iipbs/st/dev' of https://www.onasys.co.kr:3000/ONAANDALL/frontend 2026-07-23 11:43:30 +09:00
chanii8 f535cd1010 [st] feat: 대시보드 일정안내 empty 구현 및 일정관리 월 이동 구현 2026-07-23 11:33:21 +09:00
chanii8 b388edb23c [as] feat: 업무신청에서 재이용수 선택 로직 구현 2026-07-22 17:03:46 +09:00
chanii8 85fa9a8658 Merge branch 'main' of https://www.onasys.co.kr:3000/ONAANDALL/frontend into deploy
Deploy Frontend / deploy (push) Successful in 10m37s
2026-07-22 14:42:42 +09:00
chanii8 2f6d4ebec1 chore: 코드 정리 2026-07-22 14:13:38 +09:00
rsone001 1c3cc5b61b Merge branch 'iipbs/st/dev' of https://www.onasys.co.kr:3000/ONAANDALL/frontend into iipbs/st/dev 2026-07-22 13:39:57 +09:00
rsone001 db7584cb01 [st] - fix: 집계06.공공하수처리시설 조회 조건 추가, 입력06.공공하수처리시설 매핑 계약기간 DatePicker 수정, 입력자 예외 제출 valuedation 수정 2026-07-22 13:38:58 +09:00
kiminchan ec60a05b01 처리분구관리 화면 구현 2026-07-22 13:15:06 +09:00
chanii8 5ae56481c2 Merge remote-tracking branch 'origin/main' into deploy
Deploy Frontend / deploy (push) Successful in 7m23s
2026-07-22 11:44:50 +09:00
chanii8 b842408f41 Merge remote-tracking branch 'origin/iipbs/as/dev' 2026-07-22 11:36:12 +09:00
chanii8 6e33a62ed9 [as] feat: 설계자문 페이지 구현 2026-07-22 11:34:38 +09:00
mind-one005 36231a5eca Merge branch 'iipbs/wr/dev' 2026-07-22 09:23:43 +09:00
mind-one005 90f0e4691b Merge branch 'iipbs/wr/dev' into iipbs/sn/dev 2026-07-21 21:03:19 +09:00
mind-one005 b41a317788 wr: fo: sn: 지도화면 session confirm 2026-07-21 17:59:15 +09:00
chanii8 84fb81b245 Merge branch 'main' of https://www.onasys.co.kr:3000/ONAANDALL/frontend into iipbs/as/dev 2026-07-21 15:56:50 +09:00
chanii8 e18f759fab [as] feat: 설계자문 엔티티 생성 2026-07-21 14:32:14 +09:00
chanii8 ce9c7b17a2 Merge remote-tracking branch 'origin/iipbs/st/dev' 2026-07-21 13:54:32 +09:00
chanii8 c2d6f7fe37 Merge remote-tracking branch 'origin/iipbs/cs/dev' 2026-07-21 13:54:28 +09:00
chanii8 9b18aa9cef Merge remote-tracking branch 'origin/iipbs/cm/dev' 2026-07-21 13:54:22 +09:00
chanii8 5eccb58aa9 Merge remote-tracking branch 'origin/iipbs/as/dev' 2026-07-21 13:54:16 +09:00
chanii8 acce1364fa Merge branch 'iipbs/st/dev' of https://www.onasys.co.kr:3000/ONAANDALL/frontend into iipbs/st/dev 2026-07-21 13:53:30 +09:00
chanii8 625c5f5fe2 [st] chore: 토큰 자동 리프레시 코드 주석 처리 2026-07-21 13:53:24 +09:00
chanii8 dffa9d74a0 [cs] chore: 토큰 자동 리프레시 코드 주석 처리 2026-07-21 13:52:59 +09:00
chanii8 668a8ef844 [cm] chore: 토큰 자동 리프레시 코드 주석 처리 2026-07-21 13:52:26 +09:00
chanii8 df4d708981 [as] chore: 토큰 자동 리프레시 코드 주석 처리 2026-07-21 13:51:10 +09:00
chanii8 c48a46c7ab feat: 토큰 시간 만료 시 authService.logout 함수 실행 2026-07-21 13:50:19 +09:00
chanii8 8079d7d6af Merge branch 'main' into deploy
Deploy Frontend / deploy (push) Successful in 7m20s
2026-07-21 11:51:55 +09:00
chanii8 da844fb3a7 Merge branch 'main' of https://www.onasys.co.kr:3000/ONAANDALL/frontend 2026-07-21 11:50:36 +09:00
chanii8 3e1f89d90f [common/components] chore: 로그인 연장 콘솔 추가(임시) 2026-07-21 11:47:39 +09:00
mind-one005 559e4ee352 Merge remote-tracking branch 'origin/main' into iipbs/wr/dev 2026-07-21 11:38:33 +09:00
jcchoi a1d43dc65c 차수 단어 제외 2026-07-21 11:11:55 +09:00
chanii8 d26cd90b02 [common/components] feat: nofooter에 authService props 추가 2026-07-21 09:20:37 +09:00
chanii8 7c8eef1715 Merge branch 'main' into deploy
Deploy Frontend / deploy (push) Successful in 6m51s
2026-07-20 18:44:05 +09:00
chanii8 45f72f7333 [common/components] chore: auth-header 참조 경로 수정 2026-07-20 18:42:15 +09:00
chanii8 196d31a084 [common/components] feat: raw fetch 헤더에 토큰 주입 2026-07-20 18:35:14 +09:00
chanii8 aaf898fb4c Merge branch 'main' of https://www.onasys.co.kr:3000/ONAANDALL/frontend into iipbs/cm/dev 2026-07-20 17:47:19 +09:00
chanii8 f10b3179c2 Merge branch 'main' into deploy
Deploy Frontend / deploy (push) Successful in 10m25s
2026-07-20 17:11:46 +09:00
rsone001 533e89c919 [st] - fix: 이상치선별보고서 css 수정 2026-07-20 17:11:10 +09:00
chanii8 2f0448a98e [common/components] refactor: banner, menu, site를 기본 fetch 로 수정 2026-07-20 17:08:36 +09:00
chanii8 aab8cf9622 [cm] feat: 인증 서비스에 "X-Device-Id" 적용 2026-07-20 15:37:17 +09:00
kiminchan 5e0693e057 Merge branch 'iipbs/sn/dev_kic' into iipbs/sn/dev 2026-07-20 15:33:27 +09:00
kiminchan 1708555133 시설물 레이어 체크 시 스크롤 위치 유지 2026-07-20 15:29:23 +09:00
mind-one005 c38d95fd60 Merge branch 'iipbs/sn/dev' of https://www.onasys.co.kr:3000/ONAANDALL/frontend into iipbs/sn/dev 2026-07-20 15:03:52 +09:00
kiminchan 667f7b2094 Merge remote-tracking branch 'origin/iipbs/sn/dev' into iipbs/sn/dev_kic 2026-07-20 14:57:39 +09:00
kiminchan d17909df41 그리드 공통 정렬 기능 확대 적용 2026-07-20 14:56:23 +09:00
mind-one005 88113fca1c wr: fo: sn: NEXT_PUBLIC_COOKIE_COMAIN 개발 추가 2026-07-20 14:52:48 +09:00
chanii8 2e0bb5aa84 Merge branch 'main' of https://www.onasys.co.kr:3000/ONAANDALL/frontend into deploy
Deploy Frontend / deploy (push) Successful in 10m10s
2026-07-20 13:52:10 +09:00
chanii8 81fc947c9d chore: as, st 앱 standalone 활성 2026-07-20 13:49:22 +09:00
chanii8 c684440e65 Merge branch 'iipbs/st/dev' of https://www.onasys.co.kr:3000/ONAANDALL/frontend 2026-07-20 13:45:21 +09:00
chanii8 4c6222acf1 Merge branch 'iipbs/cs/dev' of https://www.onasys.co.kr:3000/ONAANDALL/frontend 2026-07-20 13:45:12 +09:00
chanii8 2131ecc315 Merge branch 'iipbs/cm/dev' of https://www.onasys.co.kr:3000/ONAANDALL/frontend 2026-07-20 13:45:07 +09:00
chanii8 f53c72f31f Merge branch 'main' of https://www.onasys.co.kr:3000/ONAANDALL/frontend into iipbs/as/dev 2026-07-20 13:44:16 +09:00
chanii8 1d3910c157 [st] chore: route handler 쿠키 도메인 설정 구문 수정 2026-07-20 13:43:46 +09:00
chanii8 3b2f5c2d5d [cm] chore: route handler 쿠키 도메인 설정 구문 수정 2026-07-20 13:42:55 +09:00
chanii8 903cdaad45 [as] chore: route handler 쿠키 도메인 설정 구문 수정 2026-07-20 13:41:15 +09:00
chanii8 386fc61a3f [cs] chore: route handler 쿠키 도메인 설정 구문 수정 2026-07-20 13:39:43 +09:00
dongsilove 6e354690c5 sn: NEXT_PUBLIC 제거 2026-07-19 23:52:05 +09:00
dongsilove adae670318 Merge branch 'iipbs/wr/dev' into iipbs/sn/dev 2026-07-19 23:03:36 +09:00
dongsilove bdbefbf600 :wr :fo :dm NEXT_PUBLIC 삭제 2026-07-19 20:40:41 +09:00
dongsilove 939089a79c :wr :sn :fo NEXT_PUBLIC_COOKIE_DOMAIN 추가 2026-07-19 18:14:34 +09:00
dongsilove f8354344ff Merge branch 'iipbs/wr/dev' 2026-07-18 14:02:49 +09:00
dongsilove e596c1f0a6 wr: sn: fo: X-Device-Id 추가 2026-07-18 14:01:33 +09:00
chanii8 7ae8d42731 Merge branch 'main' into deploy
Deploy Frontend / deploy (push) Successful in 9m2s
2026-07-16 18:39:59 +09:00
chanii8 7f53badcf3 chore: auth service 수정 2026-07-16 18:33:35 +09:00
chanii8 1dcf01bb0e chore: 의존성 업데이트 2026-07-16 18:26:58 +09:00
chanii8 eec25ab1c4 Merge branch 'iipbs/st/dev' 2026-07-16 18:26:24 +09:00
chanii8 f90f093385 Merge branch 'iipbs/cs/dev' 2026-07-16 18:26:13 +09:00
chanii8 befe56fd44 Merge branch 'iipbs/cm/dev' 2026-07-16 18:26:02 +09:00
chanii8 47d91424c5 Merge branch 'iipbs/as/dev' 2026-07-16 18:25:49 +09:00
chanii8 ddd72f71d2 [st] feat: 로그인 시 X-Device-Id 헤더 추가 2026-07-16 18:24:39 +09:00
chanii8 1a1ff2ec30 [cs] feat: 로그인 시 X-Device-Id 헤더 추가 2026-07-16 18:22:58 +09:00
chanii8 10d89279bc [cm] refactor: auth service 수정 2026-07-16 18:21:37 +09:00
chanii8 a6f9ba7526 [as] feat: 재원협의 보완요청 로직 작업 2026-07-16 17:54:57 +09:00
mind-one005 19dfe45b0b wr: sn: fo: BaseLayout 호출 param 추가 2026-07-16 16:58:26 +09:00
chanii8 f584e21480 [as] feat: 설치인가 보완요청 및 완료 기능 구현 2026-07-16 15:17:43 +09:00
dongsilove 6acacbfcf4 sn: 공통 모듈 기반 로그인 변경 2026-07-15 22:04:26 +09:00
mind-one005 52a79eca60 fo: 공통 모듈 기반 로그인 변경 2026-07-15 18:22:39 +09:00
chanii8 70faadb27e [as] feat: 보완요청 기능 구현 2026-07-15 17:52:43 +09:00
mind-one005 2eb1809f36 wr: 공통 모듈기반 로그인 변경 2026-07-15 17:22:51 +09:00
kiminchan d9febf8010 하수관로 편집 세션 UI 및 토글 동작 개선 2026-07-15 15:54:15 +09:00
kiminchan d4c5787360 하수관로 편집 세션 배치 및 팝업 전환 개선 2026-07-15 15:39:38 +09:00
mind-one005 c8c461e8e8 Merge remote-tracking branch 'origin/main' into iipbs/wr/dev 2026-07-15 14:54:42 +09:00
chanii8 9e2da003f1 [as] feat: 전결 로직 수정 및 결재현황 섹션 구현 2026-07-15 13:36:20 +09:00
rsone001 ae41483bb7 [ST] - fix: 집계 컬럼 설정 fixedColumns 수정 2026-07-15 11:39:09 +09:00
kiminchan d062b8a7d4 지반침하 연계 관로 탭의 부모 종속 제거 처리 2026-07-15 11:34:06 +09:00
rsone001 18825dd0c3 [ST] - DataGrid setRow 로직 수정 및 간단한 수정사항 처리 2026-07-15 11:29:49 +09:00
mind-one005 6b2ea58b66 wr: Password 초기화 2026-07-15 10:26:56 +09:00
kiminchan fdfb37d4d0 지반침하 지도 UX 및 목록 표시 개선 2026-07-14 16:57:51 +09:00
mind-one005 450de39f8c dm: 로그인 변경 2026-07-14 16:48:08 +09:00
chanii8 c87ad8ea1b [as] refactor: 결재선 선택 다이얼로그 통합 2026-07-14 15:03:45 +09:00
mind-one005 b336651503 dm: 등록시 비번 해쉬처리 2026-07-14 14:50:54 +09:00
chanii8 7a1949fc6f [as] feat: 결재선 수정 사항 반영 2026-07-14 12:28:22 +09:00
rsone001 35a63d7c5c [st] - fix: 지난년도 데이터 가져오기 button confirm 추가 2026-07-14 11:54:29 +09:00
kiminchan 031f5e2ed8 하수관망도 시도 단위 처리시설 조회 지원 2026-07-14 10:18:46 +09:00
kiminchan 189b4b7599 지반침하 연계 탭 유형 구분·관로 단일화·부모 복귀 기능 및 후속 정책 반영 2026-07-14 09:55:06 +09:00
dongsilove 6ada32cb9f Merge branch 'iipbs/wr/dev' 2026-07-13 18:24:54 +09:00
chanii8 5491c524c5 [as] feat: 멀티 디바이스 로그인 구현 2026-07-13 18:08:26 +09:00
chanii8 8d29f25101 [as] feat: 체크리스트 전체선택 기능 추가 2026-07-13 16:43:01 +09:00
kiminchan 28d4b2d831 RDII 분석 진행률 표시 및 결과 팝업 가독성 개선 2026-07-13 15:20:04 +09:00
chanii8 399645a80a [as] feat: 설계자 전화번호 검증 코드 추가 2026-07-13 14:43:55 +09:00
chanii8 9d13809d01 [as] feat: 체크리스트 항목 관리에 '정렬 순서' 컬럼 추가 2026-07-13 14:28:10 +09:00
chanii8 e8c8db7383 [as] chore: 불필요한 코드 제거 2026-07-13 14:05:25 +09:00
chanii8 b41814ed0c [as] chore: 체크리스트 정렬 코드 제거 (서버에 위임) 2026-07-13 12:01:17 +09:00
chanii8 d71f2043de [as] feat: 필수 첨부 파일 업로드 가능한 확장자 제한 2026-07-13 11:38:38 +09:00
kiminchan 87ba3e8fa2 침입수 분석 전역 프로그래스바 표시와 상태 polling 연동 마감 2026-07-13 11:26:15 +09:00
chanii8 a9e65af77b Merge branch 'main' into deploy
Deploy Frontend / deploy (push) Successful in 3m25s
2026-07-13 11:14:34 +09:00
chanii8 eabbbf456f Merge branch 'iipbs/cm/dev' 2026-07-13 11:10:46 +09:00
chanii8 ebfba7ac8c [cm] chore: 프로젝트 설정 수정 2026-07-13 11:07:32 +09:00
mind-one005 fe4a4a420e wr: EMFILE 오류수정 2026-07-13 10:51:16 +09:00
rsone001 14ae432833 [st] - fix: 입력단 superAdmin 필드 존재 시에만 추가되도록 수정 2026-07-10 12:27:52 +09:00
kiminchan 009a38f3ca RDII 분석 완료 상태 polling 및 전역 완료 alert 적용 2026-07-09 18:51:01 +09:00
chanii8 d21ecc975f Merge branch 'main' into deploy
Deploy Frontend / deploy (push) Successful in 2m14s
2026-07-09 17:54:09 +09:00
chanii8 cfc73e4094 Merge branch 'iipbs/as/dev' 2026-07-09 17:53:18 +09:00
chanii8 748be6faa5 [as] chore: 파비콘 파일 추가 2026-07-09 17:51:20 +09:00
chanii8 452509281a Merge branch 'main' into deploy
Deploy Frontend / deploy (push) Successful in 5m8s
2026-07-09 17:40:25 +09:00
chanii8 330e2e5c69 Merge remote-tracking branch 'origin/iipbs/as/dev' 2026-07-09 17:39:35 +09:00
chanii8 343a3f81bf [as] feat: 설치인가 전자결재 로직 수정 2026-07-09 17:39:03 +09:00
mind-one005 13c7d5a0c5 wr: 중수도시설 등록 페이징 수정 2026-07-09 17:38:57 +09:00
kiminchan a9c38b356a 침입수 즉시 제출 alert 복구 및 전역 완료 alert 감시 추가 2026-07-09 17:30:21 +09:00
kiminchan 4181257afd 하수관망도 검색바 한글 깨짐 복구 2026-07-09 16:23:21 +09:00
chanii8 0141ed56c2 [as] feat: 재원협의 전자결재 로직 수정 2026-07-09 16:17:51 +09:00
kiminchan 35dc205810 Merge branch 'iipbs/sn/dev_kic' into iipbs/sn/dev 2026-07-09 16:12:21 +09:00
mind-one005 d10a17eaf6 sn: 테마변경 1차 2026-07-09 15:57:30 +09:00
mind-one005 a623c53fa5 wr: css ㅍ 2026-07-09 15:39:48 +09:00
kiminchan 3db8babee7 침입수·RDII 분석 대상지역 기본값을 양평으로 설정 2026-07-09 13:03:21 +09:00
kiminchan ca7ac992e2 침입수 분석결과 실측하수량 관로 우선 줌인 및 지역 선이동 제거 2026-07-09 11:37:26 +09:00
rsone001 a956c9894e [st] - 공지사항 메뉴 새창으로 열도록 return 수정 2026-07-09 11:35:50 +09:00
kiminchan 6c84ba6aeb 침입수·RDII 분석 화면 결과보기 버튼 및 지도결과 popup 연계 2026-07-09 10:45:53 +09:00
mind-one005 e99b7d8162 Merge branch 'iipbs/wr/dev' 2026-07-09 10:01:38 +09:00
mind-one005 09bb613929 wr: 오류수정 2026-07-09 10:00:20 +09:00
mind-one005 761b0dd502 wr: 수요처팝업 비번 초기화 2026-07-09 09:56:41 +09:00
mind-one005 8c72cb3b72 wr: 하수재이용실적 등록 2026-07-08 20:56:51 +09:00
chanii8 35b6f4ae54 [as] feat: 결재선 저장 api 수정 2026-07-08 19:22:40 +09:00
chanii8 2e3602eee6 Merge branch 'main' into deploy
Deploy Frontend / deploy (push) Successful in 11m12s
2026-07-08 18:55:17 +09:00
chanii8 cf5ade639a Merge remote-tracking branch 'origin/iipbs/cm/dev' 2026-07-08 18:52:53 +09:00
chanii8 0dfd5efa97 [cm] feat: auth 서비스 수정 및 jwt 기반 로그인 만료 구현 2026-07-08 18:52:30 +09:00
chanii8 e6cbb9dfd8 Merge branch 'iipbs/st/dev' 2026-07-08 18:21:36 +09:00
chanii8 52c7215cd8 Merge branch 'iipbs/cs/dev' 2026-07-08 18:21:28 +09:00
chanii8 fe88732a80 Merge branch 'iipbs/as/dev' 2026-07-08 18:21:22 +09:00
chanii8 aa5f85a3c1 [st] remove: 로그아웃 라우트 핸들러 제거 2026-07-08 18:21:00 +09:00
chanii8 843519c3b5 [as] remove: 로그아웃 라우터 핸들러 제거 2026-07-08 18:17:03 +09:00
chanii8 c74917d1d9 [cs] remove: 로그아웃 라우터 핸들러 제거 2026-07-08 18:16:24 +09:00
chanii8 9dca199d78 Merge branch 'iipbs/st/dev' of https://www.onasys.co.kr:3000/ONAANDALL/frontend into iipbs/st/dev 2026-07-08 18:05:51 +09:00
chanii8 4fa7542aca [st] feat: 통계 검증 리포트 반려 처리 로직 수정 2026-07-08 18:05:35 +09:00
chanii8 1cd24b5dd5 [st] chore: stClient 참조 경로 수정 2026-07-08 18:05:11 +09:00
rsone001 34f1bf5e6a Merge branch 'iipbs/st/dev' of https://www.onasys.co.kr:3000/ONAANDALL/frontend into iipbs/st/dev 2026-07-08 17:45:01 +09:00
rsone001 675e5f58d1 [st] - fix log detail 로직 수정 2026-07-08 17:39:35 +09:00
mind-one005 127fb41145 dm: 수요신청현황 api 수정, 수정시 비번 처리,무한루프처리 2026-07-08 17:05:57 +09:00
chanii8 8abf32bb53 Merge branch 'iipbs/as/dev' 2026-07-08 16:04:15 +09:00
chanii8 b567e5df13 [as] remove: instl-sncn-old 페이지 제거 2026-07-08 16:03:16 +09:00
chanii8 40acdafed2 Merge remote-tracking branch 'origin/iipbs/cs/dev' 2026-07-08 16:00:49 +09:00
chanii8 7f6b05e4e5 Merge remote-tracking branch 'origin/iipbs/as/dev' 2026-07-08 16:00:38 +09:00
chanii8 0d4a698c11 Merge branch 'iipbs/st/dev' of https://www.onasys.co.kr:3000/ONAANDALL/frontend into iipbs/st/dev 2026-07-08 15:57:24 +09:00
chanii8 5bacfb04b5 [st] chore: auth 서비스 수정 2026-07-08 15:57:17 +09:00
chanii8 1e8514a0bc Merge branch 'main' of https://www.onasys.co.kr:3000/ONAANDALL/frontend into iipbs/st/dev 2026-07-08 15:56:41 +09:00
chanii8 b6714dd8a4 [as] chore: auth 서비스 수정 2026-07-08 15:55:54 +09:00
chanii8 e05c2a03e0 Merge branch 'main' of https://www.onasys.co.kr:3000/ONAANDALL/frontend into iipbs/as/dev 2026-07-08 15:53:10 +09:00
chanii8 914df505ae [cs] chore: auth 서비스 수정 2026-07-08 15:52:14 +09:00
chanii8 7e59ae6b66 Merge branch 'main' of https://www.onasys.co.kr:3000/ONAANDALL/frontend 2026-07-08 15:46:08 +09:00
chanii8 eb84a23d7e [common] feat: useSessionExtendConfirm 생성 2026-07-08 15:43:42 +09:00
mind-one005 1076120516 dm: 전화번호 포맷 & 비번 변경 2026-07-08 10:32:33 +09:00
dongsilove 54ce26adbc Merge remote-tracking branch 'origin/iipbs/wr/dev' 2026-07-07 20:30:15 +09:00
chanii8 28d54b615b [cs] chore: auth service 수정 2026-07-07 18:19:43 +09:00
chanii8 424fa576fb [cs] feat: auth service 수정 (BaseLayout DI 패턴) 2026-07-07 18:04:08 +09:00
chanii8 7f8e5fe9f9 [as] feat: auth service 수정 (BaseLayout DI 패턴) 2026-07-07 18:02:18 +09:00
chanii8 47f1bd012c Merge branch 'main' of https://www.onasys.co.kr:3000/ONAANDALL/frontend into iipbs/as/dev 2026-07-07 17:51:28 +09:00
chanii8 0c2e762cee [cm] chore: next-env.d.ts 파일 깃에서 제거 2026-07-07 17:49:43 +09:00
chanii8 68124e6abb [common/components] chore: BaseLayout 수정 2026-07-07 17:37:26 +09:00
chanii8 5587e6b6a3 [common] feat: 공통 auth 및 components 수정(authService DI 패턴) 2026-07-07 17:34:27 +09:00
rsone001 ac1e98fbaa Merge branch 'iipbs/st/dev' of https://www.onasys.co.kr:3000/ONAANDALL/frontend into iipbs/st/dev 2026-07-07 17:02:47 +09:00
rsone001 d25f9f3a01 [st] - fix: 2-3 컬럼 로직 수정, 입력단 excel 업로드 시 행정동코드 매핑 검사 2026-07-07 17:01:36 +09:00
mind-one005 fb638752eb wr: 검색어 있는 경우 paging과 건축물용도 2026-07-07 16:42:51 +09:00
chanii8 8c3dd62f6d Merge branch 'iipbs/st/dev' of https://www.onasys.co.kr:3000/ONAANDALL/frontend into iipbs/st/dev 2026-07-07 15:14:27 +09:00
chanii8 e79635b81a [st] feat: 통계 검증 리포트 페이지 수정 2026-07-07 15:14:18 +09:00
rsone001 e3a9851de6 [st] - fix: 하수관로 관종별 현황, 입력 가능 연도만 매설연장 컬럼 수정가능, 관리자 계정일 시 엑셀 업로드로 모든 cell 수정 가능 2026-07-07 12:17:44 +09:00
mind-one005 34811d4571 Merge branch 'main' into iipbs/sn/dev 2026-07-07 11:03:47 +09:00
chanii8 3167a9a6e3 WIP: 전자결재 로직 수정 2026-07-07 09:18:50 +09:00
mind-one005 a29d1f0cc2 wr: 수요처 pk변경 1 2026-07-06 17:37:28 +09:00
jcchoi 7dfd535841 Merge branch 'main' into deploy
Deploy Frontend / deploy (push) Successful in 2m54s
2026-07-06 16:54:57 +09:00
jcchoi e76cddd45b Merge remote-tracking branch 'origin/iipbs/st/dev' 2026-07-06 16:53:09 +09:00
jcchoi 39d928b5b1 Merge remote-tracking branch 'origin/iipbs/st/dev' into deploy 2026-07-06 16:51:29 +09:00
rsone001 3c214f4725 [st] - fix: chat.js registerd error 2026-07-06 14:54:32 +09:00
rsone001 80861938f3 [st] - fix: 입력단 텝 형식 그리드 제출 및 저장 후 재조회 로직 수정 2026-07-06 14:11:25 +09:00
rsone001 401f2dba13 [ST] - SearchFrom 수정 2026-07-06 11:29:56 +09:00
jcchoi 525695072a Merge branch 'main' into deploy
Deploy Frontend / deploy (push) Successful in 2m56s
2026-07-05 11:07:27 +09:00
jcchoi c4d7c516ef Merge remote-tracking branch 'origin/iipbs/st/dev' 2026-07-05 10:58:48 +09:00
chanii8 2f11b1185b [as] feat: 재원협의 신청 및 수정 페이지 작업 2026-07-03 17:23:18 +09:00
rsone001 42274a71b7 Merge remote-tracking branch 'origin/feature/sein' into iipbs/st/dev 2026-07-03 16:19:48 +09:00
rsone001 f1fcfa9ee4 [st] - 그리드 style 적용 로직 수정, 로그 조회 일정 선택 로직 수정(최대 1년 제한) 2026-07-03 16:19:27 +09:00
yangsein afcfbbbf61 feat: 집계표 비고 제거 , 행정동 인구관리 갱신 버튼추가 2026-07-03 16:15:34 +09:00
mind-one005 defba2962d wr: 하수재이용시설 등록 수요처 추가 2026-07-03 15:17:10 +09:00
rsone001 4c7666169c Merge remote-tracking branch 'origin/feature/sein' into iipbs/st/dev 2026-07-03 13:09:41 +09:00
yangsein 5580b4301f [feat]집계 11분뇨찌꺼기 tab2 소화조 컬럼 매핑 수정 2026-07-03 13:02:40 +09:00
jcchoi 972a4ce789 Merge branch 'main' into deploy
Deploy Frontend / deploy (push) Successful in 5m30s
2026-07-02 18:34:53 +09:00
jcchoi 421ff8cb40 Merge remote-tracking branch 'origin/iipbs/st/dev' 2026-07-02 18:31:43 +09:00
jcchoi 879aadc068 Merge remote-tracking branch 'origin/iipbs/st/dev' into deploy
Deploy Frontend / deploy (push) Successful in 3m2s
2026-07-02 18:29:55 +09:00
mind-one005 96b95e0eb9 Merge branch 'iipbs/wr/dev' 2026-07-02 18:08:03 +09:00
rsone001 cea2d39df8 [st] - 일정등록, 입력단 지난검증결과 알림 뱃지, 로그 상세조회, 검토단 cell style 적용 2026-07-02 17:46:13 +09:00
kiminchan f4eae0d33e 지반침하 좌표 실패 이슈 및 잔여 케이스 문서 반영 2026-07-02 15:38:45 +09:00
chanii8 716a20cc22 [as] feat: 코드관리 페이지 통합 2026-07-02 15:35:56 +09:00
mind-one005 873a74492a wr: refresh token 적용 2026-07-02 15:33:06 +09:00
kiminchan 516d93d6fa RDII 분석결과 팝업 지도연계 및 결과전용 팝업 적용 2026-07-02 11:38:40 +09:00
mind-one005 958a8ffe2c Merge branch 'main' of https://www.onasys.co.kr:3000/ONAANDALL/frontend 2026-07-02 09:10:49 +09:00
mind-one005 0286e2a92e Merge branch 'iipbs/wr/dev' 2026-07-02 09:10:14 +09:00
mind-one005 01e339cc61 wr: 하수재이용시설 조회 api 정리2 2026-07-01 18:18:36 +09:00
chanii8 0e7c9b4a96 [as] feat: 재원분담 API 추가 2026-07-01 17:52:57 +09:00
kiminchan d5814043d9 침입수 분석결과 지도연계 및 I/I 분석 메뉴 정리 2026-07-01 17:35:58 +09:00
chanii8 e81210ec04 [as] feat: 재원협의 신청 페이지 작업 및 설치인가 신청 폼 섹션 공통 컴포넌트화 2026-07-01 17:19:48 +09:00
mind-one005 8d17623d3a wr: 하수재이용시설 조회 api 정리1 2026-07-01 15:18:42 +09:00
jcchoi ba9d7c8172 Merge remote-tracking branch 'origin/iipbs/st/dev'
Deploy Frontend / deploy (push) Successful in 3m9s
2026-07-01 10:13:30 +09:00
mind-one005 06f5a3cde0 wr: 하수재이용실적 등록1 2026-06-30 18:14:19 +09:00
rsone001 25417dcda1 [st] - any type 수정, 검토 그리드 cell style 수정 2026-06-30 17:59:11 +09:00
jcchoi 9a3b332130 Merge remote-tracking branch 'origin/iipbs/st/dev'
Deploy Frontend / deploy (push) Successful in 3m57s
2026-06-30 16:02:29 +09:00
rsone001 1236a24b61 [st] - fix: 입력단 날짜 데이터 값 없을 시 null 처리 2026-06-30 15:56:47 +09:00
rsone001 f50de743e3 [st] - feat 통계인구관리 기능 추가 2026-06-30 14:56:52 +09:00
rsone001 0c2568aad0 Merge remote-tracking branch 'origin/feature/sein' into iipbs/st/dev 2026-06-30 14:40:51 +09:00
yangsein b15cbeb568 feat: 행정동인구 탭 추가 2026-06-30 14:36:25 +09:00
rsone001 afdc06638f [st] - 검토단 작업 완료 및 입력6-1, 10-1 운영데이터업데이트 기능 추가, 텝 영역 우클릭 후 텝 닫기 기능 추가 2026-06-30 14:23:08 +09:00
chanii8 6fb610d9aa [as] feat: fnrs-cnsltn-mng 서비스 구현 2026-06-30 13:51:22 +09:00
kiminchan c14d536133 정보검색 기본계획보고서 탭 조회 UX 개선 2026-06-30 13:09:07 +09:00
chanii8 3008ae2eeb Merge branch 'iipbs/as/dev'
Deploy Frontend / deploy (push) Successful in 3m41s
2026-06-30 12:27:39 +09:00
chanii8 3b4d9df0e8 [as] feat: 설치인가 수정 페이지 수정 2026-06-30 12:27:13 +09:00
mind-one005 48d4a5e135 Merge branch 'main' of https://www.onasys.co.kr:3000/ONAANDALL/frontend 2026-06-30 09:05:23 +09:00
mind-one005 ff33565513 wr: 지도 overlay 버튼 수정 2026-06-29 18:18:48 +09:00
chanii8 b40bae1b50 Merge branch 'iipbs/as/dev'
Deploy Frontend / deploy (push) Successful in 5m53s
2026-06-29 18:00:17 +09:00
chanii8 0533d229e6 [as] feat: 설치인가 검토의견 작성 폼 추가 2026-06-29 17:59:18 +09:00
mind-one005 bbb755bf56 wr: 오류 수정 2026-06-29 17:46:17 +09:00
kiminchan 31caee87db GIS 편집 임시 관로 스냅 지원 및 세션 취소/뒤로가기 분리 2026-06-29 17:45:31 +09:00
kiminchan 87cda451f3 지반침하 설정 패널 연도선택 UI 및 우측 탭 스타일 정리 2026-06-29 17:08:31 +09:00
mind-one005 e2b8f901a3 Merge branch 'main' of https://www.onasys.co.kr:3000/ONAANDALL/frontend 2026-06-29 16:54:03 +09:00
mind-one005 951e2c1f89 wr: 지도 팝업 제목 style 통일 2026-06-29 16:53:43 +09:00
chanii8 20fd291cc3 [as] feat: 설치인가 신청 시 업무구분 선택 팝업 추가 2026-06-29 16:08:21 +09:00
kiminchan ee3ddce41d 지반침하 상세 관로 용도 OGC011 매핑 및 표 너비 조정 2026-06-29 14:51:46 +09:00
chanii8 fb160e712b [as] chore: 설치인가 페이지 수정 2026-06-29 14:46:40 +09:00
mind-one005 9a6cc1779f wr: 지도 목록보기 다운로드할 데이터 ... 오류 수정 2026-06-29 14:39:52 +09:00
chanii8 b459d0fbcb Merge branch 'iipbs/as/dev'
Deploy Frontend / deploy (push) Successful in 8m47s
2026-06-29 13:50:05 +09:00
chanii8 9816a9c46a [as] feat: 첨부파일 다운로드 기능 추가 2026-06-29 13:49:33 +09:00
kiminchan f4b8f9d65d 우측 상세 패널 탭 지도 선택 동기화 2026-06-29 13:31:31 +09:00
mind-one005 08e8d7343c Merge commit '5505791b6e3ef04480731b123512e90e9e035c43' 2026-06-29 12:56:12 +09:00
mind-one005 5505791b6e wr: 하수재이용등록 화면 속도개선-오류수정 2026-06-29 11:48:37 +09:00
mind-one005 1862477641 wr: 하수재이용등록 화면 속도개선 2026-06-26 17:34:54 +09:00
kiminchan ff9daa2bfd Merge remote-tracking branch 'origin/iipbs/wr/dev' into iipbs/sn/dev_kic 2026-06-26 17:30:06 +09:00
kiminchan 23b13e3fdc 하수처리시설 레이어 기준 검색 동기화 2026-06-26 17:29:16 +09:00
mind-one005 f93f2674df sn: 지도 component 수정 반영 2026-06-26 17:23:03 +09:00
chanii8 1d7d34b7c1 Merge branch 'iipbs/as/dev'
Deploy Frontend / deploy (push) Successful in 2m16s
2026-06-26 16:12:39 +09:00
chanii8 9837a7af71 [as] refactor: 버튼 로직 중복 코드 제거 2026-06-26 16:12:18 +09:00
chanii8 d3ef4094c6 [as] feat: 설치인가 문서 삭제 버튼 기능 2026-06-26 15:57:22 +09:00
chanii8 bf86291016 [as] feat: 설치인가 버튼 로직 작업 2026-06-26 15:48:07 +09:00
kiminchan 37ace8b34c Merge remote-tracking branch 'origin/iipbs/wr/dev' into iipbs/sn/dev_kic 2026-06-26 15:46:35 +09:00
kiminchan e170790e4c 지반침하 레이어 설정 UI 및 포인트 표시 개선 2026-06-26 15:40:21 +09:00
kiminchan 0fe1aa983c 지반침하 반경 내 관로정보 요약 표시 개선 2026-06-26 10:35:40 +09:00
kiminchan 180eb1f59d 관로 이동 도구 on/off 유지 및 입력정보 조회 오류 방어 2026-06-26 10:15:24 +09:00
kiminchan 9ca61dd60d 지반침하 반경 내 관로정보 경과년도 집계 표시 2026-06-26 09:36:00 +09:00
chanii8 52a0635810 Merge remote-tracking branch 'origin/iipbs/st/dev'
Deploy Frontend / deploy (push) Successful in 2m53s
2026-06-26 09:15:38 +09:00
chanii8 2337b4cce2 Merge branch 'iipbs/as/dev' 2026-06-26 09:14:22 +09:00
chanii8 6f51b90178 [as] WIP: 설치인가 버튼 로직
[as] WIP: 설치인가 버튼 로직

[as] WIP: 설치인가 버튼 로직
2026-06-26 09:11:32 +09:00
rsone001 162e18142c [st] - 입력단 작업 완료 2026-06-25 18:02:31 +09:00
kiminchan d4797617a6 정보검색 팝업 초기 코드 로딩 및 최초 조회 보완 2026-06-25 10:40:28 +09:00
kiminchan be67395f13 정보검색 팝업 조회조건 공통코드 초기화 2026-06-25 10:22:40 +09:00
chanii8 20e17861e1 Merge branch 'iipbs/as/dev'
Deploy Frontend / deploy (push) Successful in 4m4s
2026-06-24 17:59:35 +09:00
chanii8 deb7375d6b [as] WIP: 설치인가 버튼 로직 2026-06-24 17:59:01 +09:00
kiminchan 2767260505 지반침하 레이어 아이콘 PNG 재인코딩 2026-06-24 16:13:52 +09:00
kiminchan bba4a8eeba 시설물 레이어 패널 토글 복구 2026-06-24 15:39:06 +09:00
kiminchan c9786adc77 Merge remote-tracking branch 'origin/main' into iipbs/sn/dev_kic 2026-06-24 14:53:40 +09:00
jcchoi 407051287d Merge branch 'main' of https://www.onasys.co.kr:3000/ONAANDALL/frontend 2026-06-24 09:59:53 +09:00
jcchoi 3d178dd6bc 사용자 검색 수정 2026-06-24 09:59:44 +09:00
chanii8 8ddedc60ac Merge branch 'iipbs/as/dev'
Deploy Frontend / deploy (push) Successful in 1m56s
2026-06-24 09:09:33 +09:00
chanii8 ddb8031e55 [as] WIP: 설치인가 페이지 2026-06-24 09:07:47 +09:00
rsone001 46cf24c193 [st] - 입력단 기능 작업중, 집계 요약표 다운로드 2026-06-23 10:20:20 +09:00
yangsein 82ab1376cc feat:행정동 탭코드 추가 2026-06-18 15:38:10 +09:00
kiminchan 2c27a67cc3 위성지도 기능 개선 및 침수 레이어 범례 보완 2026-06-18 11:03:39 +09:00
yangsein 5ea68435ed Merge remote-tracking branch 'origin/iipbs/st/dev' into feature/sein 2026-06-16 16:44:28 +09:00
yangsein 58ca85ce90 feat: 통계인구관리 내국인/외국인/행정동갱신 탭 구현" 2026-06-16 16:43:06 +09:00
kiminchan 2ea207a63a 통수위험 팝업 디자인 보완 2026-06-15 17:34:24 +09:00
kiminchan e47c00f0b6 침수흔적도 목록/지도 상세 팝업 mock 구현 및 md 업데이트 2026-06-15 16:28:37 +09:00
yangsein 7483d351c3 Merge remote-tracking branch 'origin/iipbs/st/dev' into feature/sein 2026-06-15 14:53:01 +09:00
kiminchan 83a3810301 시설물 레이어 ui 변경 작업 2026-06-12 13:26:35 +09:00
kiminchan c6309bf14d 지반침하정보 총 결과 건수 표시 2026-06-11 11:36:13 +09:00
kiminchan c10a2ae1c8 지반침하정보 아이콘 표출 오류 수정 2026-06-10 18:18:53 +09:00
kiminchan 3dd09d9fc7 하수관로 상세정보 조회속도 개선 2026-06-10 17:53:48 +09:00
kiminchan 46f05dbfa0 지도 최소 줌레벨 및 경계 개선 2026-06-10 16:12:18 +09:00
kiminchan 823d1d7812 지반침하 연도 조건과 팝업 조회조건 동기화 정리 2026-06-09 16:42:15 +09:00
kiminchan a274b5a261 지반침하 팝업 조회조건, 다운로드, 지도표출 방식 정리 2026-06-09 15:26:09 +09:00
kiminchan 8737d1eb0a gis 편집 스냅핑, 꼭지점 제거 기능 구현 2026-06-08 17:40:10 +09:00
kiminchan a123588e32 지반침하정보 지도, 상세, 설정, 목록 기능 구현 2026-06-05 16:30:58 +09:00
kiminchan cc91225b01 관로 분석 재질별, 경과년도&재질별 조회 오류 해결 2026-06-04 15:54:32 +09:00
kiminchan af8db9457f 노후관로 팝업 위치 수정 2026-06-04 15:16:53 +09:00
kiminchan 5860cf3a22 Merge remote-tracking branch 'origin/main' into iipbs/sn/dev_kic 2026-06-04 13:08:00 +09:00
kiminchan 9d6cc405a9 하수관망도 - 처리구역분석 상세정보 매설년도-> 경과년도 변경 2026-06-02 16:29:07 +09:00
kiminchan 1c37591bab 노후관로 경과년도 표시 조건 보완 2026-06-02 15:44:36 +09:00
mind-one001 c7c69ea5a7 gis 편집 2026-06-01 15:49:50 +09:00
mind-one001 cdaaa34569 Merge branch 'iipbs/sn/dev' of https://www.onasys.co.kr:3000/ONAANDALL/frontend into iipbs/sn/dev 2026-05-21 15:57:02 +09:00
mind-one001 17637146be 유하방향 줌레벨 표시 추가 2026-05-21 15:56:33 +09:00
kiminchan b4033071a1 하수관로 편집 상세정보 편집 추가, 하수관망도 업로드 시설 선택 보완 2026-05-21 13:57:16 +09:00
kiminchan 0c66a8f3b7 통수위험분석 프로토타입 구현 2026-05-19 13:39:25 +09:00
kiminchan ef7bae98d4 하수관망도 업로드 구현 2026-05-18 10:23:33 +09:00
kiminchan d2a1f5e48b 정보검색, 관로분석(관재질) 팝업 테이블 가로 스크롤 추가 2026-05-15 15:34:25 +09:00
kiminchan 69b717f517 Merge remote-tracking branch 'origin/iipbs/dm/dev' into iipbs/sn/dev_kic 2026-05-15 15:06:46 +09:00
kiminchan 6d0461eaef 하수관로 편집 기능 구현 2026-05-15 15:03:00 +09:00
mind-one001 be72a594d7 Merge branch 'iipbs/sn/dev' of https://www.onasys.co.kr:3000/ONAANDALL/frontend into iipbs/sn/dev
# Conflicts:
#	apps/sn/app/(map-layout)/map/page.tsx
2026-05-13 17:28:21 +09:00
mind-one001 8cc4f58076 Merge branch 'iipbs/sn/dev2' of https://www.onasys.co.kr:3000/ONAANDALL/frontend into iipbs/sn/dev2 2026-05-13 17:17:38 +09:00
mind-one001 3f07739756 유하방향 기능 구현 2026-05-13 16:33:34 +09:00
1904 changed files with 201508 additions and 51681 deletions
+2
View File
@@ -27,6 +27,8 @@ settings.json
.npmrc
.cursor
.agent
CLAUDE.MD
apps/**/tsconfig.tsbuildinfo
packages/**/tsconfig.tsbuildinfo
logs/
+9 -5
View File
@@ -19,11 +19,15 @@
}
],
"paths": {
"@/*": ["./src/*"],
"@common/components": ["../../packages/common/components/dist/"],
"@common/network": ["../../packages/common/network/"]
"@/*": ["./src/*"]
}
},
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
"exclude": ["node_modules"]
"include": [
"next-env.d.ts",
"**/*.ts",
"**/*.tsx",
".next/types/**/*.ts",
"../../packages/common/types/**/*.d.ts"
],
"exclude": ["node_modules", ".next", "dist", "coverage", "storybook-static", "public"]
}
+13
View File
@@ -0,0 +1,13 @@
import "@/app/styles/globals.css";
export const metadata = {
title: "디지털 행정지원 시스템",
};
export default function AuthLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="ko">
<body>{children}</body>
</html>
);
}
@@ -0,0 +1 @@
export { CodeManagementPage as default } from "@/pages/code-management";
@@ -0,0 +1,3 @@
import { DashboardPage } from "@/pages/dashboard/ui/dashboard-page";
export default DashboardPage;
@@ -0,0 +1,10 @@
import { DesignEditPage } from "@/pages/design-cnstn";
interface PageProps {
params: Promise<{ id: string }>;
}
export default async function Page({ params }: PageProps) {
const { id } = await params;
return <DesignEditPage id={id} />;
}
@@ -0,0 +1,10 @@
import { DesignDetailGate } from "@/pages/design-cnstn";
interface PageProps {
params: Promise<{ id: string }>;
}
export default async function Page({ params }: PageProps) {
const { id } = await params;
return <DesignDetailGate id={id} />;
}
@@ -0,0 +1,11 @@
import { Suspense } from "react";
import { DesignListPage } from "@/pages/design-cnstn";
export default function Page() {
return (
<Suspense>
<DesignListPage />
</Suspense>
);
}
@@ -0,0 +1,27 @@
import { DesignRegistPage } from "@/pages/design-cnstn";
import { parseTaskSeComCdFromApi } from "@/pages/design-cnstn/lib/design-cnstn-regist-schema";
interface PageProps {
searchParams: Promise<{
taskSeComCd?: string;
admdstCd?: string;
sido?: string;
gugun?: string;
}>;
}
export default async function Page({ searchParams }: PageProps) {
const params = await searchParams;
const taskSeComCd = parseTaskSeComCdFromApi(params.taskSeComCd);
return (
<DesignRegistPage
defaults={{
taskSeComCd: taskSeComCd.length ? taskSeComCd : undefined,
admdstCd: params.admdstCd,
sido: params.sido,
gugun: params.gugun,
}}
/>
);
}
@@ -0,0 +1,10 @@
import { FnrsEditPage } from "@/pages/fnrs-cnsltn";
interface PageProps {
params: Promise<{ id: string }>;
}
export default async function Page({ params }: PageProps) {
const { id } = await params;
return <FnrsEditPage id={id} />;
}
@@ -0,0 +1,10 @@
import { FnrsDetailGate } from "@/pages/fnrs-cnsltn";
interface PageProps {
params: Promise<{ id: string }>;
}
export default async function Page({ params }: PageProps) {
const { id } = await params;
return <FnrsDetailGate id={id} />;
}
@@ -0,0 +1,11 @@
import { Suspense } from "react";
import { FnrsListPage } from "@/pages/fnrs-cnsltn";
export default function Page() {
return (
<Suspense>
<FnrsListPage />
</Suspense>
);
}
@@ -0,0 +1,27 @@
import { FnrsRegistPage } from "@/pages/fnrs-cnsltn";
import { parseTaskSeComCdFromApi } from "@/pages/fnrs-cnsltn/lib/fnrs-cnsltn-regist-schema";
interface PageProps {
searchParams: Promise<{
taskSeComCd?: string;
admdstCd?: string;
sido?: string;
gugun?: string;
}>;
}
export default async function Page({ searchParams }: PageProps) {
const params = await searchParams;
const taskSeComCd = parseTaskSeComCdFromApi(params.taskSeComCd);
return (
<FnrsRegistPage
defaults={{
taskSeComCd: taskSeComCd.length ? taskSeComCd : undefined,
admdstCd: params.admdstCd,
sido: params.sido,
gugun: params.gugun,
}}
/>
);
}
@@ -0,0 +1,10 @@
import { InstlEditPage } from "@/pages/instl-sncn";
interface InstlSncnEditRouteProps {
params: Promise<{ id: string }>;
}
export default async function Page({ params }: InstlSncnEditRouteProps) {
const { id } = await params;
return <InstlEditPage id={id} />;
}
@@ -0,0 +1,6 @@
import { InstlSncnDetailGate } from "@/pages/instl-sncn";
export default async function InstlSncnDetailPage({ params }: { params: Promise<{ id: string }> }) {
const { id } = await params;
return <InstlSncnDetailGate id={id} />;
}
@@ -0,0 +1,11 @@
import { Suspense } from "react";
import { InstlListPage } from "@/pages/instl-sncn";
export default function Page() {
return (
<Suspense>
<InstlListPage />
</Suspense>
);
}
@@ -0,0 +1,28 @@
import { InstlRegistPage } from "@/pages/instl-sncn";
interface InstlSncnRegistRouteProps {
searchParams: Promise<{
taskSeComCd?: string;
admdstCd?: string;
sido?: string;
gugun?: string;
}>;
}
export default async function Page({ searchParams }: InstlSncnRegistRouteProps) {
const params = await searchParams;
const taskSeComCd = params.taskSeComCd
? params.taskSeComCd.split(",").filter(Boolean)
: undefined;
return (
<InstlRegistPage
defaults={{
taskSeComCd,
admdstCd: params.admdstCd,
sido: params.sido,
gugun: params.gugun,
}}
/>
);
}
@@ -0,0 +1,3 @@
import { MyPbadmsSprtListPage } from "@/pages/my-pbadms-sprt";
export default MyPbadmsSprtListPage;
@@ -0,0 +1,3 @@
import { NtiHstryListPage } from "@/pages/nti-hstry";
export default NtiHstryListPage;
@@ -0,0 +1,3 @@
import { NtitlkSndngPage } from "@/pages/ntitlk-sndng";
export default NtitlkSndngPage;
@@ -0,0 +1,13 @@
import { SewerBscPlanEditPage } from "@/pages/sewer-bsc-plan";
interface PageProps {
params: Promise<{ id: string }>;
searchParams: Promise<{ chgCycl?: string }>;
}
export default async function Page({ params, searchParams }: PageProps) {
const { id } = await params;
const { chgCycl } = await searchParams;
const propChgCycl = chgCycl ? Number(chgCycl) : undefined;
return <SewerBscPlanEditPage id={id} propChgCycl={propChgCycl} />;
}
@@ -0,0 +1,13 @@
import { SewerBscPlanDetailGate } from "@/pages/sewer-bsc-plan";
interface PageProps {
params: Promise<{ id: string }>;
searchParams: Promise<{ chgCycl?: string }>;
}
export default async function Page({ params, searchParams }: PageProps) {
const { id } = await params;
const { chgCycl } = await searchParams;
const propChgCycl = chgCycl ? Number(chgCycl) : undefined;
return <SewerBscPlanDetailGate id={id} propChgCycl={propChgCycl} />;
}
@@ -0,0 +1,11 @@
import { Suspense } from "react";
import { SewerBscPlanListPage } from "@/pages/sewer-bsc-plan";
export default function Page() {
return (
<Suspense>
<SewerBscPlanListPage />
</Suspense>
);
}
@@ -0,0 +1,19 @@
import { SewerBscPlanRegistPage } from "@/pages/sewer-bsc-plan";
interface PageProps {
searchParams: Promise<{
taskSeComCd?: string;
taskSeCdNm?: string;
sewerBscPlanSeComCd?: string;
sewerBscPlanSeCdNm?: string;
admdstCd?: string;
sido?: string;
gugun?: string;
}>;
}
export default async function Page({ searchParams }: PageProps) {
const params = await searchParams;
return <SewerBscPlanRegistPage defaults={params} />;
}
@@ -6,8 +6,8 @@ import { Providers } from "@/app/providers";
import "@/app/styles/globals.css";
export const metadata: Metadata = {
title: "행정지원시스템",
description: "행정지원시스템",
title: "디지털 행정지원 시스템",
description: "디지털 행정지원 시스템",
};
interface RootLayoutProps {
@@ -1 +0,0 @@
export { AcntgCodeManagementPage as default } from "@/pages/acntg-code-management";
@@ -1 +0,0 @@
export { CnstpCodeManagementPage as default } from "@/pages/cnstp-code-management";
@@ -1,10 +0,0 @@
import { CnfmModifyPage } from "@/pages/instl-sncn";
export default async function InstlSncnModifyPage({
params,
}: {
params: Promise<{ id: string }>;
}) {
const { id } = await params;
return <CnfmModifyPage id={id} />;
}
@@ -1,10 +0,0 @@
import { CnfmViewPage } from "@/pages/instl-sncn";
export default async function InstlSncnViewPage({
params,
}: {
params: Promise<{ id: string }>;
}) {
const { id } = await params;
return <CnfmViewPage id={id} />;
}
@@ -1,3 +0,0 @@
import { CnfmListPage } from "@/pages/instl-sncn";
export default CnfmListPage;
@@ -1,5 +0,0 @@
import { CnfmRegistPage } from "@/pages/instl-sncn";
export default function Page(props: any) {
return <CnfmRegistPage {...props} />;
}
-1
View File
@@ -1 +0,0 @@
export { MainPage as default } from "@/pages/home";
+10
View File
@@ -0,0 +1,10 @@
import { cookies } from "next/headers";
import { NextResponse } from "next/server";
import { COOKIE_DOMAIN, REFRESH_TOKEN } from "@/shared/config";
export async function POST() {
const cookieStore = await cookies();
cookieStore.delete({ name: REFRESH_TOKEN, domain: COOKIE_DOMAIN });
return NextResponse.json({ message: "Logged out" }, { status: 200 });
}
+6 -23
View File
@@ -5,6 +5,7 @@ import {
ACCESS_TOKEN,
AUTH_USER_ID,
CLAIM_NAME,
COOKIE_DOMAIN,
REFRESH_TOKEN,
SERVER_API_URL,
SITE_ID,
@@ -20,6 +21,10 @@ async function handler(
"Content-Type": "application/json",
"X-Site-Id": SITE_ID,
};
const deviceId = request.headers.get("X-Device-Id");
if (deviceId) {
headers["X-Device-Id"] = deviceId;
}
let body = {};
const isRefreshHandler = params.url.includes("refresh");
@@ -39,27 +44,13 @@ async function handler(
}
const targetUrl = `${SERVER_API_URL}/${params.url.join("/")}`;
console.log(`[Proxy API] ${method} ${params.url.join("/")} -> ${targetUrl}`);
console.log(`[Proxy API] Headers:`, headers);
if (!isRefreshHandler) {
console.log(`[Proxy API] Body:`, body);
}
const result = await fetch(targetUrl, {
method,
headers,
body: JSON.stringify(body),
});
console.log(`[Proxy API] Response Status: ${result.status}`);
console.log(`[Proxy API] Response Headers:`, {
[ACCESS_TOKEN]: result.headers.get(ACCESS_TOKEN),
[REFRESH_TOKEN]: result.headers.get(REFRESH_TOKEN) ? '***hidden***' : undefined,
[AUTH_USER_ID]: result.headers.get(AUTH_USER_ID),
});
if (!result.ok) {
console.error(`[Proxy API] Request failed with status ${result.status}`);
return NextResponse.json({ message: "Invalid Credentials" }, { status: 401 });
}
@@ -68,24 +59,16 @@ async function handler(
const userId = result.headers.get(AUTH_USER_ID);
if (accessToken && userId) {
console.log(`[Proxy API] Login successful for user: ${userId}`);
const response = NextResponse.json({
[ACCESS_TOKEN]: accessToken,
[AUTH_USER_ID]: userId,
});
const forwardedHost = request.headers.get("x-forwarded-host");
const host = request.headers.get("host");
const actualHost = forwardedHost || host || new URL(request.url).hostname.toString();
// 운영 환경에서 domain 설정
const domain = actualHost.includes("hasuon.or.kr") ? ".hasuon.or.kr" : actualHost;
if (refreshToken) {
cookieStore.set(REFRESH_TOKEN, refreshToken, {
httpOnly: true,
sameSite: "strict",
domain: domain,
domain: COOKIE_DOMAIN,
path: "/",
});
}
+38
View File
@@ -0,0 +1,38 @@
import type { Metadata } from "next";
import Image from "next/image";
import "@/app/styles/globals.css";
export const metadata: Metadata = {
title: "디지털 행정지원 시스템",
description: "페이지가 존재하지 않습니다. 관리자에게 문의하여 주십시오.",
};
export default function GlobalNotFound() {
return (
<html lang="ko">
<body>
<main className="flex min-h-screen flex-col items-center justify-center bg-[#f0f4f8] px-4 py-16">
<div className="mb-16 text-center">
<h1 className="text-[3.2rem] font-bold leading-snug tracking-tight">
<span className="text-primary">디지털 행정지원 시스템</span>에 오신 것을 환영합니다.
</h1>
<p className="mt-6 text-[2rem] text-[#666]">오류가 발생하였습니다.</p>
</div>
<section className="card card-border flex w-full max-w-[72rem] flex-col items-center !rounded-2xl !py-16">
<Image
src="/images/magnifying-glass-with-warning.png"
alt=""
width={280}
height={280}
className="size-[28rem] object-contain"
/>
<p className="mt-4 text-[2.4rem] font-bold text-[#444]">페이지가 존재하지 않습니다.</p>
<p className="mt-2 text-[1.6rem] text-[#666]">관리자에게 문의하여 주십시오</p>
</section>
</main>
</body>
</html>
);
}
@@ -0,0 +1,250 @@
# 재원협의·실무협의 프론트엔드 개발 가이드
> **대상 앱**: `frontend/apps/as`
> **작성일**: 2026-08-27
> **개정일**: 2026-09-07
> **버전**: 2.0
> **Process**: PR-AS-003 (재원협의 관리 — 실무협의 및 AI 검증 통합)
>
> **SoT (2026-09-03 완결)**:
>
> - 프로세스·상태·버튼: `03.재원협의_실무협의_프로세스_통합_v완결.md`
> - REST 설계: `05.재원협의_상태별_endpoint_설계.md`
> - 공통코드: `FNRSSTTS` (`SV, ST, LE, FV, ER, SL, AC, TE, TP, RM, RB, RC, RA, AV, EV, RK, RR, EP, TA`)
>
> **백엔드 서비스**:
>
> - `as-service` — `/api/v1/fnrs-cnsltn-mng`, `/api/v1/pwrk-cnsltn-mng`, `/api/v1/pwrk-cnsltn-doc-crt-rslt`, `/api/v1/dcrag-to`
> - `as-elapr-service` — `/api/v1/elapr-dmnd`, `/api/v1/elapr-prgrs-stts`, `/api/v1/elapr-apln`
>
> **현재 프론트 상태**: 재원협의(`fnrs-cnsltn`)·전자결재(`elapr`)·DC RAG TO(`dcrag-to`)는 존재한다. 실무협의(`pwrk-cnsltn-`\*) 엔티티·화면은 **미구현**. 버튼 매트릭스·상태코드는 **v2.1 잔존**이며 v3.0(`FNRSSTTS`)과 불일치한다. [9절](#9-현재-코드-vs-to-be-갭) 참고.
---
## 1. 문서 목적
재원협의 4대 주체(기초·광역·환경청·공단)의 **상태 전이·버튼·API**를 `apps/as`에 구현할 때 쓰는 프론트엔드 가이드이다.
v1.0은 공단 접수자의 **자료검증 → 초안생성 → 웹기안기**만 다뤘다. v2.0은 2026-09-03 완결 프로세스 기준으로 **신청부터 최종종결(**`TA`**)까지**, 실무협의·AI 3파이프라인·결재선·보완 루프를 포함한다.
상세 표·시퀀스·DTO는 본문에 넣지 않고 레퍼런스로 분리한다. 구현 중에는 본문의 규칙만 보고, 표가 필요하면 해당 파일을 연다.
---
## 2. 문서 맵
| 파일 | 내용 | 언제 보는가 |
| -------------------------------------------------------- | ------------------------------------------------------------------------- | ----------------------- |
| [development-guide.md](./development-guide.md) (본 문서) | 도메인, 핵심 규칙, 화면 흐름, 갭, 구현 순서 | 일상 구현 |
| [ref-process-status.md](./ref-process-status.md) | 4-Lane 시퀀스, Activity, `FNRSSTTS`, 보완 3루프, AI 타임아웃, 결재선 복사 | 상태 전이·폴링 UX |
| [ref-screen-buttons.md](./ref-screen-buttons.md) | 38행 화면·역할·버튼 매트릭스, 버튼 가시성 | `button-config.ts` 개편 |
| [ref-endpoint.md](./ref-endpoint.md) | 버튼→API 총괄, 단계별 입출력, FE 호출 금지 API, Gap Analysis | 엔티티·service 매핑 |
| [ref-frontend-entities.md](./ref-frontend-entities.md) | ENDPOINT, 슬라이스, Service 시그니처, 폴링, 웹기안기, DTO | 엔티티 레이어 구현 |
| [ref-webhwp-api.md](./ref-webhwp-api.md) | 웹한글기안기 v3 `HwpCtrl` Properties/Methods, Open/SaveAs | 기안기 위젯 연동 |
---
## 3. 도메인 개요
실무협의서(PWRK)는 재원협의서(FNRS)의 **하위 문서**이다. 재원협의 1건당 실무협의서는 **1건만** 생성된다.
| 문서 | 번호 예시 | 필드 |
| -------- | ----------------- | ----------------------------- |
| 재원협의 | `F-20260824-0001` | `fnrsCnsltnDocNo` / `upDocNo` |
| 실무협의 | `P-20260827-0001` | `pwrkCnsltnDocNo` |
진행상태는 **재원협의 마스터** `tb_as_fnrs_cnsltn_mng.prgrs_stts_com_cd` (`FNRSSTTS`)가 SSOT이다. 실무협의 문서의 `prgrsSttsComCd`는 연계 표시용이며, 화면 버튼은 재원협의 상태로 분기한다.
### 3-1. 4대 주체
| 역할 | 코드 | 화면 소유 | 핵심 구간 |
| --------------- | ------------- | -------------- | ------------------------------------ |
| 기초자치단체 | `ROLE_USER05` | 작성/수정/상세 | 신청, 3종 보완, 조치결과, 최종확인 |
| 광역자치단체 | `ROLE_USER04` | 상세 | 경유 제출, 결과 전달 |
| 유역·지방환경청 | `ROLE_USER03` | 상세 | 의뢰/자체종결, 1·2차 회신 |
| 한국환경공단 | `ROLE_USER01` | 상세 + 결재선 | 파일검증, 검토자지정, 1·2차 기술검토 |
### 3-2. 핵심 식별자
| 필드 | 의미 | 비고 |
| ----------------- | ---------------- | ----------------------------------------------------------- |
| `fnrsCnsltnDocNo` | 재원협의문서번호 | 상태 전이·목록 PK |
| `pwrkCnsltnDocNo` | 실무협의문서번호 | `P-YYYYMMDD-NNNN`. 검토자지정(`ER→AC`) 시 발급 |
| `upDocNo` | 상위문서번호 | 재원협의 번호. `upDocSeComCd = "FNRS"` |
| `crtDmndUuid` | 생성요청 UUID | 초안 폴링·웹기안기·다운로드 키 |
| `verSn` | 버전일련번호 | 복합 PK `(crtDmndUuid, verSn)`. 저장 시 서버가 `+1` |
| `orgnlOtptDocCn` | HWP 바이너리 | 목록/상세 응답은 항상 `null`. 다운로드·`webhwp/open`만 사용 |
| `elaprCycl` | 결재 차수 | 1차 `TE`, 2차 `RK`. 금액검증 완료 후 1차 결재선 복사 |
### 3-3. IIPBS 약어
| 한글 | 약어 | 필드 예 |
| ---- | ------------ | --------------------------- |
| 재원 | FNRS | `fnrsCnsltnDocNo` |
| 실무 | PWRK | `pwrkCnsltnDocNo` |
| 협의 | CNSLTN | `fnrs-cnsltn-mng` |
| 생성 | CRT | `crtDmndUuid` |
| 요청 | DMND | `crtDmndUuid`, `elapr-dmnd` |
| 검증 | VRFC | `vrfcSttsComCd` |
| 보완 | SPLMNT | `splmntDmndList` |
| 결재 | ELAPR / ATRZ | `elaprCycl`, `atrzSeComCd` |
---
## 4. 상태코드 한눈에 보기
상위코드 `FNRSSTTS`. v1.0의 `PWRKSTTS`(`DV`, `AR`, `TR` 등)는 **폐기**한다.
정방향:
```
SV → ST → LE → FV → ER → AC → TE → TP → RM → RB → RC → RA → AV → EV → RK → RR → EP → TA
```
자체종결: `LE → EP → TA`
보완: `ER|TE|RK → SL` 후 직전 상태로 복귀.
| 코드 | 명칭 | FE에서 할 일 |
| ---- | ---------------------- | ------------------------------------------------- |
| `SV` | 저장 | 기초 작성화면 저장/신청/삭제 |
| `ST` | 신청완료 | 광역 환경청제출 |
| `LE` | 환경청 검토 | 자체종결(`EP`) 또는 기술검토 의뢰(`FV`) |
| `FV` | 파일검증 | AI 진행 표시. **30분** 후 `ER` Fallback |
| `ER` | 기술검토 의뢰 | 공단 접수자: 파일보완 / 수동파일검증 / 검토자지정 |
| `SL` | 보완요청 | 기초 수정화면. 복귀 대상은 이력의 직전 상태 |
| `AC` | 초안생성 | AI 진행 표시. **30분** 후 `TE` Fallback |
| `TE` | 기술검토 | 웹기안기·검토완료·보완. 결재선 1차 |
| `TP` | 기술검토 회신 | 환경청 → 광역 `RM` |
| `RM` | 재원협의결과회신 | 광역 → 기초 `RB` |
| `RB` | 지자체회신 | 기초 실무협의서 관리 / 조치완료 |
| `RC` | 조치결과서 제출 | 광역 → 환경청 `RA` |
| `RA` | 조치결과서제출(환경청) | 환경청 2차 의뢰 `AV` |
| `AV` | 금액검증 | AI 진행 표시. **30분** 후 `EV` Fallback |
| `EV` | 조치결과검토의뢰 | 공단 접수자: 2차 결재선 검토자지정 → `RK` |
| `RK` | 조치결과서검토 | 웹기안기·금액검증 재실행·보완. 결재선 2차 |
| `RR` | 조치결과서검토 회신 | 환경청 → 광역 `EP` |
| `EP` | 검토결과 회신 | 광역 → 기초 `TA` |
| `TA` | 검토결과 회신(종료) | 기초 조회만. **고시(**`TB`**) 아님** |
코드 의미·구버전 대조·보완 루프·AI Fallback은 [ref-process-status.md](./ref-process-status.md).
---
## 5. 프론트가 지켜야 할 핵심 규칙
1. **상태 SSOT는** `FNRSSTTS`. 버튼 가시성은 `(dtlInstCd, prgrsSttsComCd, atrzSeComCd)`로만 계산한다. 공단은 결재선 구분(`ATRZ01` 접수자, `ATRZ02` 검토자, `ATRZ03` 승인자, `ATRZ99` 최종승인자)을 추가로 본다.
2. **AI 콜백 API는 화면에서 호출하지 않는다.** `POST /dcrag/documents/verify-result`, `POST /dcrag/draft/complete`, `POST /dcrag/cost/verify-result`는 서버 전용이다.
3. **초안생성 1차 트리거는 검토자지정이다.** `POST /elapr-dmnd` (`ER → AC`). 예전처럼 `POST /pwrk-cnsltn-mng`로 초안을 시작하지 않는다.
4. **기술검토 의뢰는** `LE → FV` **전용 API** `POST /fnrs-cnsltn-mng/{docNo}/request-examine`. 현재 코드의 `updatePrgrsStts(ER)` 직행은 폐기.
5. **수동 AI 재실행은 상태를 바꾸지 않는다.**
- `ER` 파일검증 → `POST /dcrag-to/documents/transfer`
- `TE` 초안생성 → `POST /dcrag-to/documents/draft/generate` (타임아웃·실패 시에만)
- `RK` 금액검증 → `POST /dcrag-to/documents/cost/verify`
6. **진행상태만 바꾸는 버튼은** `POST /fnrs-cnsltn-mng/doc/updatePrgrsStts`**를 재사용한다.** (`ST→LE`, `RM→RB`, `RC→RA`, `RR→EP`, `EP→TA`)
7. **보완요청/보완완료는 공통 API** `reqsupplement` / `submitsupplement`. 복귀 상태(`ER`/`TE`/`RK`)는 서버가 이력에서 결정한다. 프론트는 직전 상태를 추측해 보내지 않는다.
8. **결재 승인/회신은** `PUT /elapr-prgrs-stts/{id}/process` **하나**. 1차 최종승인자 → `TP`, 2차 → `RR`은 서버가 Feign으로 처리한다.
9. **2차 결재선은 EV에서 수동 검토자지정**. `POST /elapr-dmnd` (`elaprCycl: 2`, `docPrgrsSttsComCd: RK`). 1차 결재선 자동 copy-line은 사용하지 않는다.
10. **웹기안기는 `webhwp/open` 응답을 axios `blob`으로 조회한 뒤 `File`로 감싸 `HwpCtrl.Open`에 전달한다.** `blob:` Object URL과 `orgnlOtptDocCn`은 쓰지 않는다.
---
## 6. 화면 데이터 흐름
재원협의 **목록 → 상세/작성**이 본체다. 실무협의 목록은 공단 검토 보조 화면이다.
```
BEGIN
CALL fnrsCnsltnMngService.findPage(...)
ON 행 CLICK → /fnrs-cnsltn/{fnrsCnsltnDocNo}
CALL findById(fnrsCnsltnDocNo)
COMPUTE buttons = getButtonConfigs(dtlInstCd, prgrsSttsComCd, atrzSeComCdList)
// ----- 기초 ROLE_USER05 -----
ON [저장] (빈값/SV) → saveApply(prgrsSttsComCd: SV)
ON [신청완료] (SV) → saveApply(prgrsSttsComCd: ST)
ON [삭제] (SV) → remove
ON [파일보완완료] (SL←ER) → submitsupplement
ON [보완완료] (SL←TE|RK) → submitsupplement
ON [실무협의서 관리] (RB) → GET webhwp/open (blob) → HwpCtrl.Open(File)
ON [조치완료] (RB) → submit-actn-result { isSubmit: true }
ON [결과회신] (TA) → API 없음 (조회)
// ----- 광역 ROLE_USER04 -----
ON [환경청제출] (ST) → updatePrgrsStts(LE)
ON [지자체회신] (RM) → updatePrgrsStts(RB)
ON [조치결과서제출] (RC) → updatePrgrsStts(RA)
ON [결과회신] (EP) → updatePrgrsStts(TA)
// ----- 환경청 ROLE_USER03 -----
ON [결과회신] (LE 자체종결) → tech-review → EP
ON [기술검토 의뢰] (LE) → request-examine → FV → START POLL FV
ON [재원협의 결과 회신] (TP) → tech-review → RM
ON [실무협의서 관리] (RA) → GET webhwp/open (blob) → HwpCtrl.Open(File) (저장 불가)
ON [조치결과 검토의뢰] (RA) → request-actn-review → AV → START POLL AV
ON [결과회신] (RR) → updatePrgrsStts(EP)
// ----- 공단 ROLE_USER01 -----
ON [파일보완] (ER, ATRZ01) → GET file-vrfc-results → 팝업 → reqsupplement
ON [파일검증] (ER, ATRZ01) → dcrag-to transfer (상태 유지)
ON [검토자지정] (ER, ATRZ01) → POST elapr-dmnd (docPrgrsSttsComCd: AC) → START POLL AC
ON [검토자지정] (EV, ATRZ01) → POST elapr-dmnd (elaprCycl: 2, docPrgrsSttsComCd: RK)
ON [실무협의서관리] (TE|RK) → GET webhwp/open (blob) → HwpCtrl.Open(File)
ON [실무협의서생성] (TE, 실패/타임아웃) → dcrag-to draft/generate
ON [검토결과조회] (TE) → pwrk-cnsltn-mng findById | findByUpDocNo
ON [저장] (TE|RK) → pwrk-cnsltn-mng save-apply
ON [검토완료] → elapr-prgrs-stts process (상신)
ON [보완요청] (TE|RK) → 보완 팝업 → reqsupplement
ON [금액검증] (RK) → dcrag-to cost/verify
ON [결재(승인)] → process (중간)
ON [결재(회신)] → process (최종 → TP 또는 RR)
// ----- AI 진행 중 (FV / AC / AV) -----
POLL 상태 또는 draft status. 30분 안내. 종료 후 상세 invalidate
END
```
38행 버튼 표는 [ref-screen-buttons.md](./ref-screen-buttons.md). API 상세는 [ref-endpoint.md](./ref-endpoint.md).
---
## 7. 버튼 → API 축약
프론트가 치는 것만. 콜백·스케줄러는 제외.
| 주체 | 버튼 | From → To | Method & URI |
| --------- | -------------------------- | ----------------------------- | ---------------------------------------------------------------------------------- |
| 기초 | 저장 / 신청완료 | →`SV` / `SV→ST` | `POST /fnrs-cnsltn-mng/save-apply` |
| 기초 | 삭제 | `SV` | `DELETE /fnrs-cnsltn-mng/{docNo}` |
| 광역 | 환경청제출 | `ST→LE` | `POST /fnrs-cnsltn-mng/doc/updatePrgrsStts` |
| 환경청 | 결과회신(자체종결) | `LE→EP` | `POST /fnrs-cnsltn-mng/{docNo}/tech-review` |
| 환경청 | 기술검토 의뢰 | `LE→FV` | **신규** `POST /fnrs-cnsltn-mng/{docNo}/request-examine` |
| 공단 접수 | 파일보완 팝업 | `ER` | `GET /fnrs-cnsltn-mng/{docNo}/file-vrfc-results` |
| 공단 접수 | 파일보완요청 | `ER→SL` | `POST /fnrs-cnsltn-mng/{docNo}/reqsupplement` |
| 공단 접수 | 파일검증 재실행 | `ER` 유지 | `POST /dcrag-to/documents/transfer` |
| 공단 접수 | 검토자지정 | `ER→AC` | `POST /elapr-dmnd` (`elaprCycl: 1`) |
| 공단 접수 | 검토자지정 | `EV→RK` | `POST /elapr-dmnd` (`elaprCycl: 2`) |
| 공단 검토 | 실무협의서관리 | `TE`/`RK` | `GET .../pwrk-cnsltn-doc-crt-rslt/{uuid}/webhwp/open` |
| 공단 검토 | 실무협의서생성 | `TE` 유지 | `POST /dcrag-to/documents/draft/generate` |
| 공단 검토 | 저장 | `TE`/`RK` | `POST /pwrk-cnsltn-mng/save-apply` |
| 공단 | 검토완료 / 결재(승인·회신) | `TE` 유지 / `TE→TP` / `RK→RR` | `PUT /elapr-prgrs-stts/{id}/process` |
| 공단 검토 | 보완요청 | `TE→SL` / `RK→SL` | `POST /fnrs-cnsltn-mng/{docNo}/reqsupplement` |
| 기초 | 파일보완완료 / 보완완료 | `SL→ER` / `TE` / `RK` | `POST /fnrs-cnsltn-mng/{docNo}/submitsupplement` |
| 환경청 | 재원협의 결과 회신 | `TP→RM` | `POST /fnrs-cnsltn-mng/{docNo}/tech-review` |
| 광역 | 지자체회신 | `RM→RB` | `updatePrgrsStts` |
| 기초 | 실무협의서 관리 | `RB` 유지 | `GET .../pwrk-cnsltn-doc-crt-rslt/{uuid}/webhwp/open` |
| 기초 | 조치완료 | `RB→RA` | **신규** `POST /pwrk-cnsltn-mng/{pwrkDocNo}/submit-actn-result` (`isSubmit: true`) |
| 광역 | 조치결과서제출 | `RC→RA` | `updatePrgrsStts` |
| 환경청 | 실무협의서 관리 | `RA` 유지 (조회) | `GET .../pwrk-cnsltn-doc-crt-rslt/{uuid}/webhwp/open` |
| 환경청 | 조치결과 검토의뢰 | `RA→AV` | **신규** `POST /fnrs-cnsltn-mng/{docNo}/request-actn-review` |
| 공단 검토 | 금액검증 재실행 | `RK` 유지 | `POST /dcrag-to/documents/cost/verify` |
| 환경청 | 결과회신 | `RR→EP` | `updatePrgrsStts` |
| 광역 | 결과회신 | `EP→TA` | `updatePrgrsStts` |
| 웹기안기 | 저장 | 버전 +1 | `POST /pwrk-cnsltn-doc-crt-rslt` multipart |
| 공통 | 다운로드 | — | `GET /pwrk-cnsltn-doc-crt-rslt/{uuid}/download` |
신규 4개: `request-examine`, `submit-actn-result`, `request-actn-review`, EV 2차 `elapr-dmnd`.
---
+334
View File
@@ -0,0 +1,334 @@
# 레퍼런스 — 상태별 Endpoint
> 상위: [개발가이드.md](./개발가이드.md)
> SoT: `05.재원협의_상태별_endpoint_설계.md` (v1.0, 2026-09-03)
> Gateway: `/as-service`, `/as-elapr-service`
> Auth: `Authorization`, `X-Site-Id`, `token-id` (기존 `client` 인터셉터)
> 날짜: `yyyy-MM-dd HH:mm:ss`
프론트가 치는 API만 상세히 적는다. AI 콜백·스케줄러·Feign은 [§6 호출 금지](#6-프론트-호출-금지).
---
## 1. 총괄 매트릭스 (38 + WebHWP)
| 순번 | 버튼 | From → To | 서비스 | Method & URI | 구분 |
| :---: | --- | --- | --- | --- | --- |
| 1 | 저장 | →`SV` | as | `POST /api/v1/fnrs-cnsltn-mng/save-apply` | 기존 |
| 2 | 신청완료 | `SV→ST` | as | 동일 (`prgrsSttsComCd=ST`) | 기존 |
| 3 | 삭제 | `SV` | as | `DELETE /api/v1/fnrs-cnsltn-mng/{docNo}` | 기존 |
| 4 | 환경청제출 | `ST→LE` | as | `POST /api/v1/fnrs-cnsltn-mng/doc/updatePrgrsStts` | 기존 |
| 5 | 결과회신(자체종결) | `LE→EP` | as | `POST /api/v1/fnrs-cnsltn-mng/{docNo}/tech-review` | 기존 |
| 6 | 기술검토 의뢰 | `LE→FV` | as | `POST /api/v1/fnrs-cnsltn-mng/{docNo}/request-examine` | **신규** |
| 7 | 파일검증 콜백 | `FV→ER` | as | `POST /api/v1/dcrag/documents/verify-result` | 서버 |
| 8 | 파일보완 팝업 | `ER` | as | `GET /api/v1/fnrs-cnsltn-mng/{docNo}/file-vrfc-results` | 기존 |
| 9 | 파일보완요청 | `ER→SL` | as | `POST /api/v1/fnrs-cnsltn-mng/{docNo}/reqsupplement` | 기존 |
| 10 | 파일검증 재실행 | `ER` | as | `POST /api/v1/dcrag-to/documents/transfer` | 기존 |
| 11 | 검토자지정 | `ER→AC` | elapr | `POST /api/v1/elapr-dmnd` | 기존 |
| 12 | 초안 콜백 | `AC→TE` | as | `POST /api/v1/dcrag/draft/complete` | 서버 |
| 13 | 실무협의서관리 | `TE` | as | `GET /api/v1/pwrk-cnsltn-mng/updocno/{upDocNo}` | 기존 |
| 14 | 검토결과조회 | `TE` | as | `GET /api/v1/pwrk-cnsltn-mng/{pwrkDocNo}` | 기존 |
| 15 | 실무협의서생성 | `TE` | as | `POST /api/v1/dcrag-to/documents/draft/generate` | 기존 |
| 16 | 저장(실무) | `TE` | as | `POST /api/v1/pwrk-cnsltn-mng/save-apply` | 기존 |
| 17 | 검토완료 | `TE` | elapr | `PUT /api/v1/elapr-prgrs-stts/{id}/process` | 기존 |
| 18 | 보완요청 | `TE→SL` | as | `POST .../reqsupplement` | 기존 |
| 19 | 결재(승인) | `TE` | elapr | `PUT .../process` | 기존 |
| 20 | 결재(회신) | `TE→TP` | elapr | `PUT .../process` | 기존 |
| 21 | 파일보완완료 | `SL→ER` | as | `POST .../submitsupplement` | 기존 |
| 22 | 보완완료(기술) | `SL→TE` | as | 동일 | 기존 |
| 23 | 보완완료(조치) | `SL→RK` | as | 동일 | 기존 |
| 24 | 재원협의 결과 회신 | `TP→RM` | as | `POST .../{docNo}/tech-review` | 기존 |
| 25 | 지자체회신 | `RM→RB` | as | `POST .../doc/updatePrgrsStts` | 기존 |
| 26 | 실무협의서 관리 | `RB` | as | `GET .../pwrk-cnsltn-doc-crt-rslt/{uuid}/webhwp/open` | 기존 |
| 27 | 조치완료 | `RB→RA` | as | `POST /api/v1/pwrk-cnsltn-mng/{pwrkDocNo}/submit-actn-result` (`isSubmit=true`) | **신규** |
| 28 | 조치결과서제출 | `RC→RA` | as | `updatePrgrsStts` | 기존 |
| 29 | 조치결과 검토의뢰 | `RA→AV` | as | `POST /api/v1/fnrs-cnsltn-mng/{docNo}/request-actn-review` | **신규** |
| 30 | 금액검증 콜백 | `AV→EV` | as | `POST /api/v1/dcrag/cost/verify-result` | 서버 |
| 30a | 검토자지정(2차) | `EV→RK` | elapr | `POST /api/v1/elapr-dmnd` (`elaprCycl=2`) | 기존 |
| 31 | 실무협의서관리 | `RK` | as | `GET /pwrk-cnsltn-mng/{pwrkDocNo}` | 기존 |
| 32 | 금액검증 재실행 | `RK` | as | `POST /api/v1/dcrag-to/documents/cost/verify` | 기존 |
| 33 | 보완요청(금액) | `RK→SL` | as | `reqsupplement` | 기존 |
| 34 | 결재(승인) | `RK` | elapr | `process` | 기존 |
| 35 | 결재(회신) | `RK→RR` | elapr | `process` | 기존 |
| 36 | 결과회신 | `RR→EP` | as | `updatePrgrsStts` | 기존 |
| 37 | 결과회신 | `EP→TA` | as | `updatePrgrsStts` | 기존 |
| 38 | 결과회신(확인) | `TA` | — | 없음 | — |
| W1 | 웹기안기 Open | — | as | `GET /api/v1/pwrk-cnsltn-doc-crt-rslt/{uuid}/webhwp/open` | 기존 |
| W2 | HWPX 저장 | — | as | `POST /api/v1/pwrk-cnsltn-doc-crt-rslt` multipart | 기존 |
| W3 | 다운로드 | — | as | `GET /api/v1/pwrk-cnsltn-doc-crt-rslt/{uuid}/download` | 기존 |
| E-N | 결재선 복사 | `AV→RK` 부수 | elapr | `POST /api/v1/elapr-apln/copy-line` | **신규·서버** |
조회 공통: `GET /fnrs-cnsltn-mng`, `GET /fnrs-cnsltn-mng/{docNo}`, `GET /pwrk-cnsltn-mng`, `GET /dcrag-to/documents/draft/status/{crtDmndUuid}`.
---
## 2. 공통 요청
### `DocPrgrsUpdateRequestDto`
`POST /fnrs-cnsltn-mng/doc/updatePrgrsStts` — `ST→LE`, `RM→RB`, `RC→RA`, `RR→EP`, `EP→TA`.
```json
{
"docNo": "F-20260824-0001",
"docSeComCd": "FNRS",
"prgrsSttsComCd": "LE",
"rgtrUuid": "optional-uuid",
"rmrk": "optional"
}
```
응답: `204/200` void. 프론트 엔티티: 기존 `changePrgrsSttsComCd`.
### `FnrsCnsltnApplySaveRequestDto`
`save-apply`, `tech-review`, `reqsupplement`, `submitsupplement`가 공유. 핵심은 `fnrsCnsltnMng.prgrsSttsComCd`와 중첩 리스트(`bzScaleList`, `bizCstList`, `cklstResultList`, `esntlAtchFileList`, `splmntDmndList`).
---
## 3. 단계별 FE API
### 3-1. `SV → ST → LE`
**저장 / 신청완료** — `POST /fnrs-cnsltn-mng/save-apply`
권한: `ROLE_USER05`. 임시저장은 `prgrsSttsComCd=SV`, 신청은 `ST`.
응답: `string` (문서번호). 기존 `fnrsCnsltnMngService.saveApply`.
**삭제** — `DELETE /fnrs-cnsltn-mng/{docNo}` (`SV`만).
**환경청제출** — `updatePrgrsStts` `LE`. 권한: `ROLE_USER04`.
### 3-2. `LE → FV | EP`
**자체종결** — `POST /fnrs-cnsltn-mng/{docNo}/tech-review`
Body: `FnrsCnsltnApplySaveRequestDto` (환경청 의견·체크리스트). `LE→EP`.
기존 `techReview`. 현재 화면은 `TP`에서도 이 API를 쓰며 목표 상태를 `EP`로 넣고 있다 → **`TP`는 `RM`으로 바꿔야 함**.
**기술검토 의뢰 (신규)** — `POST /fnrs-cnsltn-mng/{docNo}/request-examine`
```json
{ "prgrsSttsComCd": "FV" }
```
응답: `string` (docNo). `LE→FV` + AI 파일검증 + 30분 타이머(서버).
프론트: `fnrsCnsltnMngService.requestExamine(docNo, body)` 추가. **`updatePrgrsStts("ER")` 금지.**
### 3-3. `FV → ER → SL → ER`
파일검증 콜백은 서버. FE는 `FV`에서 상세 refetch.
**검증결과 목록** — `GET /fnrs-cnsltn-mng/{fnrsCnsltnDocNo}/file-vrfc-results`
응답: `FnrsCnsltnFileVrfcRsltResponseDto[]`
| 필드 | 설명 |
| --- | --- |
| `fileSeComCd` | `ESSENTIAL` / `ADDITIONAL` |
| `fileSeNm` | 구분명 |
| `esntlAtchFileId` | 필수첨부 ID |
| `atchFileNm` | 파일명 |
| `vrfcRsltComCd` | `PASS` / `FAIL` / `WARN` |
| `vrfcOpnn` | 검증의견 |
엔티티에 `findFileVrfcResults` 추가. 첨부 행 배지는 상세 `esntlFileList`/`etcFileList`의 `vrfcSttsComCd`, `vrfcRsltCn`, `vrfcDt`도 사용 (타입 확장 필요).
**파일보완요청** — `POST .../{docNo}/reqsupplement` (`ER→SL`).
**파일보완완료** — `POST .../{docNo}/submitsupplement` (`SL→ER`). 복귀는 서버.
**파일검증 재실행** — `POST /dcrag-to/documents/transfer`
```json
{ "fnrsCnsltnDocNo": "F-20260824-0001", "taskSeComCd": "SF", "taskSeCdNm": "하수처리시설" }
```
응답: `{ resultCode, message, requestId }`. 상태 유지. 기존 `dcRagApiToService.requestDocumentTransfer`.
### 3-4. `ER → AC → TE → TP`
**검토자지정** — `POST /elapr-dmnd`
기존 `elaprDmndService.save`.
| 필드 | 값 |
| --- | --- |
| `elaprDocNo` | 재원협의 번호 |
| `elaprCycl` | `1` |
| `docPrgrsSttsComCd` | **`AC`** (현행은 현재 상태 `ER`를 넣고 있음 → 수정) |
| `elaprPrgrsSttsList[].atrzOrdr` | 1 검토자, 2 승인자, 3 최종 |
서버가 실무협의 문서 생성 + RAG 초안 트리거 + 30분 타이머. 응답의 문서번호/`crtDmndUuid`가 있으면 폴링 키로 쓴다. 없으면 `findByUpDocNo`로 복원.
**초안 상태 폴링** — `GET /dcrag-to/documents/draft/status/{crtDmndUuid}`
기존 `getDraftGenerationStatus`. 주기 5~10초. 종료 `COMPLETED`/`FAILED`.
**수동 초안생성** — `POST /dcrag-to/documents/draft/generate` (`TE` 유지)
```json
{
"fnrsCnsltnDocNo": "F-...",
"pwrkCnsltnDocNo": "P-...",
"crtDmndUuid": "optional"
}
```
202 + `DcRagDraftGenerateResponseDto` (`crtDmndUuid`, `crtSttsComCd`, `estimatedMinutes`).
v1.0 가이드의 “이 API를 프론트가 치면 안 된다”는 **폐기**. 1차 트리거는 검토자지정이고, 이 API는 Fallback 전용.
**실무 저장** — `POST /pwrk-cnsltn-mng/save-apply` → `string`.
**보완요청/완료** — fnrs `reqsupplement` / `submitsupplement`.
**결재** — `PUT /elapr-prgrs-stts/{elaprPrgrsId}/process`
```json
{
"atrzPrgrsSttsComCd": "ATRZ_PRGRS_003",
"atrzOpnnCn": "의견",
"finalApprovalYn": false
}
```
반려: `ATRZ_PRGRS_004`. 기존 `elaprPrgrsSttsService.process`. 최종 시 서버가 `TP`/`RR` 전이.
### 3-5. `TP → RM → RB → RA`
**환경청 1차 회신** — `tech-review` (`TP→RM`).
**광역 지자체회신** — `updatePrgrsStts` `RB`.
**조치완료 (신규)** — `POST /pwrk-cnsltn-mng/{pwrkDocNo}/submit-actn-result`
```json
{
"isSubmit": true,
"actnList": [
{
"rvwOpnnSn": 1,
"actnRsltCn": "수용 — 관로 연장 재산정",
"atchFileGroupId": "optional"
}
],
"totActnSummary": "제출 시 권장",
"muniDocNo": "제출 시 권장"
}
```
- `isSubmit: false` → `RB` 유지 (API만 존재, **화면 버튼 없음**. HWP·첨부는 실무협의서 관리 다이얼로그에서 저장)
- `isSubmit: true` → `RB→RA` (조치완료)
응답: `string` (pwrkDocNo). DTO명 `PwrkActnResultSubmitDto`.
### 3-6. `RA → AV → EV → RK`
**2차 의뢰 (신규)** — `POST /fnrs-cnsltn-mng/{docNo}/request-actn-review`
```json
{
"specialRqstCn": "중점 검증 요청 (선택)"
}
```
`RA→AV`. 응답: `string` (docNo). DTO명 `EnvoActnReviewReqDto`. `specialRqstCn`만 선택.
금액검증 콜백은 서버 → `AV→EV`.
**2차 검토자지정** — `POST /elapr-dmnd` (`elaprCycl: 2`, `docPrgrsSttsComCd: RK`). 1차 결재선(`findDocPrgrsByDocNo`, cycl=1)을 시드로 편집.
**금액검증 재실행** — `POST /dcrag-to/documents/cost/verify`
```json
{
"fnrsCnsltnDocNo": "F-...",
"pwrkCnsltnDocNo": "P-..."
}
```
202. 기존 `requestCostVerification`. `RK` 유지.
### 3-7. `RK → RR | SL`
보완은 3-4와 동일 API. 팝업만 금액 체크.
결재 `process` 2차 최종 → 서버가 `RR`.
### 3-8. `RR → EP → TA`
둘 다 `updatePrgrsStts`. `TA` 확인은 API 없음.
---
## 4. 웹기안기
설계서 기준 **기존**. 구현 시 컨트롤러 존재 여부를 확인한다.
| ID | 용도 | URI | 응답 |
| --- | --- | --- | --- |
| W1 | 웹기안기 Open | `GET .../pwrk-cnsltn-doc-crt-rslt/{crtDmndUuid}/webhwp/open` | `inline` HWPX blob → `HwpCtrl.Open(File)` |
| W2 | 편집 저장 | `POST .../pwrk-cnsltn-doc-crt-rslt` multipart `file` + `crtDmndUuid` | 201, `verSn+1` |
| W3 | PC 저장 | `GET .../{crtDmndUuid}/download` | `attachment` blob |
버전 지정: `GET .../{crtDmndUuid}/{verSn}/webhwp/open`, `.../{verSn}/download`.
`/{uuid}/latest`, `/{uuid}/download`가 `/{uuid}/{verSn}`보다 우선. path를 섞지 말 것.
다운로드:
- axios `responseType: "blob"`
- 파일명: `Content-Disposition` `filename*=UTF-8''...` (`parseFilenameFromResponse`)
- 서버 파일명: `재원협의 실무협의서({bizNm})_v{verSn}.hwp`
- Content-Type은 `application/x-hwp` 또는 `application/haansofthwpx`일 수 있음. 타입에 의존하지 말 것
Open은 axios `responseType: "blob"`으로 인증된 API를 호출하고, 응답 Blob을 HWPX `File`로 감싸 `HwpCtrl.Open`에 전달한다. `blob:` Object URL은 사용하지 않는다.
multipart `Content-Type` 헤더를 수동 지정하지 않는다 (boundary). JSON `saveJson`은 UI에서 쓰지 않는다.
---
## 5. 전자결재 (`as-elapr-service`)
| API | URI | FE |
| --- | --- | --- |
| 검토자지정·1차 결재요청 | `POST /elapr-dmnd` | O |
| 결재 처리 | `PUT /elapr-prgrs-stts/{id}/process` | O |
| 결재선 복사 | `POST /elapr-apln/copy-line` | **X (서버)** |
`copy-line` body (참고만):
```json
{
"docNo": "P-20260827-0001",
"sourceElaprCycl": 1,
"targetElaprCycl": 2,
"rgtrUuid": "system-uuid"
}
```
`RK`에서 결재현황은 `findDocPrgrsByDocNo`(전체) 조회 후 `elaprCycl`로 1차/2차 탭 표시.
---
## 6. 프론트 호출 금지
| URI | 이유 |
| --- | --- |
| `POST /dcrag/documents/verify-result` | AI→AS 콜백 |
| `POST /dcrag/draft/complete` | AI→AS 콜백 |
| `POST /dcrag/cost/verify-result` | AI→AS 콜백. 여기서 copy-line도 호출 |
| `POST /elapr-apln/copy-line` | 콜백 Feign |
| `POST /pwrk-cnsltn-mng` (`save` 초안 트리거) | v3.0 1차 트리거는 `elapr-dmnd`. 컨트롤러가 남아 있어도 화면에서 쓰지 않음 |
`POST /dcrag-to/documents/draft/generate`는 **Fallback에서만** 허용.
---
## 7. Gap Analysis (프론트 엔티티)
### 이미 있는 것
`fnrsCnsltnMngService`: `findPage`, `findById`, `save`, `saveApply`, `update`, `techReview`, `submitSupplement`, `submitReqSupplement`, `remove`, `changePrgrsSttsComCd`
`dcRagApiToService`: `requestDocumentTransfer`, `requestDraftGeneration`, `getDraftGenerationStatus`, `requestCostVerification`
`elaprDmndService.save`, `elaprPrgrsSttsService.process`
### 추가할 것
| 메서드 | URI |
| --- | --- |
| `requestExamine` | `POST /fnrs-cnsltn-mng/{id}/request-examine` |
| `findFileVrfcResults` | `GET /fnrs-cnsltn-mng/{id}/file-vrfc-results` |
| `requestActnReview` | `POST /fnrs-cnsltn-mng/{id}/request-actn-review` |
| `pwrkCnsltnMngService.*` | 슬라이스 신규 |
| `submitActnResult` | `POST /pwrk-cnsltn-mng/{id}/submit-actn-result` |
| `pwrkCnsltnDocCrtRsltService.*` | 슬라이스 신규 |
`copyLine`은 프론트 서비스에 넣지 않는다.
@@ -0,0 +1,350 @@
# 레퍼런스 — 프론트 엔티티·DTO
> 상위: [개발가이드.md](./개발가이드.md)
> 엔티티 규칙: `frontend/.cursor/skills/backend-controller-to-entity`
---
## 1. ENDPOINT
`apps/as/src/shared/config/api.ts`
```ts
AS_SERVICE: {
// 기존
FNRS_CNSLTN_MNG: "/as-service/api/v1/fnrs-cnsltn-mng",
DCRAG_TO: "/as-service/api/v1/dcrag-to",
// 추가
PWRK_CNSLTN_MNG: "/as-service/api/v1/pwrk-cnsltn-mng",
PWRK_CNSLTN_DOC_CRT_RSLT: "/as-service/api/v1/pwrk-cnsltn-doc-crt-rslt",
}
AS_ELAPR_SERVICE: {
ELAPR_TMPLT: "/as-elapr-service/api/v1/elapr-tmplt",
ELAPR_APLN: "/as-elapr-service/api/v1/elapr-apln",
ELAPR_DMND: "/as-elapr-service/api/v1/elapr-dmnd",
ELAPR_PRGRS_STTS: "/as-elapr-service/api/v1/elapr-prgrs-stts",
}
```
`copy-line`은 `ELAPR_APLN` 하위이나 FE에서 호출하지 않음.
---
## 2. 슬라이스 배치
```
entities/fnrs-cnsltn/ # 확장
entities/dcrag-to/ # 구현됨
entities/elapr/ # 구현됨
entities/pwrk-cnsltn-mng/ # 신규
entities/pwrk-cnsltn-doc-crt-rslt/ # 신규
```
```
entities/pwrk-cnsltn-mng/
├── model/
│ ├── pwrk-cnsltn-mng-interface.ts
│ └── pwrk-cnsltn-mng-payload-schema.ts
├── api/
│ ├── pwrk-cnsltn-mng-service.ts
│ └── queries.ts
└── index.ts
```
`submit-actn-result` Request는 zod SSOT (`PwrkActnResultSubmitDto`).
`request-examine` / `request-actn-review`도 fnrs payload-schema에 추가.
라우트:
| 화면 | 경로 |
| --- | --- |
| 재원협의 목록/상세/작성 | 기존 `app/(main)/(with-base-layout)/fnrs-cnsltn/...` |
| 실무협의 목록 | `.../pwrk-cnsltn/page.tsx` (선택) |
| 실무협의 상세 | `.../pwrk-cnsltn/[id]/page.tsx` (선택) |
| 페이지 UI | `pages/fnrs-cnsltn/`, `pages/pwrk-cnsltn/` |
---
## 3. Service 시그니처
`fnrsCnsltnMngService`에 추가:
```ts
requestExamine(docNo: string, body: FnrsExamineRequestDto): Promise<string>;
findFileVrfcResults(fnrsCnsltnDocNo: string): Promise<FnrsCnsltnFileVrfcRsltResponseDto[]>;
requestActnReview(docNo: string, body: EnvoActnReviewReqDto): Promise<string>;
```
실무협의:
```ts
export interface PwrkCnsltnMngService {
findPage(searchDto: PwrkCnsltnMngSearchDto): Promise<PageResponse<PwrkCnsltnMngResponseDto>>;
findById(pwrkCnsltnDocNo: string): Promise<PwrkCnsltnMngDetResponseDto>;
findByUpDocNo(upDocNo: string): Promise<PwrkCnsltnMngDetResponseDto>;
saveApply(body: PwrkCnsltnApplySaveRequestDto): Promise<string>;
submitActnResult(
pwrkCnsltnDocNo: string,
body: PwrkActnResultSubmitDto,
): Promise<string>;
update(pwrkCnsltnDocNo: string, body: PwrkCnsltnMngUpdateRequestDto): Promise<string>;
remove(pwrkCnsltnDocNo: string): Promise<void>;
changePrgrsSttsComCd(body: DocPrgrsUpdateRequestDto): Promise<void>;
}
```
v1.0의 `save(): PwrkCnsltnMngSaveResponseDto`(초안 트리거)는 화면에서 사용하지 않는다. 컨트롤러가 남아 있으면 엔티티에 넣더라도 UI 연결 금지.
생성결과:
```ts
export interface PwrkCnsltnDocCrtRsltService {
findPage(
searchDto: PwrkCnsltnDocCrtRsltSearchDto,
): Promise<PageResponse<PwrkCnsltnDocCrtRsltResponseDto>>;
findById(crtDmndUuid: string, verSn: number): Promise<PwrkCnsltnDocCrtRsltResponseDto>;
findLatestByCrtDmndUuid(crtDmndUuid: string): Promise<PwrkCnsltnDocCrtRsltResponseDto>;
openWebHwpLatest(crtDmndUuid: string): Promise<AxiosResponse<Blob>>;
download(crtDmndUuid: string, verSn: number): Promise<AxiosResponse<Blob>>;
downloadLatest(crtDmndUuid: string): Promise<AxiosResponse<Blob>>;
saveMultipart(formData: FormData): Promise<PwrkCnsltnDocCrtRsltResponseDto>;
updateMultipart(
crtDmndUuid: string,
verSn: number,
formData: FormData,
): Promise<PwrkCnsltnDocCrtRsltResponseDto>;
remove(crtDmndUuid: string, verSn: number): Promise<void>;
}
```
`webhwp/open`은 인증된 axios 요청으로 Blob을 조회한다:
```ts
async function openWebHwpLatest(crtDmndUuid: string) {
return client.get<Blob>(`${BASE}/${crtDmndUuid}/webhwp/open`, {
responseType: "blob",
});
}
```
응답 Blob은 HWPX `File`로 감싸 `HwpCtrl.Open(file, "HWPX", ...)`에 전달한다. `blob:` Object URL은 사용하지 않는다.
DC RAG TO (구현됨, 시그니처 유지):
```ts
requestDocumentTransfer(body: DcRagDocumentTransferRequestDto): Promise<DcRagCommonResponseDto>;
requestDraftGeneration(body: DcRagDraftGenerateRequestDto): Promise<DcRagDraftGenerateResponseDto>;
getDraftGenerationStatus(crtDmndUuid: string): Promise<DcRagDraftStatusResponseDto>;
requestCostVerification(body: DcRagCostVerifyRequestDto): Promise<DcRagCommonResponseDto>;
```
---
## 4. DTO
타입명 = 백엔드 클래스명. Save/Apply는 zod.
### 4-1. 재원협의 추가
**`FnrsExamineRequestDto`**
| 필드 | 필수 | 값 |
| --- | --- | --- |
| `prgrsSttsComCd` | N | 기본 `FV` |
**`EnvoActnReviewReqDto`**
| 필드 | 필수 |
| --- | --- |
| `specialRqstCn` | N |
**`FnrsCnsltnFileVrfcRsltResponseDto`**: [ref-endpoint.md](./ref-endpoint.md) §3-3.
첨부 검증 배지용으로 `AtflMngClientResponseDto` / `EsntlAtchFileMngTreeResponseDto`에 `vrfcDt`, `vrfcRsltCn`, `vrfcSttsComCd` 확장.
### 4-2. `PwrkActnResultSubmitDto` (zod)
| 필드 | 필수 | 비고 |
| --- | --- | --- |
| `isSubmit` | Y | `false` API만(화면 버튼 없음), `true` 조치완료(`RB→RA`) |
| `actnList` | N | 조치완료 시 선택 |
| `actnList[].rvwOpnnSn` | Y (항목 있을 때) | |
| `actnList[].actnRsltCn` | N | |
| `actnList[].atchFileGroupId` | N | |
| `totActnSummary` | N | 제출 시 권장 |
| `muniDocNo` | N | 제출 시 권장 |
| `pwrkAtchFileGroupId` | N | |
### 4-3. `PwrkCnsltnMng*`
**Search**: `pwrkCnsltnDocNo`, `upDocNo`, `upDocSeComCd`, `prgrsSttsComCd`, `admdstCd`, `envoSeComCd`, `taskSeComCd`, `bizNm`
**DetResponse 중첩**
- `cnsltnList`: 협의내역 (`rvwOpnnSn`, `rvwOpnnClsfComCd`, `cnsltnCn`, `rfltYn`, …)
- `pjtcoAjmtList`: 사업비조정
- `crtDmndList[].crtRslt`: 생성요청 + 최신 결과
- `splmntDmndList`: 보완요청
- `sttsChgHstryList`: 상태변경이력 — `SL` 복귀 라벨에 사용
- `trsmFileList`: 전송파일 (Java Det DTO 확인 후 반영)
마스터 조인: `bizNm`, `admdstCd`, `envoSeComCd`, `taskSeComCd`, `aplcntNm` 등.
`crtRslt.orgnlOtptDocCn`은 항상 `null`.
**상세 예**
```json
{
"pwrkCnsltnDocNo": "P-20260827-0001",
"upDocNo": "F-20260824-0001",
"upDocSeComCd": "FNRS",
"prgrsSttsComCd": "TE",
"cnsltnList": [],
"pjtcoAjmtList": [],
"crtDmndList": [
{
"crtDmndUuid": "d0545bef-735f-4d7b-a781-88e96e03577a",
"pwrkCnsltnDocNo": "P-20260827-0001",
"rqstrUuid": "...",
"rqstrNm": "관리자",
"crtSttsComCd": "C",
"crtRslt": {
"crtDmndUuid": "d0545bef-735f-4d7b-a781-88e96e03577a",
"verSn": 1,
"rgtrNm": "관리자",
"orgnlOtptDocCn": null,
"crtCmptnDt": "2026-08-27 10:47:01"
}
}
],
"splmntDmndList": [],
"sttsChgHstryList": []
}
```
### 4-4. `PwrkCnsltnDocCrtRslt*`
복합 PK: `crtDmndUuid` + `verSn`
**Response**
| 필드 | 타입 | 비고 |
| --- | --- | --- |
| `crtDmndUuid` | `string` | |
| `verSn` | `number` | |
| `rgtrUuid` / `rgtrNm` | `string` | |
| `orgnlOtptDocCn` | `null` | 목록/상세 미포함 |
| `crtCmptnDt` | `string` | |
**Search** (`PageableParams`): `crtDmndUuid`(이력 조회 시 필수), `pwrkCnsltnDocNo`, `verSn`, `rgtrUuid`
```http
GET /as-service/api/v1/pwrk-cnsltn-doc-crt-rslt?page=0&size=10&crtDmndUuid={uuid}&sort=verSn,desc
```
**Save (zod)**: `crtDmndUuid` 필수. `rgtrUuid` 생략 시 서버 로그인 사용자. `file`은 multipart part (DTO 필드 아님).
### 4-5. DC RAG (구현됨)
```ts
interface DcRagDocumentTransferRequestDto {
fnrsCnsltnDocNo: string;
taskSeComCd?: string;
taskSeCdNm?: string;
}
interface DcRagDraftStatusResponseDto {
crtDmndUuid: string;
status: DraftStatus;
statusName?: string;
progressPercent?: number;
events?: EventInfoDto[];
startedDt?: string;
estimatedCompletionDt?: string;
errorMessage?: string | null;
}
type DraftStatus =
| "REQUESTED"
| "DOWNLOADING"
| "ANALYZING"
| "GENERATING"
| "COMPLETED"
| "FAILED";
```
`estimatedMinutes`는 초안 응답에 있을 수 있으나 UX 안내는 **30분 Fallback**을 따른다.
---
## 5. 폴링 훅
초안 (`AC` 또는 `TE`이면서 생성 중):
```ts
useQuery({
queryKey: [...dcragToKeys.draftStatus(crtDmndUuid)],
queryFn: () => dcRagApiToService.getDraftGenerationStatus(crtDmndUuid),
enabled: Boolean(crtDmndUuid) && isPolling,
refetchInterval: (query) => {
const status = query.state.data?.status;
if (status === "COMPLETED" || status === "FAILED") return false;
return 5_000;
},
});
```
`COMPLETED` 시 `fnrs-cnsltn` 상세·`pwrk-cnsltn-mng` `findByUpDocNo` invalidate.
`FV`/`AV`는 `findById`를 5~10초 refetch. `prgrsSttsComCd`가 `ER`/`RK`가 되면 중단. 시작 시각 기준 30분 경과 안내 문구.
`crtDmndUuid` 복원: `findByUpDocNo(fnrsCnsltnDocNo).crtDmndList[0]`.
---
## 6. 다운로드
```ts
const response = await client.get<Blob>(url, { responseType: "blob" });
const filename = parseFilenameFromResponse(response);
const objectUrl = window.URL.createObjectURL(response.data);
```
기존 `attachService`와 동일.
---
## 7. 실무협의 목록 컬럼 (선택 화면)
| 표시명 | Field |
| --- | --- |
| 실무협의번호 | `pwrkCnsltnDocNo` |
| 재원협의번호 | `upDocNo` |
| 진행상태 | `prgrsSttsComCdNm` |
| 사업명 | `bizNm` |
| 시도/구군 | `sido` / `gugun` |
| 신청자 | `aplcntNm` |
| 등록일 | `regDt` |
행 클릭 → `/pwrk-cnsltn/{pwrkCnsltnDocNo}` 또는 재원협의 상세로 이동 (화면설계 확정 후).
---
## 8. `elapr-dmnd` 저장 시 주의
현행 `floating-action-buttons.tsx`:
```ts
elaprCycl: data.detDto?.prgrsSttsComCd === "RK" ? 2 : 1,
docPrgrsSttsComCd: data.detDto?.prgrsSttsComCd, // ER
```
To-Be:
- 검토자지정은 **`ER`(1차)** 과 **`EV`(2차)** 에서.
- `ER`: `elaprCycl: 1`, `docPrgrsSttsComCd: "AC"`, 서식 선택 다이얼로그
- `EV`: `elaprCycl: 2`, `docPrgrsSttsComCd: "RK"`, 1차 결재선 시드 다이얼로그(서식 없음)
`RK` / ATRZ02 FAB: `findDocPrgrsByDocNo` 전체 조회 후 pending은 `elaprCycl === 2`만 사용. 검토완료 후 `ElaprApprovalDialog`에 `elaprCycl={2}`. 보완요청은 TE와 동일 `SplmntDmndDialog`.
@@ -0,0 +1,246 @@
# 레퍼런스 — 프로세스·상태 전이
> 상위: [개발가이드.md](./개발가이드.md)
> SoT: `03.재원협의_실무협의_프로세스_통합_v완결.md` (v3.0, 2026-09-03)
---
## 1. 프로세스 개요
| 항목 | 내용 |
| --- | --- |
| Process No. | PR-AS-003 |
| 메뉴 | 행정지원 > 2.2.2 재원협의 > 2.2.2.1 재원협의 관리 |
| 목적 | 기초 → 광역(경유) → 환경청(승인) → 공단(기술검토/AI) 4자 협의로 사업규모·국비·분담금을 확정 |
2-Pass:
- **Pass 1** 기술 타당성: `SV→ST→LE→FV→ER→AC→TE→TP→RM→RB`
- **Pass 2** 조치결과·금액: `RB→RA→AV→EV→RK→RR→EP→TA`
자체종결(기술검토 생략): `LE→EP→TA`
---
## 2. 4-Lane 시퀀스
```mermaid
sequenceDiagram
autonumber
actor 기초 as 기초 (ROLE_USER05)
actor 광역 as 광역 (ROLE_USER04)
actor 환경청 as 환경청 (ROLE_USER03)
actor 공단 as 공단 (ROLE_USER01)
actor AI as AI 엔진
rect rgb(240, 248, 255)
기초->>기초: [저장] SV
기초->>광역: [신청완료] ST
광역->>환경청: [환경청제출] LE
end
rect rgb(255, 250, 240)
alt 자체종결
환경청->>광역: [결과회신] LE → EP
광역->>기초: [결과회신] EP → TA
else 기술검토 의뢰
환경청->>AI: [기술검토 의뢰] LE → FV
end
end
rect rgb(245, 255, 245)
AI-->>공단: 파일검증 콜백 FV → ER
Note over 공단: 30분 미응답 시 ER + 수동 [파일검증]
alt 파일 미비
공단->>기초: [파일보완] ER → SL
기초->>공단: [파일보완완료] SL → ER
else 적격
공단->>AI: [검토자지정] ER → AC
end
end
rect rgb(255, 245, 245)
AI-->>공단: 초안 콜백 AC → TE
Note over 공단: 30분 미응답 시 TE + 수동 [실무협의서생성]
alt 설계 미비
공단->>기초: [보완요청] TE → SL
기초->>공단: [보완완료] SL → TE
else 검토 완료
공단->>공단: [검토완료] 상신, [결재(승인)] TE 유지
공단->>환경청: [결재(회신)] TE → TP
end
end
rect rgb(250, 240, 255)
환경청->>광역: [재원협의 결과 회신] TP → RM
광역->>기초: [지자체회신] RM → RB
기초->>환경청: [조치완료] RB → RA
end
rect rgb(240, 255, 255)
광역->>환경청: [조치결과서제출] RC → RA
환경청->>AI: [조치결과 검토의뢰] RA → AV
AI-->>공단: 금액검증 콜백 AV → EV
공단->>공단: [검토자지정] EV → RK
Note over 공단: EV에서 1차 결재선 시드로 2차 결재선 수동 배정
end
rect rgb(255, 255, 230)
alt 소명 미비
공단->>기초: [보완요청] RK → SL
기초->>공단: [보완완료] SL → RK
else 확정
공단->>환경청: [결재(회신)] RK → RR
end
end
rect rgb(255, 240, 240)
환경청->>광역: [결과회신] RR → EP
광역->>기초: [결과회신] EP → TA
end
```
거버넌스:
```
기초 (USER05) --ST--> 광역 (USER04) --LE--> 환경청 (USER03)
기초 <-----TA------ 광역 <-----EP/RM------ 환경청
환경청 --FV/ER--> 공단 (USER01) --TP/RR--> 환경청
```
---
## 3. Activity 정의 (14)
| No. | Activity | 주체 | From → To | FE 포인트 |
| --- | --- | --- | --- | --- |
| 1 | 재원협의 조회 | 기초 | — | 기본계획·자가점검 대조 |
| 2 | 등록 및 제출 | 기초·광역 | `SV→ST`, 광역 `LE` | `save-apply`, `updatePrgrsStts` |
| 3 | 접수 및 의뢰 | 환경청 | `LE→FV` / `EP` | 의뢰 vs 자체종결 분기 |
| 4 | AI 파일검증 | 공단·AI | `FV→ER` / `SL` | 30분 Fallback, 파일보완 팝업 |
| 5 | 자체종결 회신 | 환경청·광역 | `LE→EP→TA` | 공단 레인 없음 |
| 6 | 검토자지정·초안 | 공단·AI | `ER→AC→TE` | `elapr-dmnd`, 초안 폴링 |
| 7 | 1차 기술검토 | 공단 결재선 | `TE` / `SL` | 웹기안기, HWP 파싱은 서버 |
| 8 | 기술검토 회신 | 공단 최종 | `TE→TP` | `process` 최종 |
| 9 | 검토결과 회신 | 환경청·광역 | `TP→RM→RB` | 1차 회신. `EP`와 혼동 금지 |
| 10 | 조치결과 작성 | 기초 | `RB→RA` | `submit-actn-result` `isSubmit:true` (조치완료) |
| 11 | 조치 의뢰 | 환경청 | `RA→AV` | `request-actn-review` |
| 12 | AI 금액검증 | AI·공단 | `AV→EV` | 콜백/Fallback 후 접수자 대기 |
| 12a | 2차 검토자지정 | 공단 접수 | `EV→RK` | `elapr-dmnd` cycl=2 |
| 13 | 2차 검토·결재 | 공단 | `RK→RR` / `SL` | 2차 결재선 |
| 14 | 최종 회신 | 환경청·광역·기초 | `RR→EP→TA` | 종결 |
---
## 4. `FNRSSTTS` 상세
관리: `tb_cs_lwpo_cd` / `tb_as_fnrs_cnsltn_mng.prgrs_stts_com_cd`
| 코드 | 국문 | 영문 | 화면 주체 | 전이 |
| --- | --- | --- | --- | --- |
| `SV` | 저장 | Save | 기초 작성 | 신규/`SV` → `SV` |
| `ST` | 신청완료 | Submit to Province | 기초→광역 | `SV→ST` |
| `LE` | 환경청 검토 | Local Environment Review | 광역→환경청 | `ST→LE` |
| `FV` | 파일검증 | File Verification | AI | `LE→FV` |
| `ER` | 기술검토 의뢰 | Examine Request | 공단 접수자 | `FV→ER`, `SL→ER` |
| `SL` | 보완요청 | Supplement Loop | 공단→기초 | `ER\|TE\|RK → SL` |
| `AC` | 초안생성 | AI Auto Creation | AI | `ER→AC` |
| `TE` | 기술검토 | Technical Examine | 공단 1차 결재 | `AC→TE`, `SL→TE` |
| `TP` | 기술검토 회신 | Technical Pass to Basin | 공단→환경청 | `TE→TP` |
| `RM` | 재원협의결과회신 | Result Message to Province | 환경청→광역 | `TP→RM` |
| `RB` | 재원협의결과회신(지자체) | Result Back to Municipality | 광역→기초 | `RM→RB` |
| `RC` | 조치결과서 제출 | Result Complete | 기초→광역 | `RB→RC` |
| `RA` | 조치결과서 제출(환경청) | Result Ask to Basin | 기초→환경청 | `RB→RA` |
| `AV` | 금액검증 | Amount Verification | AI | `RA→AV` |
| `EV` | 조치결과검토의뢰 | Examine Verify | 공단 접수자 | `AV→EV` |
| `RK` | 조치결과서검토 | Result Check | 공단 2차 결재 | `EV→RK`, `SL→RK` |
| `RR` | 조치결과서검토 회신 | Result Return to Basin | 공단→환경청 | `RK→RR` |
| `EP` | 검토결과 회신 | Examine Pass to Province | 환경청→광역 | `LE→EP`(자체), `RR→EP`(최종) |
| `TA` | 검토결과 회신(종료) | Technical Approval | 광역→기초 | `EP→TA` |
### 4-1. v2.1 → v3.0 대조 (프론트 폐기 대상)
| 구간 | v2.1 | v3.0 |
| --- | --- | --- |
| 의뢰 직후 파일검증 | `ER` | **`FV` → `ER`** |
| 검토자지정 후 초안 | `EE` → `DV` | **`ER` → `AC` → `TE`** |
| 1차 내부 결재 | `TR` → `TP` | **`TE` 유지 → `TP`** |
| 환경청→광역 1차 회신 | `EP` | **`RM`** |
| 금액검증 | `RA` | **`RA` → `AV` → `RK`** |
| 공단 2차 회신 | `TP` | **`RR`** |
| 최종 완료 | `TP` / 고시 `TB` | **`TA`** (고시 없음) |
가이드 v1.0 `PWRKSTTS`(`DV`, `AR`, `TR`, `AA` 등)도 동일하게 폐기.
---
## 5. 보완(`SL`) 3루프
복귀 상태는 `tb_as_doc_stts_chg_hstry` 직전 코드. 프론트는 복귀 코드를 요청에 넣지 않고, 라벨만 이력으로 고른다.
```mermaid
stateDiagram-v2
ER --> SL: 파일보완 팝업(파일리스트)
SL --> ER: 파일보완완료
TE --> SL: 보완 검토팝업()
SL --> TE: 보완완료
RK --> SL: 보완 검토팝업(금액)
SL --> RK: 보완완료
```
| 루프 | 팝업 | 요청 | 제출 버튼 |
| --- | --- | --- | --- |
| 파일 무결성 | 파일리스트 + 검증결과 | 공단 접수자 `ER` | [파일보완완료] |
| 1차 기술 | 설계 미달·사유 | 공단 검토자 `TE` | [보완완료] |
| 2차 금액 | 공종별 금액 체크 | 공단 검토자 `RK` | [보완완료] |
---
## 6. AI 3파이프라인·30분 Fallback
| ID | 단계 | 진입 → 완료 | 프론트 진입 | Fallback | 수동 재실행 |
| --- | --- | --- | --- | --- | --- |
| AI-1 | 파일 무결성 | `FV→ER` | 환경청 [기술검토 의뢰] | 30분 → `ER` + [파일검증] | `POST /dcrag-to/documents/transfer` |
| AI-2 | 초안 생성 | `AC→TE` | 공단 [검토자지정] | 30분 → `TE` + [실무협의서생성] | `POST /dcrag-to/documents/draft/generate` |
| AI-3 | 금액 검증 | `AV→EV` | 환경청 [조치결과 검토의뢰] | 30분 → `EV` + 수동 [금액검증] | `POST /dcrag-to/documents/cost/verify` |
- 예상 소요 안내는 **30분** (v1.0의 10분은 폐기).
- 콜백 수신·스케줄러 전이는 서버. FE는 상세 refetch / draft status 폴링만.
- `AC→TE` 성공 시에만 [실무협의서관리]·[검토결과조회] 활성. 실패·타임아웃이면 [실무협의서생성].
초안 폴링 이벤트 예:
| `eventType` | `eventMessage` |
| --- | --- |
| `REQUESTED` | 요청을 접수했습니다. |
| `DOWNLOADING` | 신청서를 수신하는 중입니다. |
| `ANALYZING` | 자료 준비가 완료되었습니다. |
| `GENERATING` | 문서 저장이 완료되었습니다. |
| `COMPLETED` | 문서 생성이 완료되었습니다. |
| `FAILED` | `errorMessage` 표시 |
종료: `status === "COMPLETED" | "FAILED"` 또는 `events`에 해당 `eventType`.
---
## 7. 2차 결재선 (수동 검토자지정)
1. `TE`에서 1차 결재선(`elaprCycl = 1`) 완료.
2. 금액검증 콜백/Fallback → `AV→EV`.
3. 공단 접수자가 `EV`에서 [검토자지정]: 1차 결재선을 시드로 편집 후 `POST /elapr-dmnd` (`elaprCycl: 2`) → `RK`.
4. `copy-line` 자동 복사는 사용하지 않는다.
결재 `process`:
- 상신·중간 승인: 문서 상태 `TE` 또는 `RK` 유지.
- 1차 최종: 서버가 `TE→TP`.
- 2차 최종: 서버가 `RK→RR`.
- 반려: 직전 결재자 복귀. 문서 상태 유지.
---
## 8. 웹기안기
- `TE`/`RK` [실무협의서관리] → `webhwp/open` Blob 조회 후 팝업에서 `HwpCtrl.Open(File)`.
- [검토완료] 시 HWP 파싱·DB 등재는 **서버**. FE는 결재 `process`만.
- 편집본 저장: `POST /pwrk-cnsltn-doc-crt-rslt` multipart. `verSn`은 클라이언트가 보내지 않음.
@@ -0,0 +1,181 @@
# 레퍼런스 — 화면·버튼 매트릭스
> 상위: [개발가이드.md](./개발가이드.md)
> SoT: `03` §4 화면 및 버튼별 상세 상태전이 명세서 (Row 4~42, 38행)
구현 위치: `pages/fnrs-cnsltn/lib/button-config.ts` + `ui/components/floating-action-buttons.tsx`
---
## 1. 화면 구분
| 화면 | 소유 | 라우트 (현행) | 비고 |
| --- | --- | --- | --- |
| 작성화면 | 기초 `ROLE_USER05` | `/fnrs-cnsltn/new`, `/fnrs-cnsltn/{id}/edit` | `SV` |
| 수정화면 | 기초 | `/fnrs-cnsltn/{id}/edit` | `SL` 보완 |
| 상세화면 | 광역·환경청·공단·기초(`RB`/`TA`) | `/fnrs-cnsltn/{id}` | 조회 + 액션 버튼 |
| 자동화 | AI | 버튼 없음 | `FV`/`AC`/`AV` 진행 패널 |
공단 상세는 결재선 구분으로 같은 상태라도 버튼이 다르다.
| `atrzSeComCd` | 역할 |
| --- | --- |
| `ATRZ01` | 접수자 |
| `ATRZ02` | 검토자 |
| `ATRZ03` | 승인자 |
| `ATRZ99` | 최종승인자 |
---
## 2. 38행 매트릭스
API 컬럼은 [ref-endpoint.md](./ref-endpoint.md)와 동일.
| 순번 | 화면 | 권한 | 결재선 | 상태 | 버튼 | 전이 | 다음 담당 | FE 동작 |
| :---: | --- | --- | --- | --- | --- | --- | --- | --- |
| 1 | 작성 | USER05 | - | 빈값, `SV` | 저장 | `SV` | 본인 | `save-apply` `SV` |
| 2 | 작성 | USER05 | - | `SV` | 신청완료 | `ST` | 광역 | `save-apply` `ST` |
| 3 | 작성 | USER05 | - | `SV` | 삭제 | 삭제 | — | `DELETE` |
| 4 | 상세 | USER04 | - | `ST` | 환경청제출 | `LE` | 환경청 | `updatePrgrsStts` |
| 5 | 상세 | USER03 | - | `LE` | 결과회신 | `EP` | 광역 | `tech-review` 자체종결 |
| 6 | 상세 | USER03 | - | `LE` | 기술검토 의뢰 | `FV` | 공단 접수 | **`request-examine`** |
| 7 | 자동화 | AI | - | `FV` | (파일검증) | `ER` | 공단 접수 | FE 호출 없음. 진행 패널 |
| 8 | 상세 | USER01 | 접수자 | `ER` | 파일보완 | `SL` | 기초 | 팝업(파일리스트) → `reqsupplement` |
| 9 | 상세 | USER01 | 접수자 | `ER` | 파일검증 | `ER` | 본인 | `dcrag-to/transfer` 재실행 |
| 10 | 상세 | USER01 | 접수자 | `ER` | 검토자지정 | `AC` | 다음 결재자 | `POST /elapr-dmnd` |
| 11 | 자동화 | AI | - | `AC` | (초안생성) | `TE` | 공단 검토 | FE 호출 없음. 폴링 |
| 12 | 상세 | USER01 | 검토자 | `TE` | 실무협의서관리 | 유지 | — | 웹기안기 Open. **초안 성공 시만** |
| 13 | 상세 | USER01 | 검토자 | `TE` | 검토결과조회 | 유지 | — | 실무협의 상세 |
| 14 | 상세 | USER01 | 검토자 | `TE` | 실무협의서생성 | 유지 | — | **실패/타임아웃/초안 없음** 시 |
| 15 | 상세 | USER01 | 검토자 | `TE` | 저장 | `TE` | — | `pwrk save-apply` |
| 16 | 상세 | USER01 | 검토자 | `TE` | 검토완료 | `TE` | 다음 결재자 | `elapr process` 상신. 반려 시 직전 결재자 |
| 17 | 상세 | USER01 | 검토자 | `TE` | 보완요청 | `SL` | 기초 | 보완 팝업() → `reqsupplement` |
| 18 | 상세 | USER01 | 승인자 | `TE` | 결재(승인) | `TE` | 다음 결재자 | `process` |
| 19 | 상세 | USER01 | 최종승인자 | `TE` | 결재(회신) | `TP` | 환경청 | `process` 최종 |
| 20 | 수정 | USER05 | - | `SL` | 파일보완완료 | `ER` | 공단 접수 | `submitsupplement` (직전=`ER`) |
| 21 | 수정 | USER05 | - | `SL` | 보완완료 | `TE` | 공단 검토 | `submitsupplement` (직전=`TE`) |
| 22 | 수정 | USER05 | - | `SL` | 보완완료 | `RK` | 공단 검토 | `submitsupplement` (직전=`RK`) |
| 23 | 상세 | USER03 | - | `TP` | 재원협의 결과 회신 | `RM` | 광역 | `tech-review` |
| 24 | 상세 | USER04 | - | `RM` | 지자체회신 | `RB` | 기초 | `updatePrgrsStts` |
| 25 | 상세 | USER05 | - | `RB` | 실무협의서 관리 | 유지 | — | 웹기안기 Open |
| 26 | 상세 | USER05 | - | `RB` | 조치완료 | `RA` | 환경청 | **`submit-actn-result` `isSubmit:true`** |
| 27 | 상세 | USER04 | - | `RC` | 조치결과서제출 | `RA` | 환경청 | `updatePrgrsStts` |
| 28 | 상세 | USER03 | - | `RA` | 실무협의서 관리 | 유지 | — | 웹기안기 Open. **저장 불가** |
| 28a | 상세 | USER03 | - | `RA` | 조치결과 검토의뢰 | `AV` | 공단 검토 | **`request-actn-review`** |
| 29 | 자동화 | AI | - | `AV` | (금액검증) | `EV` | 공단 접수 | FE 호출 없음. 진행 패널 |
| 29a | 상세 | USER01 | 접수자 | `EV` | 검토자지정 | `RK` | 공단 검토 | `POST /elapr-dmnd` cycl=2. 1차 결재선 시드 |
| 30 | 상세 | USER01 | 검토자 | `RK` | 실무협의서관리 | 유지 | — | 웹기안기 |
| 31 | 상세 | USER01 | 검토자 | `RK` | 금액검증 | `RK` | — | `dcrag-to/cost/verify` |
| 32 | 상세 | USER01 | 검토자 | `RK` | 저장 | `RK` | — | `pwrk save-apply` |
| 33 | 상세 | USER01 | 검토자 | `RK` | 검토완료 | `RK` | 다음 결재자 | `process` |
| 34 | 상세 | USER01 | 승인자 | `RK` | 결재(승인) | `RK` | 다음 결재자 | `process` |
| 35 | 상세 | USER01 | 최종승인자 | `RK` | 결재(회신) | `RR` | 환경청 | `process` 최종 |
| 36 | 상세 | USER03 | - | `RR` | 실무협의서 관리(조회), 검토결과 회신 | `EP` | 광역 | `tech-review` |
| 37 | 작성/상세 | USER04 | - | `EP` | 결과회신, 실무협의서 관리(조회) | `TA` | 기초 | `updatePrgrsStts` |
| 38 | 상세 | USER05 | - | `TA` | 결과회신, 실무협의서 관리(조회) | — | — | **API 없음. 조회** |
`SL` 20~22행: 버튼은 직전 상태에 따라 **하나만** 노출. 파일 루프면 [파일보완완료], 그 외 [보완완료].
---
## 3. `button-config` 권장 구조
액션 키는 현행 `FNRS_CNSLTN_VIEW_BUTTON_ACTION`을 확장한다. 신규·이름 변경:
| 신규/변경 액션 | 라벨 | 비고 |
| --- | --- | --- |
| `fileSplmnt` | 파일보완 | `ER` 접수자. 현행에 없음 |
| `fileVrfc` | 파일검증 | 유지. `ER` 재실행 |
| `dsgntRvwr` | 검토자지정 | `ER→AC`(1차), `EV→RK`(2차) |
| `pwrkCnsltnDocMng` | 실무협의서관리 | 유지. `TE`·`RK`·`RB`·`RA`(조회 전용) |
| `pwrkCnsltnDocCrt` | 실무협의서생성 | 유지. 실패/타임아웃만 |
| `rvwRsltInq` | 검토결과조회 | 신규 |
| `actnCmptn` | 조치완료 | `RB→RA`. `isSubmit:true` |
| `actnSbmsn` | 조치결과서제출 | 광역 `RC→RA` |
| `rqstActnRvw` | 조치결과 검토의뢰 | 환경청 `RA→AV` |
| `costVrfc` | 금액검증 | `RK` |
| `lclRply` | 지자체회신 | 광역 `RM→RB` |
| `fnrsRsltRply` | 재원협의 결과 회신 | 환경청 `TP→RM` |
| `rsltRply` | 결과회신 | `LE→EP`, `RR→EP`, `EP→TA`, `TA` 조회 |
| `fileSplmntCmptn` | 파일보완완료 | `SL←ER` |
| `splmntCmptn` | 보완완료 | `SL←TE\|RK` |
**삭제**: `fnrsCnsltnAncmnt`(고시→`TB`), `sncnAprv`(인가승인). `EP`/`TA`는 `rsltRply`로 통일.
### 3-1. 역할 × 상태 (공단 제외)
```
ROLE_USER05
"" | SV → 저장, 신청완료, 삭제
SL → (직전 ER) 파일보완완료 | (직전 TE|RK) 보완완료
RB → 실무협의서 관리, 조치완료
TA → 결과회신 (조회), 실무협의서 관리(조회)
ROLE_USER04
ST → 환경청제출 // 현행 반려(rjct→SV)는 SoT 38행에 없음. 유지 시 별도 합의
RM → 지자체회신
RC → 조치결과서제출
EP → 결과회신, 실무협의서 관리(조회)
ROLE_USER03
LE → 결과회신(자체종결), 기술검토 의뢰
TP → 재원협의 결과 회신
RA → 실무협의서 관리(조회), 조치결과 검토의뢰
RR → 실무협의서 관리(조회), 검토결과 회신 (`tech-review` → `EP`)
```
### 3-2. 공단 결재선 × 상태
```
ER / ATRZ01 접수자
→ 파일보완, 파일검증, 검토자지정
EV / ATRZ01 접수자
→ 검토자지정 (2차 결재선. 1차 결재선 시드, 서식 선택 없음)
TE / ATRZ02 검토자
→ (초안 성공) 실무협의서관리, 검토결과조회, 저장, 검토완료, 보완요청
→ (초안 실패·타임아웃) 실무협의서생성 (+ 위 항목 중 관리/조회는 초안 생긴 뒤)
TE / ATRZ03 승인자 → 결재(승인)
TE / ATRZ99 최종 → 결재(회신)
RK / ATRZ02 검토자
→ (초안 완료) 실무협의서관리
→ (초안 완료 + 결재 대기 ATRZ_PRGRS_002, cycl2) 보완요청, 검토완료
· 보완요청 UI: TE와 동일 SplmntDmndDialog
RK / ATRZ03 → (초안 완료) 실무협의서관리, (cycl2 pending) 결재(승인)
RK / ATRZ99 → (초안 완료) 실무협의서관리, (cycl2 pending) 결재(회신)
· 결재 UI: ElaprApprovalDialog (elaprCycl=2) 승인/반려 → PUT process
```
`FV`, `AC`, `AV`: 액션 빈 배열 + 진행 패널.
`PENDING_APPROVAL_ACTIONS`: `dmndSplmnt`, `rvwCmptn`, `atrzAprv`, `atrzRply`만.
`pwrkCnsltnDocMng`는 결재 대기와 무관(초안 완료만). ATRZ02·ATRZ03·ATRZ99라도 pending 없으면 관리만 노출.
---
## 4. 초안 성공 vs 실패 버튼
`TE`에서 `crtDmndList[].crtSttsComCd` / 폴링 `status`로 분기.
| 조건 | 노출 |
| --- | --- |
| `C` / `COMPLETED` | 실무협의서관리, 검토결과조회, 저장, 검토완료, 보완요청 |
| `F` / `FAILED` 또는 30분 Fallback 후 초안 없음 | 실무협의서생성 |
| `R`/`I` 생성 중 | 진행 패널. 위 버튼 비활성 (`AC`와 동일 UX, 상태가 이미 `TE`면 패널+생성 버튼) |
`RK`는 금액검증 성공이 기본. Fallback 후 [금액검증] 재실행만 추가 노출.
---
## 5. 현행 `button-config.ts`와의 차이
| 항목 | 현재 | To-Be |
| --- | --- | --- |
| USER05 | `""/SV/TA(고시)` | `SL`, `RB` 추가. `TA`는 조회 |
| USER04 | `ST`(제출+반려), `EP`(인가승인) | `RM/RC/EP` 추가. 인가승인 삭제 |
| USER03 | `LE`, `TP`(→EP로 회신) | `RA`, `RR` 추가. `TP`는 `RM` |
| USER01 | `ER`(파일검증, 검토자지정), `TE` | `ER`에 파일보완. `RK` 전면 추가 |
| USER01 ATRZ | `ER`, `TE`만 `needsRoleUser01AtrzResolve` | `RK` 포함 |
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,674 @@
# dmbpRegist.jsp → React 마이그레이션 분석·구현 가이드
| 항목 | 내용 |
| ----------- | ------------------------------------------------------ |
| 원본 JSP | `adssNewOld/.../fnrsc/dmbp/dmbpRegist.jsp` |
| 대상 앱 | `frontend/apps/as` |
| 도메인 | 하수도기본계획 (구: 기본계획검토 / dmbp) |
| API 엔티티 | `@/entities/sewer-bsc-plan` (`SewerBscPlanController`) |
| 참조 패턴 | `@/pages/fnrs-cnsltn` + `@/widgets/pbadms-sprt` |
| 문서 목적 | contents 영역 **섹션별** UI·상태·API 매핑 및 구현 방향 |
| 작성 기준일 | 2026-07-27 |
---
## 1. 마이그레이션 범위
### 1-1. 포함 (contents만)
JSP `568~1274`행: `<div class="contents">` ~ `<!-- //contents -->`
| 영역 | JSP 식별 | 개요 |
| ---- | ---------------------------------- | --------------------------------------------------------------- |
| A | `gTitle1` | 페이지 타이틀·브레드크럼 |
| B | `slide_10` | 기본계획변경 신청(마스터·연도·개요) |
| C | `slide_15` | 신청자·설계자 정보 |
| D | `slide_19` | 개인정보 동의 |
| E | `slide_11` | 사업개요(단계별 인구·보급률) |
| F | `slide_12` | 총사업비 — `BizCstMatrixFormSection` 전용 |
| G | `slide_13` | 재원분담 |
| H | `slide_14` | 처리시설별 하수도정비기본계획 (Checkbox + Tabs) |
| I | `slide_16` | 체크리스트 + 필수첨부 + 기타첨부 |
| J | JSP 상단 `saveBtn` / `presentnBtn` | React: 폼 하단 액션바 (`fnrs-form-page` 279~323과 동일 구성, API만 sewer) |
### 1-2. 제외
- `<%@ include %>`: top / sideMenu / footer / `bscPlnPopup.jsp` / `sndrdBzAmnt.jsp`
- 레이아웃·메뉴·권한 셸 → 기존 `BaseLayout` / `PageLayout` / AUTH 체계
- `mStep1` 진행 단계 표시 (미구현 · 마이그레이션 범위 밖)
팝업(`이전기본계획조회`)은 **별도 Dialog 컴포넌트**로 재구현하며, include JSP 자체는 포팅하지 않는다.
---
## 2. 목표 아키텍처
```
app/(with-base-layout)/sewer-bsc-plan/regist/page.tsx
└─ pages/sewer-bsc-plan/ui/sewer-bsc-plan-regist-page.tsx
└─ sewer-bsc-plan-form-page.tsx # FormProvider + 섹션 조립
├─ sections/*-form-section.tsx # 도메인 전용
└─ widgets/pbadms-sprt/* # 공통 재사용
entities/sewer-bsc-plan/ # 이미 구현됨
saveApply / findDetails / submitSupplement …
```
**폼 스택 (fnrs-cnsltn과 동일)**
- `react-hook-form` + `zod` (`zodResolver`, `mode: "onChange"`)
- 섹션 래퍼: `SectionCollapsible` (Accordion 아님)
- UI: `@common/components` (Input, Select, Textarea, Button, Radio, Tabs, Table 등)
- 그리드가 필요한 곳만 `@tanstack/react-table` + `DataTable`
- 데이터: React Query (`useSaveApplySewerBscPlan` 등) — 목데이터는 API 미연동 구간만 `@faker-js/faker`
**Vercel React Best Practices (적용 요약)**
- `client-swr-dedup`: React Query로 체크리스트/필수첨부/코드 조회 중복 제거
- `bundle-dynamic-imports`: 처리시설 Tabs 패널·이전계획 Dialog는 `next/dynamic` 후보
- `rerender-derived-state`: 단계 연도·합계·진행률은 render 중 파생, 불필요 effect 금지
- `async-parallel`: 등록 진입 시 코드/체크리스트트리/필수첨부트리를 병렬 조회
---
## 3. 전체 레이아웃
`fnrs-form-page.tsx`와 동일한 **FormProvider + 세로 섹션 스택** 구조를 따르고,
하단 액션바는 **[`fnrs-form-page.tsx` 279~323](../../src/pages/fnrs-cnsltn/ui/fnrs-form-page.tsx)** 과 동일 구성(목록·저장·신청완료·삭제·보완완료)이며 **API/라우트만 sewer** 로 바꾼다.
타이틀·브레드크럼은 폼 밖(`PageLayout` / regist·edit·view 셸)에서 처리한다.
(상세 View의 sticky FAB·검토/결재 버튼은 본 등록 문서 범위 밖 — `fnrs-view-page` 대응 후속.)
### 3-1. 컴포넌트 트리 (fnrs 대응)
```
PageLayout (title / breadcrumb)
└─ SewerBscPlanRegistPage | SewerBscPlanEditPage | SewerBscPlanViewPage
└─ SewerBscPlanFormPage | SewerBscPlanViewPage 본문
FormProvider (등록/수정) / 읽기 섹션 (상세)
└─ <form|div className="mt-6 space-y-4">
├─ BasicInfoFormSection // JSP slide_10
├─ ContactInfoFormSection // JSP slide_15 (pbadms-sprt)
├─ PrivacyConsentSection // JSP slide_19 (pbadms-sprt, 등록·수정)
├─ OutlineFormSection // JSP slide_11 (사업개요, 신규)
├─ BizCstMatrixFormSection // JSP slide_12 (총사업비 전용, 신규)
├─ FnrsCstFormSection // JSP slide_13 (재원분담, 신규 ※ FnrsShar 아님)
├─ TmplntFormSection // JSP slide_14 (처리시설, Tabs로 시설별 패널)
├─ ChecklistFormSection // JSP slide_16 (pbadms-sprt)
├─ AttachmentsFormSection // JSP 필수·기타첨부 (pbadms-sprt)
├─ SplmntDmndFormSection // edit + SL 상태만 (pbadms-sprt)
└─ form footer action bar // fnrs-form-page 279~323 동일
// [목록] / [저장] / edit시 [신청완료][삭제] / SL시 [보완완료]
```
**폼 하단 액션바 버튼 구성**
기준: [`fnrs-form-page.tsx` 279~323](../../src/pages/fnrs-cnsltn/ui/fnrs-form-page.tsx). UI·분기만 동일하고 훅/라우트는 sewer.
| 순서 | 버튼 | 조건 | sewer 비고 |
| ---- | -------- | ----------------------------------------- | ---------------------------------------------------- |
| 1 | 목록 | 항상 | `router.push("/sewer-bsc-plan")` |
| 2 | 저장 | `!isSplmntPrgrsStts` | `type="submit"` → `saveApply` / 임시저장(SV) |
| 3 | 신청완료 | `!isSplmntPrgrsStts && isEditMode` | 체크리스트+필수첨부 검증 → `saveApply` / LE |
| 4 | 삭제 | `!isSplmntPrgrsStts && isEditMode` | confirm → `delete` → 목록 |
| 5 | 보완완료 | `isSplmntPrgrsStts` (`prgrsSttsComCd=SL`) | `submitSupplement` (fnrs `onSplmntCmptn` 대응) |
**fnrs와의 차이 (섹션 치환만, 골격 동일)**
| fnrs-form-page | sewer-bsc-plan |
| ---------------------------------------------- | ------------------------------------------------------ |
| `BasicInfoFormSection` | 동일 역할 (마스터·연도·개요 필드는 sewer DTO) |
| `ContactInfoFormSection` | 동일 (`fieldPrefix="sewerBscPlanDtl"`) |
| `PrivacyConsentSection` | 동일 |
| `BusinessScaleFormSection` | → `OutlineFormSection` (단계별 인구·보급률) |
| `BusinessCostFormSection` | → `BizCstMatrixFormSection` (단계×원가 계층 전용) |
| `FnrsSharFormSection` | → `FnrsCstFormSection` (국고·지방비·원인자·기타) |
| _(없음)_ | `TmplntFormSection` (체크박스 + Tabs 시설별 매트릭스) |
| `ChecklistFormSection` `docSeComCd="FNRS"` | `docSeComCd="SEWER"` (TBD) |
| `AttachmentsFormSection` | 동일 패턴 |
| `SplmntDmndFormSection` | 동일 (`readOnly={!isSplmntPrgrsStts}`) |
| 폼 하단 액션바 (목록·저장·신청완료·삭제·보완완료) | **동일 구성, API·라우트만 sewer** |
### 3-2. 본문 ASCII (폼 페이지)
```
┌─────────────────────────────────────────────────────────────────┐
│ PageLayout: 하수도기본계획 신청/수정 breadcrumb │
├─────────────────────────────────────────────────────────────────┤
│ FormProvider │
│ <form className="mt-6 space-y-4"> │
│ │
│ ┌─ SectionCollapsible: 기본계획 신청 ─────────────────────┐ │
│ │ BasicInfoFormSection │ │
│ └──────────────────────────────────────────────────────────┘ │
│ ┌─ 신청자 정보 ────────────────────────────────────────────┐ │
│ │ ContactInfoFormSection │ │
│ └──────────────────────────────────────────────────────────┘ │
│ ┌─ 개인정보 동의 ──────────────────────────────────────────┐ │
│ │ PrivacyConsentSection │ │
│ └──────────────────────────────────────────────────────────┘ │
│ ┌─ 사업개요 ────────────── [이전기본계획조회] ─────────────┐ │
│ │ OutlineFormSection │ │
│ └──────────────────────────────────────────────────────────┘ │
│ ┌─ 총사업비 (백만원) ──────────────────────────────────────┐ │
│ │ BizCstMatrixFormSection │ │
│ └──────────────────────────────────────────────────────────┘ │
│ ┌─ 재원분담 (백만원) ──────────────────────────────────────┐ │
│ │ FnrsCstFormSection │ │
│ └──────────────────────────────────────────────────────────┘ │
│ ┌─ 처리시설별 하수도정비기본계획 ──────────────────────────┐ │
│ │ TmplntFormSection │ │
│ │ ├─ BscFctList Checkbox │ │
│ │ └─ Tabs (선택 시설별 TabsTrigger / TabsContent) │ │
│ └──────────────────────────────────────────────────────────┘ │
│ ┌─ 체크리스트 ─────────────────────────────────────────────┐ │
│ │ ChecklistFormSection │ │
│ └──────────────────────────────────────────────────────────┘ │
│ ┌─ 첨부파일 ───────────────────────────────────────────────┐ │
│ │ AttachmentsFormSection │ │
│ └──────────────────────────────────────────────────────────┘ │
│ ┌─ 보완요구 (edit + SL) ───────────────────────────────────┐ │
│ │ SplmntDmndFormSection │ │
│ └──────────────────────────────────────────────────────────┘ │
│ │
│ ┌─ form footer (fnrs-form-page 279~323 동일) ──────────────┐ │
│ │ [목록] [저장] / edit: [신청완료][삭제] / SL: [보완완료] │ │
│ │ ※ API·라우트만 sewer — UI 분기는 fnrs와 동일 │ │
│ └──────────────────────────────────────────────────────────┘ │
│ </form> │
└─────────────────────────────────────────────────────────────────┘
```
### 3-3. 액션바 동작 (`fnrs-form-page` 279~323 동일, API만 sewer)
구현 위치: `sewer-bsc-plan-form-page.tsx` 하단
(`fnrs-form-page.tsx`의 `mx-4 flex flex-wrap justify-center gap-3` 블록을 그대로 옮기고 훅·path만 교체)
| 버튼 | 조건 | 대표 동작 |
| -------- | ---------------------------- | -------------------------------------------------------------------------- |
| 목록 | 항상 | `router.push("/sewer-bsc-plan")` |
| 저장 | `!isSplmntPrgrsStts` | `type="submit"` → `saveApply` + 임시저장(`SV`) |
| 신청완료 | edit && `!isSplmntPrgrsStts` | 체크리스트 완료 + **필수 첨부 완료** 검증 → `saveApply` + `LE` |
| 삭제 | edit && `!isSplmntPrgrsStts` | confirm → `delete` → 목록 |
| 보완완료 | `isSplmntPrgrsStts` (SL) | `form.handleSubmit` → `useSubmitSupplementSewerBscPlan` |
**신청완료 사전 검증** (fnrs `handleApplyClick`과 동일 정책)
1. **체크리스트**: `isFormChecklistComplete(cklstResultList)` — 미완료 시 `"모든 체크리스트 항목을 체크해야 신청이 가능합니다."`
2. **필수 첨부**: `esntlAtchYn === "Y"`인 필수첨부 슬롯마다 `esntlAtchFileList`에 `atchFileGroupId`가 있어야 함
- Form: `AttachmentsFormSection`의 트리 + 폼 `esntlAtchFileList`
- 미충족 시 예: `"필수 첨부파일을 모두 등록해야 신청이 가능합니다."`
- 헬퍼 후보: `isFormEsntlAtchComplete(requiredTree, esntlAtchFileList)` (`pbadms-sprt`에 추가)
저장에는 위 검증을 적용하지 않는다 (임시저장 허용).
저장/제출 버튼을 섹션 헤더(`gTitle2 gRt`)에 두지 않는다 — **폼 하단 액션바 단일 진입점** (§4-J).
### 3-4. 라우트
| 화면 | path | 셸 → FormPage |
| ---- | --------------------------- | ------------------------------------------ |
| 등록 | `/sewer-bsc-plan/regist` | `mode="create"` |
| 수정 | `/sewer-bsc-plan/[id]/edit` | `mode="edit"` + `useSewerBscPlanDetails` |
| 상세 | `/sewer-bsc-plan/[id]` | ViewPage (본 문서 범위 밖, fnrs-view 대응) |
`docSeComCd` 후보: 백엔드 체크리스트·필수첨부 등록값 확인 후 **`SEWER`** (또는 레거시 `DMBP`) — **TBD, CMS 코드와 맞출 것**.
---
## 4. 섹션별 상세 구현
### 4-0. Hidden / 세션 컨텍스트 (폼 루트)
JSP hidden → React 폼 기본값·세션 스토어로 흡수.
| JSP | 의미 | React |
| ------------------------------- | --------------- | ------------------------------------------------------- |
| `chgSe` / `chgSeSp` / `chgSeCd` | 변경구분 | `sewerBscPlan.sewerBscPlanSeComCd` + 표시용 코드명 |
| `progrsSttus` | SAVE / PRESENTN | 저장·제출 시 `prgrsSttsComCd`로 매핑 (임시저장 vs 제출) |
| `planSeCd` | 고정 `A` | 필요 시 상수 또는 API 필드 확인 |
| `adstDstrCd` / `rgnCd` | 행정구역 | `sewerBscPlan.admdstCd` |
| `sidoNm` / `gugunNm` | 표시용 | 읽기 전용 표시 (`detDto.sido`/`gugun`) |
구현: `getCreateDefaultValues(userInfo)`에서 로그인 사용자·소속 지자체 주입.
---
### 4-A. 타이틀·브레드크럼
| JSP | React |
| ------------------------ | ------------------------------------------------------ |
| `h3` 기본계획검토 | PageLayout title: **하수도기본계획 신청** (IIPBS 명명) |
| 설치인가 및 제원협의 > … | 메뉴 메타 기반 breadcrumb |
별도 섹션 컴포넌트 불필요. 라우트 `page.tsx` / layout metadata로 처리.
---
### 4-B. 기본계획변경 신청 (`slide_10`)
**파일**: `ui/sections/basic-info-form-section.tsx`
**래퍼**: `SectionCollapsible` title=`기본계획 신청`
**필드 접두사**: `sewerBscPlan.*` + `sewerBscPlanDtl.*`
| 표시명 | JSP | API 매핑 | UI | 필수 | 비고 |
| ---------------- | ----------------- | ------------------------------- | ------------------ | ---- | ---------------------------------- |
| 기본계획명 | `drngMtncPlanNm` | `sewerBscPlan.sewerBscPlanNm` | Input | Y | |
| 계획년도 | `planYr` | `sewerBscPlanDtl.planYr` | Select (현재~2005) | Y | |
| 기준년도 | `crtrYr` | `sewerBscPlanDtl.crtrYr` | Select | Y | |
| 1~4단계 목표연도 | `goalYrStep1~4` | `frlvlGoalYr`~`folvlGoalYr` | Select (현재~+30) | Y | 1단계 변경 시 +5/+10/+15 자동 연동 |
| 계획개요 | `bzCn` | `sewerBscPlanDtl.bizOtlnCn` | Textarea | Y | |
| 구분 | `#chgSeNm` | `sewerBscPlanSeComCd` (+코드명) | 읽기 또는 Select | | 신규/변경 등 |
| 신청 지자체 | `${lclgvrnmntNm}` | `admdstCd` | 읽기 전용 | | |
**동작**
- `goalYrStep1` onChange → 2·3·4단계 기본값 세팅 + E/F/G 헤더 연도 span 갱신 (`watch` 파생)
- JSP 상단 `gRt` 저장/제출은 사용하지 않음 → FormPage 하단 액션바 (§3-3, §4-J)
---
### 4-C. 신청자 정보 (`slide_15`)
**재사용**: `@/widgets/pbadms-sprt`의 `ContactInfoFormSection`
**props**: `fieldPrefix="sewerBscPlanDtl"` (또는 dtl 필드 구조에 맞게)
| 표시 | JSP | API |
| ---------------------------- | --------------------------- | --------------------------------------------------------------------------------------- |
| 신청자 이름/전화/부서/이메일 | `${UsrNm}` 등 서버렌더 | 로그인 사용자 읽기 전용 → `aplcntNm`, `aplcntMblTelno`, `aplcntOgdpNm`, `aplcntEmlAddr` |
| 설계자 | `dsgnrNm/Telno/Psitn/Email` | `dsgnrNm`, `dsgnrTelno`, `dsgnrOgdpNm`, `dsgnrEmlAddr` |
신청자 4필드는 세션에서 defaultValues에 채우고 Input `disabled`.
---
### 4-D. 개인정보 동의 (`slide_19`)
**재사용**: `PrivacyConsentSection`
| JSP | React |
| ----------------------------- | ------------------------------------------------------------------ |
| 고지 textarea + 보유기간 문구 | 동일 문구 상수/마크다운 |
| `privacyAgree` Y/N | 폼 필드 `privacyAgree: "Y" \| "N"` (API 미전송, 클라이언트 검증만) |
**검증**: 제출 시 `Y` 필수 (JSP `presentnBtn`과 동일). 저장(임시)은 동의 없이 허용할지 정책 TBD — 기본은 JSP와 같이 **제출만 강제**.
---
### 4-E. 사업개요 (`slide_11`)
**파일**: `ui/sections/outline-form-section.tsx` (신규, 도메인 전용)
**API**: `sewerBscPlanOtlnList: SewerBscPlanOtlnItem[]` (planStpNo 1~4)
| 행(구분) | JSP name | Item 필드 |
| ------------ | --------------- | ------------------- |
| 계획인구 | `arrPlanPpltn` | `sewerPlanPpltnCnt` |
| 처리인구 | `arrPrcsPpltn` | `sewerPrcsPpltnCnt` |
| 하수도보급율 | `arrDrngSplyRt` | `sewerPsplyRt` |
열: 1~4단계 (헤더에 `frlvlGoalYr` 등 표시).
**버튼**: `이전기본계획조회` → Dialog (`PreviousPlanLookupDialog`)
- 레거시: `fnbscPlnPopupToggle` + `bscPlnPopup.jsp`
- React: Modal + 조회 API (**TBD**: 이전 계획 조회 엔드포인트; 없으면 1차는 Dialog UI만 + mock)
숫자 입력: 콤마 제거 후 number 전송 (제출 시 JSP `replaceComma` 대체).
---
### 4-F. 총사업비 (`slide_12`)
**파일**: `ui/sections/biz-cst-matrix-form-section.tsx` (**전용 컴포넌트** — fnrs `BusinessCostFormSection` 재사용 금지)
**래퍼**: `SectionCollapsible` title=`총사업비` (단위 `백만원`은 헤더 우측)
**JSP 현실**: 단계(1~4) × 원가 계층(총사업비, 공사비, 처리시설, 하수관로 신설/보수, 펌프장, 배수설비, 기타, 부대경비, 설계/감리/부대비). 일부 readonly·자동합산 JS.
**신규 API**: `bizCstList: SewerBscPlanBizCstItem[]` = `{ planStpNo, acntgSeCd, cstrnAmt }`
**구현 방향 (`BizCstMatrixFormSection` 전용)**
- 행 = `useAcntgSeMngTree` → `buildAcntgCostItems` (fnrs `BusinessCostFormSection`과 동일 출처)
- `costItems` 로드 시 `useEffect`로 `bizCstList`를 `mergeBizCstList(existing, costItems)`로 동기화
- 열 = `planStpNo` 1~4 (헤더에 목표연도 표시)
- readonly 행(`CostItemDef.readonly=true`)은 children 합산으로 자동계산; Input에 `readOnly` + `bg-muted`
- 변경 시 `setAmt` → `recalculateBizCstMatrix(list, costItems)` → `setValue("bizCstList")`
- 저장 시 섹션 onChange 합산을 신뢰하여 `bizCstList` 그대로 전송 (`toBizCstSaveList` identity)
**표준사업비 조회** 버튼은 JSP에서 주석 처리됨 → **미구현**.
---
### 4-G. 재원분담 (`slide_13`)
**주의**: fnrs의 `FnrsSharFormSection`(재원협의 공유구분 트리)과 **다름**.
| 행 | JSP | `SewerBscPlanFnrsCstItem` |
| ------------ | -------------- | ------------------------- |
| 총사업비 | `arrTotAmnt` | `sumAmt` (또는 파생) |
| 국고 | `arrNlepAmt` | `gvexpAmt` |
| 지방비 | `arrLcepAmt` | `lcexpAmt` |
| 원인자부담금 | `arrCusrAlotm` | `orgprBdchgAmt` |
| 기타 | `arrEtcAmt` | `etcAmt` |
**파일**: `ui/sections/fnrs-cst-form-section.tsx` (신규)
데이터: `fnrsCstList` 길이 4 (`planStpNo` 1~4).
검증(선택): 단계별 `gvexp+lcexp+orgpr+etc === sumAmt` (JSP `calculateTotalFunding` 참고).
---
### 4-H. 처리시설별 하수도정비기본계획 (`slide_14`) — 핵심 복잡도
**JSP 동작**
1. `BscFctList` 체크박스로 처리시설 다중 선택 (`arrBscFctCd`)
2. 선택 시 `createFormSection(code, name)`로 **당초 4단계 | 현재 | 변경 4단계** 매트릭스 동적 삽입
→ **React**: 세로 삽입 대신 `@common/components` `Tabs`로 시설별 패널 관리 (§아래 Tabs 규칙)
3. 활성 `formFields`(축소판): 처리구역면적, 하수처리인구, 계획하수량, 시설용량, 분류식 오수/우수, 합류식, 차집, 배수설비, 오수중계/일반/우수 펌프
4. 시설별 필수첨부 `createFileAttachmentSection`
5. `fetchBasicPlanData`로 당초(이전) 데이터 바인딩
**API 매핑**
| UI | DTO |
| -------------------- | ------------------------------------------------------------- |
| 선택 시설 목록 | `sewerBscPlanTmplntList[].swtrmtFcltCd` (+ `atchFileGroupId`) |
| 단계별 수치 (변경측) | `sewerBscPlanTmplntDtlList[]` → `SewerBscPlanTmplntDtlItem` |
| 임시저장 | `tmplntTmprStrgList` (편집 중 임시, 필요 시) |
필드 대응 (변경 단계 기준):
| UI 라벨 | `SewerBscPlanTmplntDtlItem` |
| -------------- | --------------------------- |
| 처리구역면적 | `prcsZoneArea` |
| 하수처리인구 | `swtrmtPpltnCnt` |
| 계획하수량 | `planSwqty` |
| 시설용량 | `fcltCpct` |
| 분류식 오수 | `sprsysDrtwPplLen` |
| 분류식 우수 | `sprsysExlnPplLen` |
| 합류식 | `cbsysPplLen` |
| 차집관로 | `icptgPplLen` |
| 배수설비 | `drgCnt` |
| 오수 중계 펌프 | `drtwRlyPumpCnt` |
| 오수 일반 펌프 | `drtwPumpCnt` |
| 우수 펌프 | `exlnPumpCnt` |
**구현 구성**
```
ui/sections/tmplnt-form-section.tsx
├─ TmplntFacilityPicker # BscFctList Checkbox 목록 (시설 마스터 API TBD)
└─ Tabs (@common/components Tabs) # 선택 시설별 동적 패널
├─ TabsList / TabsTrigger # value=swtrmtFcltCd, 라벨=시설명
└─ TabsContent (시설 1개당)
├─ TmplntMatrixTable # 당초|현재|변경 매트릭스 (useFieldArray)
└─ TmplntFacilityAttachments # 시설별 필수첨부 (선택)
```
**Tabs 관리 규칙** (`packages/common/components/src/ui/tabs`)
- `BscFctList` 체크 **선택** → `useFieldArray` append + 해당 시설 `TabsTrigger`/`TabsContent` 추가 → `Tabs` `value`를 신규 시설로 전환
- 체크 **해제** → confirm 후 remove + 해당 탭 제거 → 남은 탭 중 하나로 `value` 이동 (없으면 Tabs 영역 비표시)
- 선택 시설이 0개면 Tabs UI 숨김; 1개 이상이면 Tabs로 시설별 패널 전환
- 매트릭스·첨부는 각 `TabsContent` 안에만 렌더 (JSP의 세로 동적 삽입을 탭 패널로 대체)
**매트릭스 열**
- **당초 열**: 이전계획 API 조회 결과 읽기 전용 (없으면 빈 칸)
- **현재 열**: 기준년도 시점 값 (API 제공 시)
- **변경 열**: 편집 가능 → 저장 payload의 dtl만 전송
시설 마스터 목록 API: 레거시 `BscFctList` 대체 — **TBD** (`swtrmtFclt` 계열).
`bundle-dynamic-imports`: `TmplntFormSection`(또는 TabsContent 내부 매트릭스)을 `next/dynamic` 후보.
---
### 4-I. 체크리스트 + 첨부 (`slide_16`)
#### I-1. 체크리스트
**재사용**: `ChecklistFormSection`
`docSeComCd="<SEWER|DMBP TBD>"`
`fieldPrefix`: 마스터에서 `taskSeComCd`를 읽는 경로 (예: `sewerBscPlan`)
| JSP | React |
| ----------------------- | ------------------------------------------- |
| 업무탭 `ceckEssntlArr` | 코드 `taskSeComCd` 다중 → Tabs |
| 진행률 / 전체 예·아니오 | 위젯 내장 로직 |
| `exmntResult` Y/N | `cklstResultList[].selected` (+ `picRvwCn`) |
저장: `cklstResultList: CklstResultItem[]`
#### I-2. 필수 첨부 (탭별)
**재사용**: `AttachmentsFormSection`
`docSeComCd` 동일, `esntlAtchFileList`
레거시: 체크리스트 탭마다 `essntlList` + `uploadFile` multipart.
신규: TUS/`attach-service` + `esntlAtchFileId` / `atchFileGroupId` (fnrs와 동일).
#### I-3. 기타 첨부
`AttachmentsFormSection`의 etc 영역 또는 `atchFileGroupId` on `sewerBscPlanDtl`.
JSP `uploadFileETC` multiple → Zip 안내 문구 유지.
---
### 4-J. 저장 / 제출
**UI 구성**: [`fnrs-form-page.tsx` 279~323](../../src/pages/fnrs-cnsltn/ui/fnrs-form-page.tsx) 과 **동일**.
마크업·분기(`isSplmntPrgrsStts` / `isEditMode`)·버튼 색상·`disabled={isSubmitting}` 패턴을 그대로 두고, **호출 API·목록 path만 sewer** 로 교체한다.
```tsx
<div className="mx-4 flex flex-wrap justify-center gap-3 sm:gap-4">
<Button color="white" type="button" onClick={() => router.push("/sewer-bsc-plan")} disabled={isSubmitting}>
목록
</Button>
{!isSplmntPrgrsStts ? (
<>
<Button type="submit" disabled={isSubmitting}>저장</Button>
{isEditMode && (
<>
<Button color="green" type="button" onClick={handleApplyClick} disabled={isSubmitting}>
신청완료
</Button>
<Button color="red" type="button" onClick={handleDelClick} disabled={isSubmitting}>
삭제
</Button>
</>
)}
</>
) : (
<Button type="button" onClick={form.handleSubmit(onSplmntCmptn)} disabled={isSubmitting}>
보완완료
</Button>
)}
</div>
```
| 버튼 | fnrs 대응 | sewer API / 동작 |
| -------- | ----------------------------- | ------------------------------------------------------------ |
| 목록 | `router.push("/fnrs-cnsltn")` | `router.push("/sewer-bsc-plan")` |
| 저장 | `saveApply` + 임시저장 | `useSaveApplySewerBscPlan` + `prgrsSttsComCd`=임시저장(`SV`) |
| 신청완료 | `handleApplyClick` → 제출 | 체크리스트+필수첨부 검증 → `saveApply` + `LE` (상태코드 TBD) |
| 삭제 | `handleDelClick` | `useDeleteSewerBscPlan`(또는 동등) → 목록 |
| 보완완료 | `onSplmntCmptn` | `useSubmitSupplementSewerBscPlan` |
| JSP | 진행값 | URL | React |
| ---- | ---------- | ------------------------- | ---------------------------------------------------------- |
| 저장 | `SAVE` | `insertFnrscDmbp.do` | `saveApply` + 임시저장 코드 |
| 제출 | `PRESENTN` | `insertFnrscDscss.do` (!) | `saveApply` + 제출 상태코드 — **백엔드 상태코드 확인 TBD** |
페이로드 조립 (`buildApplyPayload`):
```ts
SewerBscPlanApplySaveRequestDto {
sewerBscPlan, sewerBscPlanDtl,
sewerBscPlanOtlnList, bizCstList, fnrsCstList,
sewerBscPlanTmplntList, tmplntTmprStrgList?,
cklstResultList, esntlAtchFileList,
splmntDmndList?, rvwOpnnList? // 등록 화면에서는 보통 빈 배열
}
```
성공 후: `invalidateQueries(sewerBscPlanBaseKey)` → `router.push('/sewer-bsc-plan')` (신청완료는 상세로 보낼 수 있음 — fnrs와 동일 정책).
권한: JSP `AUTH3` → 기존 AS 권한 훅/역할로 버튼 `disabled`/`hidden`.
---
## 5. API / DTO 연결
Base: `/as-service/api/v1/sewer-bsc-plans`
엔티티: `@/entities/sewer-bsc-plan`
| 화면 동작 | Hook / Service | 비고 |
| -------------- | ---------------------------------------- | ---------------- |
| 등록 저장·제출 | `useSaveApplySewerBscPlan` → `saveApply` | 본 문서 핵심 |
| 수정 로드 | `useSewerBscPlanDetails(docNo, chgCycl)` | 편집 시 |
| 마스터만 | `useSewerBscPlan` | 목록 행 클릭 등 |
| 보완 제출 | `useSubmitSupplementSewerBscPlan` | edit + `prgrsSttsComCd=SL` 시 폼 하단 [보완완료] |
| 기술검토 | `useTechReviewSewerBscPlan` | 등록 JSP 범위 밖 |
등록 JSP에 없는 섹션(보완요구·검토의견)은 **상세/검토 화면**에서 `SplmntDmndFormSection` / 검토의견 섹션으로 후속 구현.
---
## 6. 권장 파일 배치
```
apps/as/
├── app/(with-base-layout)/sewer-bsc-plan/
│ └── regist/page.tsx
├── src/pages/sewer-bsc-plan/
│ ├── lib/
│ │ ├── sewer-bsc-plan-regist-schema.ts # zod
│ │ └── form-data-mapper.ts # Det ↔ Form, Apply payload
│ ├── model/
│ │ └── (필요 시 table columns)
│ └── ui/
│ ├── sewer-bsc-plan-regist-page.tsx
│ ├── sewer-bsc-plan-form-page.tsx
│ ├── components/
│ │ └── previous-plan-lookup-dialog.tsx
│ └── sections/
│ ├── basic-info-form-section.tsx
│ ├── outline-form-section.tsx # 사업개요
│ ├── biz-cst-matrix-form-section.tsx # 총사업비 (전용)
│ ├── fnrs-cst-form-section.tsx # 재원분담
│ └── tmplnt-form-section.tsx # 처리시설 (Checkbox + Tabs)
└── docs/sewer-bsc-plan/
└── dmbp-regist-migration.md # 본 문서
```
공통 재사용 (신규 작성 최소화):
- `ContactInfoFormSection`, `PrivacyConsentSection`
- `ChecklistFormSection`, `AttachmentsFormSection`
- `SectionCollapsible`
- `Tabs` / `TabsList` / `TabsTrigger` / `TabsContent` (`@common/components` — 처리시설 패널)
도메인 전용 (재사용 금지):
- `BizCstMatrixFormSection` — 총사업비 (fnrs `BusinessCostFormSection` 미사용)
- 폼 하단 액션바 — `fnrs-form-page` 279~323 복제, API만 sewer
---
## 7. 화면 데이터 흐름
```
BEGIN
// 최초 진입 (등록)
CALL 로그인사용자조회
CALL 코드조회(SEWERBSCPLANSE, SEWER, …) // 병렬
CALL 체크리스트트리(docSeComCd) // 병렬
CALL 필수첨부트리(docSeComCd) // 병렬
CALL 처리시설마스터목록 // TBD (BscFctList)
DISPLAY 폼 defaultValues
ON 1단계목표연도 CHANGE DO
SET 2·3·4단계 연도 (+5/+10/+15)
DISPLAY E/F/G/H 헤더 연도
END ON
ON 처리시설 체크 DO
ADD tmplntList 항목
ADD TabsTrigger / TabsContent (시설 패널)
SET Tabs value = 신규 시설
CALL 이전기본계획수치(시설코드) // 당초열, TBD
END ON
ON 처리시설 체크해제 DO
CONFIRM 제거
REMOVE tmplntList + 해당 Tabs 패널
SET Tabs value = 남은 시설 (없으면 Tabs 숨김)
END ON
ON [이전기본계획조회] CLICK DO
OPEN PreviousPlanLookupDialog
END ON
ON [저장] CLICK DO
VALIDATE zod (동의 제외 가능)
CALL saveApply(payload, 임시저장 상태)
NAVIGATE 목록
END ON
ON [신청완료] CLICK DO
VALIDATE zod + privacyAgree=Y + 체크리스트 완료 + 필수첨부(esntlAtchYn=Y) 완료
CONFIRM 신청 확인
CALL saveApply(payload, 제출 상태 LE)
NAVIGATE 상세
END ON
END
```
---
## 8. JSP ↔ 신규 갭·리스크
| # | 이슈 | 대응 |
| --- | ---------------------------------------------------- | ------------------------------------------------- |
| 1 | JSP 제출 URL이 `dscss`로 분기 (오타/구프로세스 가능) | 신규는 `saveApply` 단일 진입으로 통일 |
| 2 | 총사업비 UI 계층 ≠ `BizCstItem` | `BizCstMatrixFormSection` 전용 + `acntgSeCd` 매핑 테이블 |
| 3 | 재원분담 ≠ fnrs shar | 전용 `fnrs-cst-form-section` |
| 4 | 처리시설 매트릭스(당초/현재/변경) | Checkbox 선택 → Tabs 패널; 저장은 변경 dtl 중심; 당초는 조회 전용 |
| 5 | 시설·이전계획 API | TBD — 미정 시 체크박스 목록 mock(`faker`)만 |
| 6 | `docSeComCd` 값 | CMS/체크리스트 마스터와 합의 |
| 7 | 레거시 multipart vs TUS | fnrs 첨부 패턴 준수 |
| 8 | 주석 처리된 상세 `formFields` (자연발생인구 등) | **축소된 formFields만** 이관; 주석 블록 복원 금지 |
---
## 9. 구현 순서 (권장)
1. 라우트 + `FormPage` 골격 + zod 스키마(마스터·dtl·동의) + 폼 하단 액션바(§4-J)
2. B·C·D 섹션 (공통 위젯 최대 활용)
3. E 사업개요 + G 재원분담 (4열 매트릭스 패턴 공유)
4. F 총사업비 (`BizCstMatrixFormSection` 전용)
5. I 체크리스트·첨부
6. H 처리시설 (`BscFctList` Checkbox + `@common/components` Tabs — 가장 복잡)
7. 저장/신청완료/삭제/보완완료 API 연동 (§4-J)
8. 이전계획 Dialog (API 확정 후)
---
## 10. 체크리스트 (jsp-migration-as)
- [ ] contents만 이관 (include 제외)
- [ ] vercel-react-best-practices 적용 (Query 병렬·파생상태·dynamic)
- [ ] `@common/components` + 필요 시 DataTable
- [ ] API·모델은 `@/entities/sewer-bsc-plan` 우선
- [ ] 목데이터는 `@faker-js/faker`만 (시설 마스터 등 TBD 구간)
- [ ] 로딩·빈·에러 상태
- [ ] `router.push`로 목록 복귀
---
## 11. 후속 문서
- 목록(`dmbpList.jsp`) / 상세(`dmbpView.jsp`) / 수정(`dmbpModify.jsp`)은 본 문서와 동일 섹션 체계로 별도 확장
- 화면설계서 SPEC 형식이 필요하면 `docs/sewer-bsc-plan/SPEC.md`로 분리 (영역 A~J 표 + API 표)
+498
View File
@@ -0,0 +1,498 @@
# 화면설계서: 전국 행정지원 지도 (대시보드 메인)
## 1. 기본 정보
| 항목 | 내용 |
| ---------- | -------------------------------------------- |
| 버전 | 1.2 |
| 프로세스명 | UI설계 |
| 화면명 | 전국 행정지원 지도 (대시보드 메인) |
| 화면 ID | TBD |
| 화면 유형 | [v] 조회 [ ] 입력 [ ] 수정 [ ] 삭제 [ ] 출력 |
| 메뉴 경로 | 메인 |
---
## 2. 화면 목적
로그인 사용자의 **기관 권한·당해 연도** 기준으로 문서별 진행상태 통계와 행정지원 알림을 한 화면에서 조회한다. 좌측 지도에서 전국 행정지원 현황을 보고, 우측에서 진행상황 카드·알림이력·공지사항을 확인한 뒤 알림 [처리하기]로 연계 업무 화면으로 이동한다.
---
## 3. 화면 구성
### 3-1. 전체 레이아웃
브레드크럼·페이지 타이틀은 스크린샷에 없음. 홈(`/`) 메인 콘텐츠로 구성한다.
```
┌────────────────────────────────┬─────────────────────────────────────────────────┐
│ [영역 A] 전국 행정지원 지도 │ [영역 B] 문서별 진행상황 카드 (2×2) │
│ 타이틀: 전국 행정지원 지도 │ ┌────────────────┐ ┌────────────────┐ │
│ │ │ 재원협의 │ │ 설치인가 │ │
│ (대한민국 시도·시군구 경계) │ │ 신청/진행/완료 │ │ 신청/진행/완료 │ │
│ 마커: 서울 강남구, │ ├────────────────┤ ├────────────────┤ │
│ 대전 유성구, │ │ 설계자문 │ │ 기본계획 │ │
│ 부산 해운대구 │ │ 신청/진행/완료 │ │ 신청/진행/완료 │ │
│ │ └────────────────┘ └────────────────┘ │
│ ├─────────────────────────────────────────────────┤
│ │ [영역 C] 알림이력 │
│ │ 알림이력 업데이트 HH:mm [전체보기] │
│ │ [오늘 N건] [지연 N건] [완료대기 N건] │
│ │ [뱃지] [일자] 제목 [처리하기] │
│ │ … (최대 5건) │
│ ├─────────────────────────────────────────────────┤
│ │ [영역 D] 공지사항 [더보기] │
│ │ ┌────┬────────┬────────┬────────┬──────┐ │
│ │ │번호│ 제목 │ 작성자 │ 작성일 │조회수│ │
│ │ └────┴────────┴────────┴────────┴──────┘ │
└────────────────────────────────┴─────────────────────────────────────────────────┘
```
### 3-2. 화면 데이터 흐름
```
BEGIN
// 최초 진입
// searchYear 미전달 → 서버가 당해 연도로 고정. 알림 목록은 최신 5건
CALL getMainDashboard(DashboardMainSearchDto) // Authorization은 client 인터셉터
DISPLAY 진행상황 카드 (영역 B) // docPrgrsSttsList, TOTAL 행 제외
DISPLAY 알림 통계 칩 · 알림 목록 (영역 C) // notiStats, notiList
CALL getUserPostList(UserPostSearchParams) // board-service, AS_DASHBOARD_BBS_ID
DISPLAY 공지사항 그리드 (영역 D)
CALL 지도 마커/음영 조회(…) // TBD — 대시보드 API에 없음
DISPLAY 전국 지도 (영역 A)
ON 영역 C [전체보기] 버튼 CLICK DO
NAVIGATE /nti-hstry
END ON
ON 영역 C [처리하기] 버튼 CLICK DO
CALL readNoti(notiId) // entities/noti
NAVIGATE notiUrl // 비어 있으면 이동하지 않음
CALL getMainDashboard(…) // → 영역 C 갱신 (invalidate)
END ON
ON 영역 D [더보기] 버튼 CLICK DO
NAVIGATE /cms/bbsnotice/{AS_DASHBOARD_BBS_ID} // as 앱 공지 목록 라우트 미구현. st/cm 관례
END ON
ON 영역 D 행 CLICK DO
NAVIGATE /cms/bbsnotice/{AS_DASHBOARD_BBS_ID}/{pstNo}
END ON
ON 영역 B 카드 CLICK DO
NAVIGATE 해당 문서 목록 // §5-3
END ON
ON 영역 A 마커 CLICK DO
// TBD — 팝업/필터/이동 여부 미확정
END ON
END
```
---
## 4. 영역 A — 전국 행정지원 지도
스크린샷 타이틀: **전국 행정지원 지도**.
`getMainDashboard` 응답에 지도·좌표·행정구역 음영 데이터는 **없다**. 마커·음영 소스 API는 **TBD**.
### 4-1. 표시 요소
| 표시명 | 입력 유형 | 필수 | 기본값 | API 파라미터 매핑 | 비고 |
| ----------- | --------- | ---- | ------ | ----------------- | ----------------------------------------------------------------- |
| 섹션 타이틀 | Text | — | — | — | 고정 문구 `전국 행정지원 지도` |
| 전국 지도 | Map | — | — | TBD | 시도·시군구 경계. 북·동부 음영(청) / 남서부 비음영(백) — 의미 TBD |
| 마커 라벨 | Marker | — | — | TBD | 스크린샷 샘플: `서울 강남구`, `대전 유성구`, `부산 해운대구` |
### 4-2. 상호작용
| 동작 | 설명 |
| ---------- | ----------------------------------------- |
| 마커 클릭 | TBD (상세 팝업 / 해당 지자체 필터 / 이동) |
| 지도 줌·팬 | TBD (스크린샷에 컨트롤 없음) |
`entities/adstdstr`는 시도·구군 **콤보**만 제공하며 좌표를 주지 않는다. 지도 라이브러리도 as 앱에 없음 — 선정 TBD.
---
## 5. 영역 B — 문서별 진행상황 카드
`DashboardMainResponseDto.docPrgrsSttsList`를 **`docSeComCd`로 매핑**해 4장 카드를 그린다. 배열 순서에 의존하지 않는다.
스크린샷 배치(좌→우, 상→하):
| 화면 카드 타이틀 | `docSeComCd` | API `docSeNm` |
| ----------------- | ------------ | -------------- |
| 재원협의 진행상황 | `FNRS` | 재원협의 |
| 설치인가 진행상황 | `INSTL` | 설치인가 |
| 설계자문 진행상황 | `CNFM` | 설계자문 |
| 기본계획 진행상황 | `SEWER` | 하수도기본계획 |
서버 SQL `ORDER BY`는 `INSTL → FNRS → SEWER → CNFM` 이며, `GROUP BY ROLLUP`으로 **`docSeComCd = TOTAL`** 합계 행이 추가된다. 카드에는 TOTAL 행을 **표시하지 않는다**.
카드 타이틀은 스크린샷 문구(`… 진행상황`)를 쓴다. `SEWER`의 API명 `하수도기본계획`은 화면에서 `기본계획`으로 축약한다.
### 5-1. 카드 내부 필드
각 카드 공통 구조. `totCnt`는 화면에 없음.
| 표시명 | Field | 비고 |
| ------ | ---------- | ------------------ |
| 신청 | `reqCnt` | 파란 아이콘 + 건수 |
| 진행 | `prgrsCnt` | 초록 아이콘 + 건수 |
| 완료 | `cmptnCnt` | 주황 아이콘 + 건수 |
상태 그룹(서버): 임시저장(`SV`/`CV`) 제외. 문서별 `prgrs_stts_com_cd` → `REQ`/`PRG`/`CMP`.
### 5-2. 검색 파라미터 (화면 미표시)
영역 B에 연도·필터 UI는 없다. 서버 기본값을 따른다.
| 표시명 | 입력 유형 | 필수 | 기본값 | API 파라미터 매핑 | 비고 |
| ------ | --------- | ---- | --------- | ----------------- | --------------------------------------------------------------------- |
| (없음) | — | — | 당해 연도 | `searchYear` | 미전달 시 서버 `LocalDate.now().getYear()`. 연도 셀렉터 추가 여부 TBD |
`docSeComCd` 쿼리는 **알림 목록 필터**에만 쓰이며, 진행상황 SQL에는 전달되지 않는다. 카드 4종은 항상 전원 집계한다.
### 5-3. 상호작용
카드 클릭 시 **해당 문서 목록 페이지**로 이동한다. `docSeComCd` → 라우트 고정 매핑.
| 동작 | `docSeComCd` | 이동 경로 |
| --------- | ------------ | ----------------- |
| 카드 클릭 | `FNRS` | `/fnrs-cnsltn` |
| 카드 클릭 | `INSTL` | `/instl-sncn` |
| 카드 클릭 | `CNFM` | `/design-cnstn` |
| 카드 클릭 | `SEWER` | `/sewer-bsc-plan` |
---
## 6. 영역 C — 알림이력
서버가 cms-service 알림을 대시보드 응답에 합친다. 목록은 **page=0, size=5** (최신 5건). 페이지네이션 없음.
### 6-1. 헤더
| 표시명 | Field / 소스 | 비고 |
| ------------- | ------------ | --------------------------------------------------------------------------------------- |
| 섹션 타이틀 | — | 고정 문구 `알림이력` |
| 업데이트 시각 | (client) | 스크린샷 `업데이트 10:32`. API 필드 없음. `getMainDashboard` 마지막 fetch 시각(`HH:mm`) |
| 전체보기 | Button | `/nti-hstry`로 이동 |
### 6-2. 통계 칩
`NotiAsStatResponseDto`.
| 표시명 | Field | 비고 |
| ------------ | -------------- | -------------------------------------- |
| 오늘 N건 | `todayCount` | 당일 00:00 이후 수신 |
| 지연 N건 | `delayCount` | `notReadYn=N` 이고 수신 후 3일 이상 |
| 완료대기 N건 | `pendingCount` | `notReadYn=Y` 이고 `notiPrcsCmptnYn=N` |
### 6-3. 목록 행
| 표시명 | Field | 비고 |
| ------ | --------- | --------------------------------------------- |
| 일자 | `regDt` | 표시 `YYYY-MM-DD`. 응답 `yyyy-MM-dd HH:mm:ss` |
| 제목 | `notiTtl` | 알림 제목 |
| 처리 | (action) | 스크린샷 라벨 `처리하기`. 클릭 §6-4 |
응답에 있으나 이 목록에 **표시하지 않음**:
| Field | 비고 |
| ----------------- | ----------------------------------------- |
| `notiId` | 행 키 · `readNoti` 파라미터 |
| `recvUnqId` | 수신 회원 UUID (서버 로그인 사용자 고정) |
| `senderUnqId` | 발신 회원 UUID |
| `notiType` | `ADSS` |
| `notiCn` | 본문 |
| `notiUrl` | 처리 후 이동 URL. 컬럼 미표시 |
| `notiLnkgUnqNo` | 알림연결고유번호 |
| `docSeComCd` | 문서구분 코드 |
| `docSeComNm` | 문서구분명 (알림이력 화면에서는 연계업무) |
| `notReadYn` | 뱃지 판정 TBD에 사용 가능 |
| `notiIdntyYn` | 확인 여부 |
| `notiIdntyDt` | 확인 일시 |
| `notiPrcsCmptnYn` | 처리 완료 여부 |
| `notiPrcsCmptnDt` | 처리 완료 일시 |
### 6-4. 행 상호작용
| 동작 | 설명 |
| --------------- | ----------------------------------------------------------------------------------------------------------------- |
| [전체보기] 클릭 | `/nti-hstry` (알림이력 목록)로 이동 |
| [처리하기] 클릭 | `readNoti(notiId)` 후 `notiUrl`로 이동. URL이 비면 이동하지 않음(읽음 처리는 수행). `dashboardBaseKey` invalidate |
`DashboardController`에 읽음 API는 없다. **`entities/noti`의 `readNoti`** 를 쓴다. 알림이력 화면과 동일 (`PUT /cms-service/api/v1/noti/{notiId}/read`).
### 6-5. 검색 파라미터 (화면 미표시)
서버 `toNotiSearchDto()` 기본: `notiType = ADSS`. 화면 필터 없음.
| DashboardMainSearchDto | 화면 | 비고 |
| ---------------------- | ---- | --------------------------------- |
| `notiType` | 없음 | 서버 기본 `ADSS` |
| `notReadYn` | 없음 | 통계 칩 클릭 필터 시 후보 (TBD) |
| `startDt` / `endDt` | 없음 | 대시보드 기본 미전달 |
| `docSeComCd` | 없음 | 알림만 필터. 진행상황 카드와 무관 |
---
## 7. 영역 D — 공지사항
`getMainDashboard`에 공지 필드는 없다. **board-service** `getUserPostList`로 별도 조회한다.
- Base: `GET /board-service/api/v1/posts/user/{AS_DASHBOARD_BBS_ID}`
- `AS_DASHBOARD_BBS_ID` = `NEXT_PUBLIC_AS_DASHBOARD_BBS_ID` (로컬 예: `7`)
- 클라이언트: `@/entities/board` — `postApi.getUserPostList` / `useUserPostList`
페이지네이션 컨트롤은 없다. 요약 목록만 표시한다 (`page=0`, `size=3`).
### 7-1. 헤더·버튼
| 버튼명 | 동작 |
| ------ | ------------------------------------------------------------------------------------------- |
| 더보기 | `/cms/bbsnotice/{AS_DASHBOARD_BBS_ID}` 로 이동. as 앱에 공지 목록 라우트는 없음(st/cm 관례) |
### 7-2. 그리드 컬럼
스크린샷 헤더 순서. `UserPost`.
| 표시명 | Field | 비고 |
| ------ | --------- | ---------------------------------------------------- |
| 번호 | `rowNo` | `upndFixYn` = `Y` 이면 `[공지]` Badge, 그 외 `rowNo` |
| 제목 | `pstTtl` | truncate |
| 작성자 | `wrtrNm` | |
| 작성일 | `regDt` | 표시 `YYYY-MM-DD` (응답 datetime) |
| 조회수 | `inqNocs` | 숫자 |
조회 파라미터 (`UserPostSearchParams`):
| 필드 | 값 | 비고 |
| ------------- | ----------- | ------------------------------------------ |
| `page` | `0` | Spring 0-based |
| `size` | `3` | 대시보드 요약. 스크린샷 3행 |
| `keywordType` | `bbsTypeCd` | st 대시보드 공지 패널과 동일 |
| `keyword` | `BBSNOTICE` | 게시판 유형. path의 bbsId와 함께 공지 한정 |
응답에 있으나 그리드에 **표시하지 않음**: `bbsId`, `pstNo`(행 키·상세 이동), `pstCn`, `upndFixYn`(번호 열 판정만), `rgtrNm`, `atflCd` 등.
### 7-3. 행 상호작용
| 동작 | 설명 |
| ------- | ------------------------------------------------------------------------------ |
| 행 클릭 | `/cms/bbsnotice/{AS_DASHBOARD_BBS_ID}/{pstNo}` (as 앱 공지 상세 라우트 미구현) |
---
## 8. API/DTO 명세
### 8-1. 공통
| 항목 | 값 |
| --------------- | ---------------------------------------------------------------------------------------------- |
| Base prefix | `/as-service/api/v1/dashboard` (`ENDPOINT.AS_SERVICE.DASHBOARD`) |
| 인증 | `Authorization` 헤더. 프론트는 `client` 인터셉터. 로그인 기관 권한은 서버가 사용자 캐시로 적용 |
| 클라이언트 모듈 | `@/entities/dashboard` — `dashboardService` / `useGetMainDashboard` |
| 알림 읽음 | `@/entities/noti` — `notiService.readNoti` / `useReadNoti` |
| 공지사항 | `@/entities/board` — `postApi.getUserPostList` / `useUserPostList` |
영역 A(지도)는 본 컨트롤러·board-service 범위 밖 → **TBD**.
### 8-2. 대시보드 메인 조회 — `getMainDashboard`
| 기능 | Method | URL | Request DTO | Response DTO | API |
| -------------------------------------------- | ------ | ------------- | ------------------------------- | -------------------------- | ----------------------------------------------------------- |
| 대시보드 메인 통합진행상태 및 알림 정보 조회 | GET | `{BASE}/main` | Query: `DashboardMainSearchDto` | `DashboardMainResponseDto` | `dashboardService.getMainDashboard` / `useGetMainDashboard` |
**Request (`DashboardMainSearchDto`)**
| 필드 | 필수 | 설명 |
| ------------ | ---- | ---------------------------------------------------------------------- |
| `searchYear` | N | 검색 연도. 미전달 시 서버 당해 연도. 영역 B 집계 기간 |
| `notiType` | N | 알림 종류. 미전달 시 서버 `ADSS` |
| `notReadYn` | N | 알림 확인 여부 `Y`/`N`. 본 화면 미사용 |
| `startDt` | N | 알림 시작일 `YYYY-MM-DD`. 본 화면 미사용 |
| `endDt` | N | 알림 종료일 `YYYY-MM-DD`. 본 화면 미사용 |
| `docSeComCd` | N | 알림 문서구분 (`INSTL`/`FNRS`/`SEWER`/`CNFM` 등). 진행상황 집계와 무관 |
`Authorization`은 service 시그니처에 넣지 않는다.
**Response (`DashboardMainResponseDto`)**
| 필드 | 타입 | 설명 |
| ------------------ | --------------------------- | --------------------------- |
| `docPrgrsSttsList` | `DocPrgrsSttsResponseDto[]` | 문서별 진행상태 + TOTAL 행 |
| `notiList` | `NotiAsUserResponseDto[]` | 최신 최대 5건 |
| `notiStats` | `NotiAsStatResponseDto` | 오늘 / 지연 / 완료대기 건수 |
**`DocPrgrsSttsResponseDto`**
| 필드 | 타입 | 설명 |
| ------------ | ------ | --------------------------------------------- |
| `docSeNm` | string | 문서 구분 명칭 |
| `docSeComCd` | string | `INSTL` / `FNRS` / `SEWER` / `CNFM` / `TOTAL` |
| `reqCnt` | number | 신청 건수 |
| `prgrsCnt` | number | 진행 건수 |
| `cmptnCnt` | number | 완료 건수 |
| `totCnt` | number | 총 건수 (화면 미표시) |
**`NotiAsStatResponseDto`**
| 필드 | 타입 | 설명 |
| -------------- | ------ | --------- |
| `todayCount` | number | 오늘 알림 |
| `delayCount` | number | 지연 알림 |
| `pendingCount` | number | 완료대기 |
**`NotiAsUserResponseDto`** — 필드 상세는 `docs/spec/nti-hstry` §6-2와 동일 (`notiId`, `notiTtl`, `regDt`, `notiUrl`, `notReadYn`, `notiPrcsCmptnYn` 등).
### 8-3. 알림 읽음 처리 — `readNoti`
대시보드 컨트롤러가 아니라 cms-service. 영역 C [처리하기]에서 호출.
| 기능 | Method | URL | Request DTO | Response DTO | API |
| -------------- | ------ | ---------------------------------------- | ----------------------- | ---------------- | -------------------------------------- |
| 알림 읽음 처리 | PUT | `/cms-service/api/v1/noti/{notiId}/read` | Path: `notiId` (`Long`) | `Long` (알림 ID) | `notiService.readNoti` / `useReadNoti` |
Body 없음. 성공 시 `dashboardBaseKey`(및 필요 시 `notiBaseKey`) invalidate.
### 8-4. 전국 행정지원 지도 — TBD
| 기능 | Method | URL | Request DTO | Response DTO | API |
| ------------------- | ------ | --- | ----------- | ------------ | --- |
| 지도 마커·음영 조회 | TBD | TBD | TBD | TBD | TBD |
### 8-5. 공지사항 — `getUserPostList`
board-service. bbsId는 환경변수 `AS_DASHBOARD_BBS_ID`로 path에 고정한다.
| 기능 | Method | URL | Request DTO | Response DTO | API |
| ----------------------- | ------ | ------------------------------------------ | ----------------------------- | ------------------------ | --------------------------------------------- |
| 대시보드 공지 요약 목록 | GET | `/board-service/api/v1/posts/user/{bbsId}` | Query: `UserPostSearchParams` | `PageResponse<UserPost>` | `postApi.getUserPostList` / `useUserPostList` |
**Request (`UserPostSearchParams`)** — 본 화면 고정값
| 필드 | 필수 | 설명 |
| ------------- | ---- | -------------- |
| `page` | N | `0` |
| `size` | N | `3` |
| `keywordType` | N | `bbsTypeCd` |
| `keyword` | N | `BBSNOTICE` |
| `popupYn` 등 | N | 본 화면 미사용 |
**Response (`UserPost`) — 화면 매핑 필드**
| 필드 | 타입 | 설명 |
| ----------- | ------ | --------------------------- |
| `rowNo` | number | 번호. 고정글이 아니면 표시 |
| `pstNo` | number | 게시 번호. 상세 이동 키 |
| `bbsId` | number | 게시판 ID |
| `pstTtl` | string | 제목 |
| `wrtrNm` | string | 작성자 |
| `regDt` | string | 작성일 |
| `inqNocs` | number | 조회수 |
| `upndFixYn` | string | 상단고정 `Y`/`N` → `[공지]` |
---
## 9. UI 구현 가이드
### 9-1. 기술 스택·원칙
- 라우트: 기존 홈 `app/(main)/(with-base-layout)/page.tsx` → `pages/home` (현재 `MainPage` 플레이스홀더)
- UI: `@common/components` — Card, Badge, Button, Table(공지). 지도 라이브러리 TBD
- 데이터: React Query `useGetMainDashboard()`. 처리하기는 `useReadNoti()`. 공지는 `useUserPostList()`
- 진행상황 카드: `docSeComCd`로 4슬롯 매핑. `TOTAL` 제외
- 알림 목록: 테이블이 아닌 행 리스트(뱃지 + 일자 + 제목 + 버튼)
- 공지: `@tanstack/react-table` + `useDataTable`, 페이지네이션 없음
- 검색 조건 URL 동기화: 본 화면 필터 없음. `searchYear` UI가 생기면 그때 검토
### 9-2. 모듈·파일 배치
| 구분 | 경로 |
| ------------- | ------------------------------------------------------------ |
| 라우트 | `app/(main)/(with-base-layout)/page.tsx` |
| 페이지 | `pages/dashboard/ui/dashboard-page.tsx` |
| 지도 | `pages/dashboard/ui/national-as-map.tsx` (API TBD, Skeleton) |
| 진행상황 카드 | `pages/dashboard/ui/doc-prgrs-stts-cards.tsx` |
| 알림이력 | `pages/dashboard/ui/dashboard-noti-list.tsx` |
| 공지사항 | `pages/dashboard/ui/dashboard-notice-table.tsx` |
| 공지 컬럼 | `pages/dashboard/model/dashboard-notice-table-columns.tsx` |
| Entity API | `entities/dashboard/api/dashboard-service.ts` |
| Entity Hook | `entities/dashboard/api/queries.ts` → `useGetMainDashboard` |
| Entity Model | `entities/dashboard/model/dashboard-interface.ts` |
| 알림 읽음 | `entities/noti` → `useReadNoti` |
| 공지 Entity | `entities/board` → `useUserPostList` |
Entity(`getMainDashboard`, `getUserPostList`) 구현됨. 영역 B·C·D 화면 구현. 영역 A는 Skeleton.
### 9-3. 영역별 UI 매핑
| 영역 | 컴포넌트 | 데이터 |
| ---- | ------------------------ | ---------------------------------------------------------------------------- |
| A | `national-as-map` | Skeleton (지도 API TBD) |
| B | `doc-prgrs-stts-cards` | `useGetMainDashboard` → `docPrgrsSttsList` (`TOTAL` 제외, 코드 매핑) |
| C | `dashboard-noti-list` | 동 훅 → `notiStats`, `notiList`. 처리 → `useReadNoti`. 전체보기 `/nti-hstry` |
| D | `dashboard-notice-table` | `useUserPostList` → `content[]`. [더보기]·행 클릭 → `/cms/bbsnotice/...` |
### 9-4. 다이얼로그·라우팅
| 항목 | 내용 |
| -------------- | -------------------------------------------------------------------------------------- |
| 다이얼로그 | 없음 |
| 본 화면 라우트 | `/` (홈) |
| 알림 처리 이동 | [처리하기] → `readNoti` 후 `notiUrl` (알림이력과 동일, SEWER URL은 상세 세그먼트 제거) |
| 알림 전체보기 | `/nti-hstry` |
| 공지 더보기 | `/cms/bbsnotice/{AS_DASHBOARD_BBS_ID}` (as 앱 공지 라우트 미구현, st/cm 관례) |
| 공지 행 클릭 | `/cms/bbsnotice/{AS_DASHBOARD_BBS_ID}/{pstNo}` |
| 진행상황 카드 | §5-3 목록 라우트 (`/fnrs-cnsltn`, `/instl-sncn`, `/design-cnstn`, `/sewer-bsc-plan`) |
### 9-5. 데이터 흐름
```
BEGIN
// 최초 진입 (홈)
CALL getMainDashboard({})
DISPLAY 영역 B // docPrgrsSttsList — FNRS/INSTL/CNFM/SEWER 슬롯
DISPLAY 영역 C // notiStats + notiList(≤5)
CALL getUserPostList({ page: 0, size: 3, keywordType: "bbsTypeCd", keyword: "BBSNOTICE" })
DISPLAY 영역 D
CALL 지도 데이터 // TBD → 영역 A
ON 영역 C [전체보기] CLICK DO
NAVIGATE /nti-hstry
END ON
ON 영역 C [처리하기] CLICK DO
CALL readNoti(notiId)
IF notiUrl THEN
NAVIGATE notiUrl
END IF
CALL getMainDashboard // invalidate dashboardBaseKey
END ON
ON 영역 B 카드 CLICK DO
NAVIGATE 문서 목록 // §5-3
END ON
ON 영역 D [더보기] CLICK DO
NAVIGATE /cms/bbsnotice/{AS_DASHBOARD_BBS_ID}
END ON
ON 영역 D 행 CLICK DO
NAVIGATE /cms/bbsnotice/{AS_DASHBOARD_BBS_ID}/{pstNo}
END ON
END
```
+285
View File
@@ -0,0 +1,285 @@
# 화면설계서: 내 행정지원
## 1. 기본 정보
| 항목 | 내용 |
| ---------- | -------------------------------------------- |
| 버전 | 1.0 |
| 프로세스명 | UI설계 |
| 화면명 | 내 행정지원 |
| 화면 ID | AS_SC0204011 |
| 화면 유형 | [v] 조회 [ ] 입력 [ ] 수정 [ ] 삭제 [ ] 출력 |
| 메뉴 경로 | 메인 > 행정지원서비스 > 내 행정지원 |
---
## 2. 화면 목적
로그인한 사용자가 **본인이 신청한 행정지원 문서**를 기간·구분·진행상태로 조회한다. 목록에서 행을 선택하면 해당 문서 상세 화면으로 이동한다.
---
## 3. 화면 구성
### 3-1. 전체 레이아웃
```
┌─────────────────────────────────────────────────────────────────────────────────┐
│ 브레드크럼: 메인 > 행정지원서비스 > 내 행정지원 │
│ 페이지 타이틀: 내 행정지원 │
├─────────────────────────────────────────────────────────────────────────────────┤
│ [영역 A] 검색 필터 │
│ 기간 [시작일] ~ [종료일] 구분 ▼ 진행상태 ▼ [검색] │
├─────────────────────────────────────────────────────────────────────────────────┤
│ [영역 B] 내 신청 목록 │
│ 타이틀: 내 신청 목록 N개 │
│ ┌────┬──────┬────────┬──────────────┬────────────┬────────┬──────────────┐ │
│ │ No │ 구분 │ 신청일 │ 진행상태 │ 완료(예정)일│ 담당자 │ 담당자연락처 │ │
│ ├────┼──────┼────────┼──────────────┼────────────┼────────┼──────────────┤ │
│ │ … │ … │ … │ prgrsSttsComNm│ … │ … │ … │ │
│ └────┴──────┴────────┴──────────────┴────────────┴────────┴──────────────┘ │
│ [페이지네이션] │
└─────────────────────────────────────────────────────────────────────────────────┘
```
### 3-2. 화면 데이터 흐름
```
BEGIN
// 최초 진입
// 기간 기본값: 오늘 기준 최근 1개월 (startDate = today-1M, endDate = today)
CALL findMyElaperDocList(ElaprMyDocSearchDto + pageable)
DISPLAY 내 신청 목록 그리드 (영역 B)
ON [검색] 버튼 CLICK DO
CALL findMyElaperDocList(영역 A 조건 + page=0)
DISPLAY 내 신청 목록 그리드 (영역 B)
END ON
ON 페이지네이션 CHANGE DO
CALL findMyElaperDocList(영역 A 조건 + page/size)
DISPLAY 내 신청 목록 그리드 (영역 B)
END ON
ON 영역 B 행 CLICK DO
// docSeComCd·prgrsSttsComCd·rgtr → view/edit
NAVIGATE 문서 상세 또는 수정 화면
END ON
END
```
---
## 4. 영역 A — 검색 필터
구성: **기간 · 구분 · 진행상태** (+ 검색).
> UI설계 상세설명의 `docSecs` / `docStatusCd`는 레거시·설계 문서 명칭이다.
> **API SoT**는 `ElaprMyDocSearchDto`의 `docSeComCd` / `prgrsSttsComCd`를 사용한다.
### 4-1. 필드 정의
| 표시명 | 입력 유형 | 필수 | 기본값 | API 파라미터 매핑 | 비고 |
| ---------- | ---------------- | ---- | --------------------------- | ----------------- | --------------------------------------------------------------------- |
| 기간(시작) | DatePicker | N | 오늘 − 1개월 (`YYYY-MM-DD`) | `startDate` | 신청일(`reqDt`) 기준 검색으로 가정 |
| 기간(종료) | DatePicker | N | 오늘 (`YYYY-MM-DD`) | `endDate` | |
| 구분 | Select(공통코드) | N | 전체(미선택) | `docSeComCd` | 상위코드 `ASDOCSE`. UI설계 `docSecs` → API `docSeComCd` |
| 진행상태 | Select(공통코드) | N | 전체(미선택) | `prgrsSttsComCd` | 상위코드 = `{docSeComCd}STTS` (예: `INSTL` → `INSTLSTTS`). UI설계 `docStatusCd` → API 필드명 |
### 4-2. 버튼
| 버튼명 | 동작 |
| ------ | ----------------------------------------------------------------- |
| 검색 | 영역 A 조건으로 `findMyElaperDocList` 호출 → 영역 B 갱신 (page=0) |
### 4-3. 콤보 의존
| 트리거 | 동작 |
| ----------- | ------------------------------------------------------------------- |
| 구분 변경 | 진행상태 옵션을 `upCd = docSeComCd + "STTS"`로 재조회. 진행상태 선택값 RESET |
| 구분 미선택 | 진행상태 비활성(옵션 비움). `upCd` 조합 불가이므로 조회하지 않음 |
---
## 5. 영역 B — 내 신청 목록
### 5-1. 그리드 컬럼
| 표시명 | Field | 비고 |
| ------------ | ---------------- | ------------------------------------------------- |
| No | (row index) | 페이지 오프셋 반영 |
| 구분 | `docSeComNm` | 코드 `docSeComCd` (`ASDOCSE`) |
| 신청일 | `reqDt` | 표시 `YYYY-MM-DD` (응답은 `yyyy-MM-dd HH:mm:ss`) |
| 진행상태 | `prgrsSttsComNm` | 텍스트 렌더링 (단계형 프로그레스 미사용) |
| 완료(예정)일 | `cmptnExpctDt` | 표시 `YYYY-MM-DD` |
| 담당자 | `picNm` | |
| 담당자연락처 | `picTelno` | |
응답에 있으나 그리드에 **표시하지 않음**:
| Field | 비고 |
| ---------------- | ----------------------------------------------------------------- |
| `docNo` | 문서번호 — 행 클릭 라우팅 키 |
| `docTtl` | 문서명/사업명 — 미표시 |
| `chgCycl` | 변경차수 — 그리드 미표시. SEWER 이동 시 query 파라미터로 사용 |
| `prgrsSttsComCd` | 진행상태 코드 — 컬럼 표시는 `prgrsSttsComNm` |
| `rgtr` | 등록자 UUID — edit 판정용 (`rgtr === userUnqId`) |
### 5-2. 목록 메타·페이지네이션
| 항목 | 매핑 |
| ------------- | ------------------------------------------- |
| 건수 `N개` | `PageResponse.totalElements` |
| page / size | `ElaprMyDocSearchDto`의 `PageableParams` |
| 페이지 컨트롤 | Spring `Page` 표준 (`number`, `totalPages`) |
### 5-3. 행 상호작용
| 동작 | 설명 |
| ------- | -------------------------------------------------------------------------------------------- |
| 행 클릭 | `docSeComCd`·`prgrsSttsComCd`·`rgtr`로 view/edit 분기 후 이동 (`resolveMyPbadmsSprtDetailPath`) |
**edit 조건** (기존 도메인 목록과 동일):
| `docSeComCd` | edit 조건 |
| ------------------------ | ---------------------------------------------------------------------- |
| `INSTL` / `FNRS` / `SEWER` | `(prgrsSttsComCd === "SV" \|\| "SL") && rgtr === loggedInUserUnqId` |
| `CNFM` | `prgrsSttsComCd === "CV" && rgtr === loggedInUserUnqId` |
| `docSeComCd` | edit 경로 | view 경로 |
| ------------ | -------------------------------------------- | --------------------------------------- |
| `FNRS` | `/fnrs-cnsltn/{docNo}/edit` | `/fnrs-cnsltn/{docNo}` |
| `INSTL` | `/instl-sncn/{docNo}/edit` | `/instl-sncn/{docNo}` |
| `CNFM` | `/design-cnstn/{docNo}/edit` | `/design-cnstn/{docNo}` |
| `SEWER` | `/sewer-bsc-plan/{docNo}/edit?chgCycl={n}` | `/sewer-bsc-plan/{docNo}?chgCycl={n}` |
| 그 외 | 이동하지 않음 | |
- SEWER `chgCycl`: `row.chgCycl ?? 1`
- 조건 불충족 시 항상 view
---
## 6. API/DTO 명세
### 6-1. 공통
| 항목 | 값 |
| --------------- | ------------------------------------------------------------------------------------------ |
| Base prefix | `/as-elapr-service/api/v1/elapr-prgrs-stts` (`ENDPOINT.AS_ELAPR_SERVICE.ELAPR_PRGRS_STTS`) |
| 인증 | 로그인 사용자 UUID — 서버 `SecurityUtils.getLoggedInUserUnqIdUUID()` (클라이언트 미전달) |
| 클라이언트 모듈 | `@/entities/elapr` — `elaprPrgrsSttsService` / `useElaprPrgrsSttsMyDocPage` |
### 6-2. 내 행정지원 목록 — `findMyElaperDocList`
| 기능 | Method | URL | Request DTO | Response DTO | API |
| ----------------- | ------ | --------------- | --------------------------------------- | ------------------------------------ | -------------------------------------------------------------------------- |
| 내 신청 목록 조회 | GET | `{BASE}/my/doc` | Query: `ElaprMyDocSearchDto` + Pageable | `PageResponse<MyAdssDocResponseDto>` | `elaprPrgrsSttsService.findMyElaperDocList` / `useElaprPrgrsSttsMyDocPage` |
**Request (`ElaprMyDocSearchDto` + Pageable)**
| 필드 | 필수 | 설명 |
| ------------------------ | ---- | ------------------------------------------------------------ |
| `startDate` | N | 검색 시작일 `YYYY-MM-DD` |
| `endDate` | N | 검색 종료일 `YYYY-MM-DD` |
| `docSeComCd` | N | 문서구분 (`INSTL` / `FNRS` / `DESIGN` / `SEWER` / `PWRK` 등) |
| `prgrsSttsComCd` | N | 문서진행상태공통코드 |
| `page` / `size` / `sort` | N | Spring Pageable |
**Response (`MyAdssDocResponseDto`)**
| 필드 | 타입 | 설명 |
| ---------------- | ------- | ------------------------------------------- |
| `docNo` | string | 문서번호 |
| `docTtl` | string? | 문서명/사업명 |
| `docSeComCd` | string? | 문서구분 코드 |
| `docSeComNm` | string? | 문서구분 코드명 (`ASDOCSE`) |
| `reqDt` | string? | 신청일시 `yyyy-MM-dd HH:mm:ss` |
| `prgrsSttsComCd` | string? | 문서진행상태 코드 |
| `prgrsSttsComNm` | string? | 문서진행상태 코드명 |
| `cmptnExpctDt` | string? | 완료(예정)일 `yyyy-MM-dd` |
| `picNm` | string? | 담당자 성명 |
| `picTelno` | string? | 담당자 연락처 |
| `chgCycl` | number? | 변경차수 |
| `rgtr` | string? | 등록자 UUID |
### 6-3. 공통코드 (콤보)
| 용도 | 상위코드 | API | 비고 |
| -------- | ------------ | --------------------------- | ----------------------------- |
| 구분 | `ASDOCSE` | `useCodeList("ASDOCSE")` 등 | 기존 관리 화면과 동일 |
| 진행상태 | `{docSeComCd}STTS` | `useCodeList(docSeComCd + "STTS")` | 예: `INSTLSTTS`, `FNRSSTTS`, `SEWERSTTS`. 구분 미선택 시 미호출 |
---
## 7. UI 구현 가이드
### 7-1. 기술 스택·원칙
- UI: `@common/components` — DatePicker, Select/`CodeSelect`, Button, DataTable, Pagination
- 목록: `@tanstack/react-table` + `useDataTable` (기존 `instl-list` / `fnrs-list` 패턴)
- 데이터: React Query `useElaprPrgrsSttsMyDocPage(params)`
- 검색 조건·페이지: URL `searchParams` 동기화 권장 (`useSearchParamsState` 스킬)
- 진행상태 컬럼: `prgrsSttsComNm` 텍스트 렌더링 (단계형 프로그레스 미사용)
- 행 클릭: `docSeComCd` + `prgrsSttsComCd` + `rgtr`로 view/edit 분기 (`SEWER`는 `chgCycl` query 포함)
### 7-2. 앱·파일 배치
| 구분 | 경로 |
| ------------ | -------------------------------------------------------------- |
| 라우트 | `app/(main)/(with-base-layout)/my-pbadms-sprt/page.tsx` |
| 페이지 | `pages/my-pbadms-sprt/ui/my-pbadms-sprt-list-page.tsx` |
| 목록 그리드 | `pages/my-pbadms-sprt/ui/my-pbadms-sprt-list.tsx` |
| 경로 해석 | `pages/my-pbadms-sprt/lib/resolve-detail-path.ts` |
| 테이블 컬럼 | `pages/my-pbadms-sprt/model/my-pbadms-sprt-table-columns.tsx` |
| Entity API | `entities/elapr/api/elapr-prgrs-stts-service.ts` |
| Entity Hook | `entities/elapr/api/queries.ts` → `useElaprPrgrsSttsMyDocPage` |
| Entity Model | `entities/elapr/model/elapr-prgrs-stts-interface.ts` |
### 7-3. 영역별 UI 매핑
| 영역 | 컴포넌트 | 데이터 |
| ---- | -------------------------- | ------------------------------------------ |
| A | `my-pbadms-sprt-list-page` | 로컬 state → `ElaprMyDocSearchDto` |
| B | DataTable + columns | `useElaprPrgrsSttsMyDocPage` → `content[]` |
### 7-4. 다이얼로그·라우팅
| 항목 | 내용 |
| ----------- | -------------------------------------------------------------------- |
| 다이얼로그 | 없음 (목록 전용) |
| 목록 라우트 | `/my-pbadms-sprt` |
| 상세 이동 | §5-3 표와 동일 (view/edit + `rgtr` 소유자 검사, SEWER `chgCycl`) |
### 7-5. 데이터 흐름
```
BEGIN
// 최초 진입
SET 기간 = 최근 1개월
CALL findMyElaperDocList
DISPLAY 영역 B
ON [검색] CLICK DO
CALL findMyElaperDocList // → 영역 B 갱신
END ON
ON 페이지 CHANGE DO
CALL findMyElaperDocList
END ON
ON 영역 B 행 CLICK DO
IF NOT docNo OR unsupported docSeComCd THEN
// no-op
ELSE IF canEdit(prgrsSttsComCd, rgtr === userUnqId) THEN
NAVIGATE edit 경로 // SEWER면 ?chgCycl=
ELSE
NAVIGATE view 경로
END IF
END ON
END
```
+352
View File
@@ -0,0 +1,352 @@
# 화면설계서: 알림이력
## 1. 기본 정보
| 항목 | 내용 |
| ----------- | -------------------------------------------- |
| 버전 | 1.4 |
| 프로세스명 | UI설계 |
| 화면명 | 알림이력 |
| 화면 ID | AS_SC0205011 |
| 요구사항 ID | NSUR-001-001 |
| 화면 유형 | [v] 조회 [ ] 입력 [ ] 수정 [ ] 삭제 [ ] 출력 |
| 메뉴 경로 | 메인 > 행정지원서비스 > 알림이력 |
---
## 2. 화면 목적
로그인한 사용자가 **본인에게 발송된 행정지원(ADSS) 알림**을 기간·구분으로 조회한다. 목록의 처리 버튼으로 해당 알림을 읽음 처리한 뒤, 연계된 업무 화면으로 이동한다.
---
## 3. 화면 구성
### 3-1. 전체 레이아웃
```
┌─────────────────────────────────────────────────────────────────────────────────┐
│ 브레드크럼: 메인 > 행정지원서비스 > 알림이력 │
│ 페이지 타이틀: 알림이력 │
├─────────────────────────────────────────────────────────────────────────────────┤
│ [영역 A] 검색 필터 │
│ 기간 [시작일] ~ [종료일] 구분 ▼ [검색] │
├─────────────────────────────────────────────────────────────────────────────────┤
│ [영역 B] 알림 이력 목록 │
│ 타이틀: 알림 이력 목록 N개 ▼ │
│ ┌────┬──────────────┬────────────────┬──────────┬────────┬────────┐ │
│ │ No │ 알림일시 │ 알림내용 │ 연계업무 │ 상태 │ 처리 │ │
│ ├────┼──────────────┼────────────────┼──────────┼────────┼────────┤ │
│ │ … │ regDt │ notiTtl │ docSeComNm│ Badge │ 버튼 │ │
│ └────┴──────────────┴────────────────┴──────────┴────────┴────────┘ │
│ [페이지네이션] │
└─────────────────────────────────────────────────────────────────────────────────┘
```
### 3-2. 화면 데이터 흐름
```
BEGIN
// 최초 진입
// 기간 기본값: 오늘 기준 최근 1개월 (시작일 = today-1M, 종료일 = today)
CALL findMyAsNotiList(NotiSearchDto + pageable)
DISPLAY 알림 이력 목록 그리드 (영역 B)
ON [검색] 버튼 CLICK DO
CALL findMyAsNotiList(영역 A 조건 + page=0)
DISPLAY 알림 이력 목록 그리드 (영역 B)
END ON
ON 페이지네이션 CHANGE DO
CALL findMyAsNotiList(영역 A 조건 + page/size)
DISPLAY 알림 이력 목록 그리드 (영역 B)
END ON
ON 영역 B [처리] 버튼 CLICK DO
CALL readNoti(notiId)
// UI설계: 해당 알림에 연계된 URL로 이동
NAVIGATE notiUrl
END ON
END
```
---
## 4. 영역 A — 검색 필터
구성: **기간 · 구분** (+ 검색).
서버 `findMyAsNotiList` 고정 정책 (클라이언트 미전달):
- `recvUnqId` = 로그인 사용자 UUID
- `delYn` = `N`
- `notiType` = `ADSS` (행정지원 전용 API)
### 4-1. 필드 정의
| 표시명 | 입력 유형 | 필수 | 기본값 | API 파라미터 매핑 | 비고 |
| ---------- | ---------- | ---- | --------------------------- | ----------------- | ------------------------------------------------------------------------------------------------ |
| 기간(시작) | DatePicker | N | 오늘 − 1개월 (`YYYY-MM-DD`) | `startDt` | `NotiSearchDto.startDt` |
| 기간(종료) | DatePicker | N | 오늘 (`YYYY-MM-DD`) | `endDt` | `NotiSearchDto.endDt` |
| 구분 | Select | N | 전체(미선택) | `docSeComCd` | `INSTL` / `FNRS` / `SEWER` / `CNFM` / `PWRK` (또는 단축 `I`/`F`/`S`/`C`/`P`). 공통코드 `ASDOCSE` |
### 4-2. 버튼
| 버튼명 | 동작 |
| ------ | -------------------------------------------------------------- |
| 검색 | 영역 A 조건으로 `findMyAsNotiList` 호출 → 영역 B 갱신 (page=0) |
### 4-3. 콤보·기본값 주의
| 항목 | 내용 |
| -------------- | ---------------------------------------------------------- |
| 구분 = 전체 | `docSeComCd` 미전달. `notiType`은 서버가 `ADSS`로 고정 |
| 구분 옵션 소스 | 공통코드 `ASDOCSE` (`docSeComCd` ↔ `docSeComNm`) |
| 기간 | UI설계 상세설명: 기본 최근 1개월. `startDt`/`endDt`로 전달 |
---
## 5. 영역 B — 알림 이력 목록
### 5-1. 그리드 컬럼
| 표시명 | Field | 비고 |
| -------- | ------------ | --------------------------------------------------------------- |
| No | (row index) | 페이지 오프셋 반영 |
| 알림일시 | `regDt` | 표시 `YYYY-MM-DD HH:mm` (응답 `yyyy-MM-dd HH:mm:ss`) |
| 알림내용 | `notiTtl` | 제목 문자열. UI 샘플은 `[YYYY-MM-DD] …` 접두 |
| 연계업무 | `docSeComNm` | 문서구분 공통코드명 (`docSeComCd` + `@CodeName` `ASDOCSE`) |
| 상태 | (derived) | `Badge` 렌더링. 판정 규칙은 §5-1-1 |
| 처리 | (action) | 상태별 버튼 라벨. 클릭 시 `readNoti` 후 `notiUrl`로 이동 (§5-3) |
#### 5-1-1. 상태 UI 케이스 (`@common/components` `Badge`)
판정에 사용: `notiPrcsCmptnYn`, `notReadYn`, `regDt` (오늘 기준 경과일).
| 조건 | 라벨 | Badge |
| ------------------------------------------------------------------------------ | -------- | ----------------------------- |
| `notiPrcsCmptnYn` = `Y` | 처리완료 | `variant="default"` (primary) |
| `notiPrcsCmptnYn` = `N` 이고 `notReadYn` = `Y` 이고 `regDt`로부터 **7일 초과** | 처리지연 | `color="red"` |
| `notiPrcsCmptnYn` = `N` 이고 `notReadYn` = `Y` 이고 `regDt`로부터 **7일 이내** | 처리중 | `color="green"` |
| `notiPrcsCmptnYn` = `N` 이고 `notReadYn` = `N` 이고 `regDt`로부터 **3일 초과** | 지연 | `color="orange"` |
| `notiPrcsCmptnYn` = `N` 이고 `notReadYn` = `N` 이고 `regDt`로부터 **3일 이내** | 미조회 | `color="yellow"` |
```
IF notiPrcsCmptnYn = Y THEN
DISPLAY Badge "처리완료" (primary / variant=default)
ELSE IF notReadYn = Y THEN
IF daysSince(regDt) > 7 THEN
DISPLAY Badge "처리지연" (red)
ELSE
DISPLAY Badge "처리중" (green)
END IF
ELSE // notReadYn = N
IF daysSince(regDt) > 3 THEN
DISPLAY Badge "지연" (orange)
ELSE
DISPLAY Badge "미조회" (yellow)
END IF
END IF
```
- `daysSince(regDt)`: 오늘 날짜 − `regDt` 일자 (일 단위)
- `regDt`가 없으면 상태 Badge 표시 전략 TBD (미표시 또는 기본값)
응답에 있으나 그리드에 **표시하지 않음**:
| Field | 비고 |
| ----------------- | ---------------------------------------------------------------------- |
| `notiId` | 알림 ID — 행 키 |
| `recvUnqId` | 수신 회원 UUID (서버가 로그인 사용자로 고정) |
| `senderUnqId` | 발신 회원 UUID |
| `notiType` | 알림 종류 (`ADSS`) |
| `notiCn` | 알림 내용 (목록에서는 서버가 제외할 수 있음) |
| `notReadYn` | 확인 여부 `Y`/`N`. 상태 Badge 판정에 사용 (§5-1-1) |
| `notiUrl` | 처리 버튼 이동 URL. 컬럼 미표시 |
| `notiLnkgUnqNo` | 알림연결고유번호 |
| `docSeComCd` | 문서구분 공통코드. 연계업무 표시는 `docSeComNm` 사용 |
| `notiIdntyDt` | 알림 확인 일시 |
| `notiIdntyYn` | 알림 확인 여부 (`notReadYn`과 동일 의미). 상태 판정은 `notReadYn` 사용 |
| `notiPrcsCmptnYn` | 알림 처리 완료 여부. 상태 Badge 판정에 사용 (§5-1-1) |
| `notiPrcsCmptnDt` | 알림 처리 완료 일시 |
### 5-2. 목록 메타·페이지네이션
| 항목 | 매핑 |
| ------------- | ------------------------------------------- |
| 건수 / size ▼ | 상단 우측 `N개` 셀렉트 → `Pageable.size` |
| page / size | `NotiSearchDto`의 `PageableParams` |
| 페이지 컨트롤 | Spring `Page` 표준 (`number`, `totalPages`) |
### 5-3. 행 상호작용
| 동작 | 설명 |
| -------------- | --------------------------------------------------------------------------- |
| 처리 버튼 클릭 | `readNoti(notiId)`로 읽음 처리 후, 해당 알림에 연계된 URL(`notiUrl`)로 이동 |
| 행 클릭 | UI설계에 없음. 처리 버튼만 명시 |
**처리 버튼 라벨** (상태 Badge §5-1-1 기준):
| 상태 | 버튼명 |
| -------- | -------- |
| 미조회 | 처리하기 |
| 지연 | 처리하기 |
| 처리중 | 처리하기 |
| 처리지연 | 처리하기 |
| 처리완료 | 상세보기 |
- `notiUrl`이 비어 있으면 이동하지 않음 (no-op). 읽음 처리는 `notiUrl` 유무와 관계없이 호출
- 읽음 처리 성공 후 목록 쿼리(`notiBaseKey`)를 invalidate 하여 영역 B 상태를 갱신
---
## 6. API/DTO 명세
### 6-1. 공통
| 항목 | 값 |
| --------------- | ---------------------------------------------------------------------------------------- |
| Base prefix | `/cms-service/api/v1/noti` (`ENDPOINT.CMS_SERVICE.NOTI`) |
| 인증 | 로그인 사용자 UUID — 서버 `SecurityUtils.getLoggedInUserUnqIdUUID()` (클라이언트 미전달) |
| 클라이언트 모듈 | `@/entities/noti` — `notiService` / `useFindMyAsNotiList` / `useReadNoti` |
### 6-2. 로그인한 사용자 행정지원 알림 목록 — `findMyAsNotiList`
| 기능 | Method | URL | Request DTO | Response DTO | API |
| ---------------------------------- | ------ | ------------------- | --------------------------------- | ------------------------------------- | ------------------------------------------------------ |
| 로그인한 사용자 행정지원 알림 목록 | GET | `{BASE}/as/my/list` | Query: `NotiSearchDto` + Pageable | `PageResponse<NotiAsUserResponseDto>` | `notiService.findMyAsNotiList` / `useFindMyAsNotiList` |
**Request (`NotiSearchDto` + Pageable)**
| 필드 | 필수 | 설명 |
| ------------------------ | ---- | --------------------------------------------------------------------------- |
| `recvUnqId` | N | 수신 회원 UUID. 서버가 로그인 사용자로 덮어씀 |
| `senderUnqId` | N | 발신 회원 UUID. 본 화면 필터에 없음 |
| `notiType` | N | 알림 종류. 본 API는 서버가 `ADSS`로 고정 |
| `notiTtlKeyword` | N | 알림 제목 키워드. 본 화면 필터에 없음 |
| `notiCnKeyword` | N | 알림 내용 키워드. 본 화면 필터에 없음 |
| `notReadYn` | N | 알림 확인 여부 (`Y`/`N`). 본 화면 검색 필터에 없음 |
| `delYn` | N | 삭제 여부. 서버가 `N`으로 고정 |
| `startDt` | N | 시작일자 `YYYY-MM-DD` — 영역 A 기간(시작) |
| `endDt` | N | 종료일자 `YYYY-MM-DD` — 영역 A 기간(종료) |
| `docSeComCd` | N | 문서 구분 공통 코드 (`INSTL`/`FNRS`/`SEWER`/`CNFM`/`PWRK` 등) — 영역 A 구분 |
| `page` / `size` / `sort` | N | Spring Pageable |
**Response (`NotiAsUserResponseDto`)**
| 필드 | 타입 | 설명 |
| ----------------- | ------- | ------------------------------------------------------- |
| `notiId` | number | 알림 ID |
| `recvUnqId` | string | 수신 회원 UUID |
| `senderUnqId` | string | 발신 회원 UUID |
| `notiType` | string | 알림 종류 (`ADSS`) |
| `notiTtl` | string | 알림 제목 |
| `notiCn` | string? | 알림 내용 (목록에서 제외될 수 있음) |
| `notReadYn` | string? | 알림 확인 여부 (`Y`/`N`). 상태 Badge 판정 |
| `regDt` | string? | 등록 일시 `yyyy-MM-dd HH:mm:ss`. 상태 Badge 경과일 기준 |
| `notiUrl` | string? | 알림 URL 주소 |
| `notiLnkgUnqNo` | string? | 알림연결고유번호 |
| `docSeComCd` | string? | 문서구분 공통코드 |
| `docSeComNm` | string? | 문서구분 공통코드명 (`ASDOCSE`) |
| `notiIdntyDt` | string? | 알림 확인 일시 `yyyy-MM-dd HH:mm:ss` |
| `notiIdntyYn` | string? | 알림 확인 여부 (`Y`/`N`) |
| `notiPrcsCmptnYn` | string? | 알림 처리 완료 여부 (`Y`/`N`). 상태 Badge 판정 |
| `notiPrcsCmptnDt` | string? | 알림 처리 완료 일시 `yyyy-MM-dd HH:mm:ss` |
### 6-3. 알림 읽음 처리 — `readNoti`
| 기능 | Method | URL | Request DTO | Response DTO | API |
| -------------- | ------ | ---------------------- | ----------------------- | ---------------- | -------------------------------------- |
| 알림 읽음 처리 | PUT | `{BASE}/{notiId}/read` | Path: `notiId` (`Long`) | `Long` (알림 ID) | `notiService.readNoti` / `useReadNoti` |
**Request**
| 필드 | 위치 | 필수 | 설명 |
| -------- | ---- | ---- | ------- |
| `notiId` | Path | Y | 알림 ID |
Body 없음.
**Response**
| 타입 | 설명 |
| ------ | ------------------------------ |
| number | 읽음 처리된 알림 ID (`notiId`) |
화면 매핑: 영역 B [처리] 버튼 클릭 시 호출. 성공 시 `notiBaseKey` invalidate → `findMyAsNotiList` 재조회.
---
## 7. UI 구현 가이드
### 7-1. 기술 스택·원칙
- UI: `@common/components` — DatePicker, Select, Button, DataTable, Pagination, **Badge**
- 목록: `@tanstack/react-table` + `useDataTable` (기존 `my-pbadms-sprt-list` 패턴)
- 데이터: React Query `useFindMyAsNotiList(params)`, `useReadNoti()`
- 검색 조건·페이지: URL `searchParams` 동기화 권장 (`useSearchParamsState` 스킬)
- 처리 컬럼: 행 클릭이 아니라 **버튼 클릭**으로 `readNoti` 후 `notiUrl` 이동
- 상태 컬럼: §5-1-1 규칙으로 `Badge` 렌더링 (`notiPrcsCmptnYn` / `notReadYn` / `regDt`)
- 연계업무: `docSeComNm` 표시
### 7-2. 앱·파일 배치
| 구분 | 경로 |
| ------------ | --------------------------------------------------------------------- |
| 라우트 | `app/(main)/(with-base-layout)/noti/page.tsx` |
| 페이지 | `pages/noti/ui/noti-list-page.tsx` |
| 목록 그리드 | `pages/noti/ui/noti-list.tsx` |
| 테이블 컬럼 | `pages/noti/model/noti-table-columns.tsx` |
| 상태 판정 | `pages/noti/lib/resolve-noti-status.ts` |
| Entity API | `entities/noti/api/noti-service.ts` |
| Entity Hook | `entities/noti/api/queries.ts` → `useFindMyAsNotiList`, `useReadNoti` |
| Entity Model | `entities/noti/model/noti-interface.ts` |
화면 레이어(`pages/noti`)·Entity(`findMyAsNotiList`, `readNoti`) 구현 완료.
### 7-3. 영역별 UI 매핑
| 영역 | 컴포넌트 | 데이터 |
| ---- | ------------------- | -------------------------------------------------------------- |
| A | `noti-list-page` | 로컬 state → `NotiSearchDto` |
| B | DataTable + columns | `useFindMyAsNotiList` → `content[]`. 처리 버튼 → `useReadNoti` |
### 7-4. 다이얼로그·라우팅
| 항목 | 내용 |
| ----------- | --------------------------------------------------------------------- |
| 다이얼로그 | 없음 (목록 전용) |
| 목록 라우트 | `/noti` |
| 상세 이동 | 처리 버튼 → `readNoti(notiId)` 후 `notiUrl` (절대/상대 경로 형식 TBD) |
### 7-5. 데이터 흐름
```
BEGIN
// 최초 진입
SET 기간 = 최근 1개월 // startDt / endDt 전달
CALL findMyAsNotiList
DISPLAY 영역 B
ON [검색] CLICK DO
CALL findMyAsNotiList // → 영역 B 갱신
END ON
ON 페이지 CHANGE DO
CALL findMyAsNotiList
END ON
ON 영역 B [처리] 버튼 CLICK DO
CALL readNoti(notiId) // → 영역 B 상태 갱신 (invalidate)
IF NOT notiUrl THEN
// no-op (읽음 처리는 수행됨)
ELSE
NAVIGATE notiUrl
END IF
END ON
END
```
@@ -0,0 +1,441 @@
# 화면설계서: 이전기본계획조회 (기본 계획 찾기)
## 1. 기본 정보
| 항목 | 내용 |
| ---------- | --------------------------------------------------------------- |
| 버전 | 0.2 |
| 프로세스명 | UI설계 |
| 화면명 | 이전기본계획조회 (기본 계획 찾기) |
| 화면 유형 | [v] 조회 [ ] 입력 [ ] 수정 [ ] 삭제 [ ] 출력 |
| 메뉴 경로 | 하수도기본계획 등록·수정 > 사업개요 > [이전기본계획조회] Dialog |
---
## 2. 화면 목적
하수도기본계획 등록·수정 화면에서 **이전(기수립) 기본계획** 수치와 관련 보고서를 **조회·다운로드**한다. 시도·구군·연도·처리시설을 선택한 뒤 총설·처리구역별 현황을 표시하고, 분류 트리에서 기본계획 파일을 내려받는다. **부모 사업개요 폼에는 수치를 반영하지 않는다**(레거시 `bscPlnPopup.jsp`와 동일).
---
## 3. 화면 구성
### 3-1. 전체 레이아웃
부모: 하수도기본계획 등록/수정 폼 → 사업개요 섹션의 `[이전기본계획조회]` 버튼으로 Dialog 오픈.
```
┌─────────────────────────────────────────────────────────────────────────────────┐
│ Dialog 타이틀: 기본 계획 찾기 [닫기] │
├─────────────────────────────────────────────────────────────────────────────────┤
│ [영역 A] 검색 필터 │
│ 시도 ▼ 구군 ▼ 연도 ▼ 처리시설 ▼ [조회] │
├─────────────────────────────────────────────────────────────────────────────────┤
│ [영역 B] 기본계획파일 │
│ ┌──────────────────────┬────────────────────────────────────────────────────┐ │
│ │ [영역 B-1] 분류 트리 │ [영역 B-2] 파일 목록 │ │
│ │ (약 40%) │ (약 60%) │ │
│ │ └ 노드… │ 파일명 / 다운로드 │ │
│ └──────────────────────┴────────────────────────────────────────────────────┘ │
├─────────────────────────────────────────────────────────────────────────────────┤
│ [영역 C] 총설 │
│ ┌────────┬──────────────당초──────────────┬──기준──┬──────────────변경──────────────┐ │
│ │ 구분 │ 1단계 │ 2단계 │ 3단계 │ 4단계 │ 기준 │ 1단계 │ 2단계 │ 3단계 │ 4단계 │ │
│ ├────────┼───────┼───────┼───────┼───────┼────────┼───────┼───────┼───────┼───────┤ │
│ │계획목표│ 년 │ 년 │ 년 │ 년 │ 년 │ 년 │ 년 │ 년 │ 년 │ │
│ │년도 │ │ │ │ │ │ │ │ │ │ │
│ └────────┴───────┴───────┴───────┴───────┴────────┴───────┴───────┴───────┴───────┘ │
├─────────────────────────────────────────────────────────────────────────────────┤
│ [영역 D] 처리구역별 현황 │
│ ┌────────┬──────────────당초──────────────┬──기준──┬──────────────변경──────────────┐ │
│ │ 구분 │ 1~4단계(+연도헤더) │ 기준 │ 1~4단계(+연도헤더) │ │
│ ├────────┼────────────────────────────────┼────────┼────────────────────────────────┤ │
│ │ 하수처리인구 … 배제방식 (읽기 전용 행) │ │
│ └────────┴────────────────────────────────┴────────┴────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────────────────┘
```
### 3-2. 화면 데이터 흐름
```
BEGIN
// 부모 폼 — 사업개요
ON [이전기본계획조회] 버튼 CLICK DO
OPEN PreviousPlanLookupDialog
// 프리필: 부모 폼 sewerBscPlan.sido / gugun / admdstCd
CALL findSidoCombo()
DISPLAY 시도 옵션 (영역 A)
IF 시도 프리필 THEN
CALL findGugunCombo(sidoCd)
DISPLAY 구군 옵션 (영역 A)
CALL getLvNowDmgMtncGnsvy({ level: "1", ctpvNm })
// TBD: useLvNowDmgMtncGnsvy enabled — level별 필수 파라미터만 검사하도록 조정
IF 구군 프리필 THEN
CALL getLvNowDmgMtncGnsvy({ level: "2", ctpvNm, sggNm })
DISPLAY 연도 옵션 (영역 A) // children 중 level=3 노드의 gnsvyYr
CALL getClsfSystm({ clsfSystmNm: gugunNm })
DISPLAY 분류 트리 (영역 B-1)
END IF
END IF
END ON
// 영역 A: 시도 변경
ON 영역 A 시도 CHANGE DO
RESET 구군 / 연도 / 처리시설
CALL findGugunCombo(sidoCd)
CALL getLvNowDmgMtncGnsvy({ level: "1", ctpvNm })
// 구군 미선택 → 연도·처리시설 옵션 비움, 트리 빈 안내
END ON
// 영역 A: 구군 변경
ON 영역 A 구군 CHANGE DO
RESET 연도 / 처리시설
CALL getLvNowDmgMtncGnsvy({ level: "2", ctpvNm, sggNm })
DISPLAY 연도 옵션 (영역 A) // level=3 노드 → gnsvyYr
CALL getClsfSystm({ clsfSystmNm: sggNm })
DISPLAY 분류 트리 (영역 B-1)
END ON
// 영역 A: 연도 변경
ON 영역 A 연도 CHANGE DO
RESET 처리시설
CALL getLvNowDmgMtncGnsvy({ level: "3", ctpvNm, sggNm, gnsvyYr })
DISPLAY 처리시설 옵션 (영역 A) // level=3 노드 children → swtrmtFcltCd / swtrmtFcltNm
END ON
// 영역 A: 조회
ON [조회] 버튼 CLICK DO
VALIDATE 시도, 구군, 연도(targetYear), 처리시설(swtrmtFcltCd)
CALL getNowDmgMtncGnsvy({ swtrmtFcltCd, ctpvNm, sggNm, targetYear })
DISPLAY 총설 (영역 C) // 응답[0]의 planYr / planYrDt* / planYrDc*
DISPLAY 처리구역별 현황 (영역 D) // 응답[0]의 지표 Dt1~4 / base / Dc1~4
END ON
// 영역 B: 트리 노드 선택
ON 영역 B-1 노드 CLICK DO
CALL getFile({ clsfSystmSn, sort, vetPrcsYn }) // Response DTO TBD
DISPLAY 파일 목록 (영역 B-2)
END ON
// 영역 B: 파일 다운로드
ON 영역 B-2 파일 CLICK DO
CALL getFilePrcs(fileSn) // 파일 메타(경로·제목) — Response TBD
CALL fileDownload({ filePath, fileName })
// 브라우저 다운로드 트리거
END ON
ON [닫기] DO
CLOSE PreviousPlanLookupDialog
// 부모 폼 값 변경 없음
END ON
END
```
---
## 4. 영역 A — 검색 필터
구성: **시도 · 구군 · 연도 · 처리시설** (+ 조회).
- 시도·구군: `adstdstr` 콤보 (기존 스펙 유지)
- 연도·처리시설: 각각 `useLvNowDmgMtncGnsvy`를 **별도 호출**. `level`에 따라 반환 계층이 달라진다.
### 4-1. 필드 정의
| 표시명 | 입력 유형 | 필수 | 기본값 | API 파라미터 매핑 | 비고 |
| -------- | --------- | ---- | ------------------------- | ------------------------------------------------ | -------------------------------------------------------------- |
| 시도 | Select | Y | 부모 `sewerBscPlan.sido` | `ctpvNm`(표시명), 코드는 `adstDstrCd` | `useFindSidoCombo` |
| 구군 | Select | Y | 부모 `sewerBscPlan.gugun` | `sggNm`(표시명), 코드는 `adstDstrCd` | `useFindGugunCombo(sidoCd)` |
| 연도 | Select | Y | 없음 | `gnsvyYr` / 조회 시 `targetYear` | `useLvNowDmgMtncGnsvy({ level: "2", ctpvNm, sggNm })` |
| 처리시설 | Select | Y | 없음 | `swtrmtFcltCd` ← 옵션 value, 라벨 `swtrmtFcltNm` | `useLvNowDmgMtncGnsvy({ level: "3", ctpvNm, sggNm, gnsvyYr })` |
> 처리시설은 `bns-if` `useFacilityList`를 **사용하지 않는다**.
### 4-2. 버튼
| 버튼명 | 동작 |
| ------ | -------------------------------------------------------- |
| 조회 | 필수값 검증 후 `getNowDmgMtncGnsvy` 호출 → 영역 C·D 갱신 |
| 닫기 | Dialog 종료 (부모 미반영) |
### 4-3. `lvNowDmgMtncGnsvy` level 캐스케이드
| 트리거 | Request `level` | Request 파라미터 | UI에 쓰는 응답 | 옵션 추출 |
| --------- | --------------- | ---------------------------- | --------------- | ------------------------------------------------------------------------------ |
| 시도 선택 | `"1"` | `ctpvNm` | (하위 초기화용) | 연도·처리시설 Select 리셋. 구군은 `findGugunCombo` |
| 구군 선택 | `"2"` | `ctpvNm`, `sggNm` | 연도 Select | 트리에서 `level === 3` 노드의 `gnsvyYr` |
| 연도 선택 | `"3"` | `ctpvNm`, `sggNm`, `gnsvyYr` | 처리시설 Select | 선택 연도(`level === 3`) 노드의 `children[]` → `swtrmtFcltCd` / `swtrmtFcltNm` |
상위 변경 시 하위 선택값·옵션을 RESET한다 (시도→구군·연도·시설 / 구군→연도·시설 / 연도→시설).
---
## 5. 영역 B — 기본계획파일
### 5-1. 트리 (B-1)
| 표시명 | Field | 비고 |
| ------ | --------------- | ------------------------ |
| 분류명 | `clsfSystmNm` | `ClsfSystmResponseDto` |
| 노드키 | `clsfSystmSn` | 선택 시 파일 목록 조회 |
| 상위키 | `upClsfSystmSn` | 클라이언트에서 트리 조립 |
| 정렬 | `sortSeq` | |
| 경로 | `path` | |
- 조회 파라미터: `clsfSystmNm` = 선택 구군명(레거시와 동일). `upClsfSystmSn`은 하위 전개 시 TBD.
- 시도·구군 미선택 시: 「시도와 구군을 선택하세요.」 안내.
### 5-2. 파일 목록 (B-2)
| 표시명 | Field | 비고 |
| ------ | ----- | ------------------------------------------------------------------- |
| 파일명 | TBD | `getFile` Response DTO가 `unknown` — 백엔드 스키마 확정 후 매핑 |
| (기타) | TBD | 레거시: 트리 선택 후 목록 표시, 클릭 시 `fileprcs` → `fileDownload` |
### 5-3. 버튼·상호작용
| 동작 | 설명 |
| -------------- | -------------------------------------------------------------- |
| 트리 노드 클릭 | `getFile({ clsfSystmSn, … })` → B-2 목록 |
| 파일 클릭 | `getFilePrcs(fileSn)` → `fileDownload({ filePath, fileName })` |
| 빈 목록 | 「트리에서 항목을 선택하세요.」 / 「파일이 없습니다.」 |
---
## 6. 영역 C — 총설
### 6-1. 테이블 구조
| 행(구분) | 열 매핑 (당초1~~4 / 기준 / 변경1~~4) |
| ------------ | ------------------------------------------------------------------------------ |
| 계획목표년도 | `planYrDt1planYrDt4` ~~/~~ `planYr` ~~/~~ `planYrDc1planYrDc4` (+ `년` 접미사) |
- 헤더: 당초(1~~4단계) · 기준 · 변경(1~~4단계)
- 데이터 소스: `getNowDmgMtncGnsvy` 응답 배열의 **첫 번째** 요소
- 읽기 전용
---
## 7. 영역 D — 처리구역별 현황
### 7-1. 행 정의 (표시명 → Field 접두사)
각 행은 `Dt1Dt4` ~~/ (접미사 없음=기준) /~~ `Dc1Dc4` 셀로 표시한다. 숫자는 천단위 콤마, 없으면 `-`.
| 표시명 | Field 접두사 | 비고 |
| ------------------------ | -------------------- | ---------------------------------------------- |
| 하수처리인구(인) | `swtrmtPpltnCnt` | |
| 자연적하수처리인구수(인) | `natrSwtrmtPpltnCnt` | |
| 사회적하수처리인구수(인) | `scilSwtrmtPpltnCnt` | |
| 하수처리구역면적 | `swtrmtZoneArea` | |
| 물사용량원단위 | `wtrUsqtyOrgnUnit` | |
| 오수전환율(%) | `drtwSwtcRt` | |
| 변동부하율(%) | `flctnLodRt` | |
| 오수원단위 | `drtwOrgnUnit` | |
| 계획하수량합계(㎥/일) | `planSwageQntSum` | |
| 생활오수(㎥/일) | `lvngDrtwSum` | |
| 지하수(㎥/일) | `ugwtSum` | |
| 공장폐수(㎥/일) | `fctryWwtSum` | |
| 관광오수(㎥/일) | `toursmDrtwSum` | |
| 군부대(㎥/일) | `mtbsSum` | |
| 연계처리수(㎥/일) | `linkPrcsCntSum` | |
| 기타오수(㎥/일) | `etcDrtwSum` | |
| 지하수사용량(㎥/일) | `ugwtUseSum` | |
| 시설용량(㎥/일) | `fcltCpctSum` | |
| 배제방식 | `exclsMethExpln` | 문자열; 단계별 `*Dt*`/`*Dc*` 존재 시 동일 규칙 |
헤더 3행째 연도: 영역 C와 동일하게 `planYrDt*` / `planYr` / `planYrDc*` 표시.
---
## 8. API/DTO 명세
### 8-1. 공통
| 항목 | 값 |
| --------------- | ---------------------------------------------------- |
| DC Base | `/dc-service/api/v1` (`ENDPOINT.DC_SERVICE`) |
| AS adstdstr | `/as-service/api/v1/adstdstr` |
| 클라이언트 모듈 | `@/entities/dc` (`dcService`), `@/entities/adstdstr` |
> 영역 A 처리시설은 `bns-if`를 사용하지 않음.
### 8-2. 시도·구군 콤보 (non-DC)
| 기능 | Method | URL | Request DTO | Response DTO | API |
| -------- | ------ | ----------------------------------- | ------------------------ | -------------------------------- | ---------------------------------------------------------- |
| 시도목록 | GET | `/as-service/api/v1/adstdstr/sido` | — | `CmCdAdstDstrComboResponseDto[]` | `cmCdAdstDstrService.findSidoCombo` / `useFindSidoCombo` |
| 구군목록 | GET | `/as-service/api/v1/adstdstr/gugun` | Query: `sido` (시도코드) | `CmCdAdstDstrComboResponseDto[]` | `cmCdAdstDstrService.findGugunCombo` / `useFindGugunCombo` |
### 8-3. 연도·처리시설 계층 조회 — DC
| 기능 | Method | URL | Request DTO | Response DTO | API |
| --------------- | ------ | -------------------------------------- | ---------------------------- | -------------------------------- | --------------------------------------------------------- |
| 계층형 계획목록 | GET | `/dc-service/api/v1/lvNowDmgMtncGnsvy` | `LvNowDmgMtncGnsvySearchDto` | `LvNowDmgMtncGnsvyResponseDto[]` | `dcService.getLvNowDmgMtncGnsvy` / `useLvNowDmgMtncGnsvy` |
연도 Select·처리시설 Select는 **각각** `useLvNowDmgMtncGnsvy`를 호출한다 (`level`만 다르게).
**Request (**`LvNowDmgMtncGnsvySearchDto`**)**
| 필드 | 시도(`level=1`) | 구군→연도(`level=2`) | 연도→시설(`level=3`) |
| --------- | --------------- | -------------------- | -------------------- |
| `level` | `"1"` | `"2"` | `"3"` |
| `ctpvNm` | 필수 | 필수 | 필수 |
| `sggNm` | — | 필수 | 필수 |
| `gnsvyYr` | — | — | 필수 |
**Response 노드 필드 (**`LvNowDmgMtncGnsvyResponseDto`**, 부분 optional)**
| 필드 | 등장 level | 설명 |
| -------------- | ---------- | ------------------------ |
| `level` | 1~3 | 계층 깊이 |
| `ctpvNm` | 1 | 시도명 |
| `sggNm` | 2 | 구군명 |
| `gnsvyYr` | 3 | 연도 → 연도 Select value |
| `swtrmtFcltCd` | 시설(리프) | 처리시설 코드 |
| `swtrmtFcltNm` | 시설(리프) | 처리시설명 |
| `children` | 1~3 | 하위 노드 배열 |
> **TBD**: 현재 `useLvNowDmgMtncGnsvy` `enabled`가 `level && ctpvNm && sggNm && gnsvyYr`로 고정되어 `level=1`/`2` 호출이 막힘. level별 필수 파라미터만 검사하도록 수정 필요.
>
> 예: `level=1` → `ctpvNm` / `level=2` → `ctpvNm && sggNm` / `level=3` → `ctpvNm && sggNm && gnsvyYr`
### 8-4. 기본계획 수치 조회 — DC
| 기능 | Method | URL | Request DTO | Response DTO | API |
| ---------------- | ------ | ------------------------------------ | -------------------------- | ------------------------------ | ----------------------------------------------------- |
| 현재·단계별 수치 | GET | `/dc-service/api/v1/nowDmgMtncGnsvy` | `NowDmgMtncGnsvySearchDto` | `NowDmgMtncGnsvyResponseDto[]` | `dcService.getNowDmgMtncGnsvy` / `useNowDmgMtncGnsvy` |
**Request (**`NowDmgMtncGnsvySearchDto`**)**
| 필드 | 매핑 |
| -------------- | ----------------------- |
| `swtrmtFcltCd` | 영역 A 처리시설 |
| `ctpvNm` | 영역 A 시도 표시명 |
| `sggNm` | 영역 A 구군 표시명 |
| `targetYear` | 영역 A 연도 (`gnsvyYr`) |
**Response**: 지표 필드 + `Dt1Dt4` ~~/~~ `Dc1Dc4` 접미사 스테이지 필드 (`NowDmgMtncGnsvyResponseDto`). UI는 `data[0]` 사용.
### 8-5. 분류체계 — DC
| 기능 | Method | URL | Request DTO | Response DTO | API |
| ------------ | ------ | ------------------------------ | -------------------- | ------------------------ | ----------------------------------------- |
| 분류트리조회 | GET | `/dc-service/api/v1/clsfSystm` | `ClsfSystmParamsDto` | `ClsfSystmResponseDto[]` | `dcService.getClsfSystm` / `useClsfSystm` |
**Request**: `clsfSystmNm?`, `upClsfSystmSn?`
**Response**: `clsfSystmSn`, `upClsfSystmSn`, `clsfSystmNm`, `sortSeq`, `droppAble`, `path`
> 레거시 경로 `/clsf` → 현재 클라이언트는 `/clsfSystm`.
### 8-6. 파일 목록·처리·다운로드 — DC
| 기능 | Method | URL | Request DTO / Params | Response DTO | API |
| ------------ | ------ | --------------------------------- | ------------------------------------------------------- | ----------------- | -------------------------------------------- |
| 파일목록 | GET | `/dc-service/api/v1/file` | `FileParamsDto` (`sort?`, `clsfSystmSn?`, `vetPrcsYn?`) | `unknown` **TBD** | `dcService.getFile` / `useFile` |
| 파일처리정보 | GET | `/dc-service/api/v1/fileprcs` | Query: `fileSn` | `unknown` **TBD** | `dcService.getFilePrcs` / `useFilePrcs` |
| 파일다운로드 | POST | `/dc-service/api/v1/fileDownload` | `FileDownloadParamsDto` (`filePath?`, `fileName?`) | `unknown` **TBD** | `dcService.fileDownload` / `useFileDownload` |
> **TBD**: 파일 관련 Response 스키마·다운로드 blob/헤더 처리·`fileDownload` POST body vs query 전달 방식은 백엔드/게이트웨이 확인 후 확정.
---
## 9. UI 구현 가이드
### 9-1. 기술 스택·원칙
- UI: `@common/components` — `Dialog`, `Select`, `Button`, `Table`, `Skeleton`
- 상태: Dialog 로컬 state + React Query (`entities/dc`, `adstdstr`)
- 영역 A 연도·처리시설: `useLvNowDmgMtncGnsvy`를 level별 **두 번**(또는 시도 포함 시 세 번) 호출
- 테이블: 읽기 전용 고정 행 → `@tanstack/react-table` / `DataTable` **불필요**
- 트리: jsTree 미사용 — 재귀 들여쓰기 트리
- 번들: `PreviousPlanLookupDialog`는 outline에서 `next/dynamic` 로드 권장
- 부모 폼: **수치 미반영** (조회·다운로드 only)
- 1차 구현 시 DC 미연동이면 `@faker-js/faker` mock + TODO → 이후 `dcService` 훅으로 교체
### 9-2. 앱·파일 배치
| 구분 | 경로 |
| ------------ | ------------------------------------------------------------------------ |
| 진입 버튼 | `pages/sewer-bsc-plan/ui/sections/outline-form-section.tsx` |
| Dialog | `pages/sewer-bsc-plan/ui/previous-plan-lookup-dialog.tsx` |
| 필터 | `pages/sewer-bsc-plan/ui/previous-plan/previous-plan-search-filters.tsx` |
| 파일 | `pages/sewer-bsc-plan/ui/previous-plan/previous-plan-file-section.tsx` |
| 총설 | `pages/sewer-bsc-plan/ui/previous-plan/previous-plan-summary-table.tsx` |
| 처리구역 | `pages/sewer-bsc-plan/ui/previous-plan/previous-plan-area-table.tsx` |
| 셀 매핑 유틸 | `pages/sewer-bsc-plan/lib/previous-plan-table-utils.ts` |
| mock(선택) | `pages/sewer-bsc-plan/lib/previous-plan-mock.ts` |
| DC entity | `entities/dc/api/dc-service.ts`, `queries.ts`, `model/dc-interface.ts` |
| 레거시 참조 | `adssNewOld/.../cmmn/bscPlnPopup.jsp` |
### 9-3. 영역별 UI 매핑
| 영역 | 컴포넌트 | 데이터 |
| ---- | ------------------------------ | -------------------------------------------------------------- |
| A | `previous-plan-search-filters` | adstdstr + `useLvNowDmgMtncGnsvy`(level 1·2·3) |
| B | `previous-plan-file-section` | `useClsfSystm` + `useFile` + `useFilePrcs` + `useFileDownload` |
| C | `previous-plan-summary-table` | `useNowDmgMtncGnsvy` / 조회 결과 state |
| D | `previous-plan-area-table` | 동일 |
### 9-4. 다이얼로그·라우팅
| 항목 | 내용 |
| ------------ | ------------------------------------------------------------------------ |
| 다이얼로그명 | `PreviousPlanLookupDialog` / 타이틀 `기본 계획 찾기` |
| 오픈 | 사업개요 `[이전기본계획조회]` |
| 라우트 | 없음 (모달). 부모: `/sewer-bsc-plan/regist`, `/sewer-bsc-plan/[id]/edit` |
| 선택 반영 | 없음 |
### 9-5. 데이터 흐름 (구현 요약)
```
BEGIN
ON [이전기본계획조회] CLICK DO
OPEN PreviousPlanLookupDialog (sido/gugun 프리필)
END ON
ON 시도 CHANGE DO
CALL findGugunCombo
CALL getLvNowDmgMtncGnsvy(level=1)
RESET 연도·처리시설
END ON
ON 구군 CHANGE DO
CALL getLvNowDmgMtncGnsvy(level=2) // → 연도 옵션
CALL getClsfSystm
RESET 처리시설
END ON
ON 연도 CHANGE DO
CALL getLvNowDmgMtncGnsvy(level=3) // → 처리시설 옵션
END ON
ON [조회] CLICK DO
VALIDATE
CALL getNowDmgMtncGnsvy
DISPLAY 영역 C · 영역 D
END ON
ON 트리 노드 / 파일 CLICK DO
CALL getFile → getFilePrcs → fileDownload // Response TBD
END ON
END
```
---
## 10. 미확정 (TBD) 추적
| ID | 항목 | 비고 |
| --- | -------------------------------------------------------- | -------------------------------------------------------------------- |
| T1 | `useLvNowDmgMtncGnsvy` enabled을 level별 필수값으로 분기 | `1`: ctpvNm / `2`: +sggNm / `3`: +gnsvyYr |
| T2 | `getFile` / `getFilePrcs` / `fileDownload` Response DTO | 현재 `unknown` |
| T3 | 파일 다운로드 UX (blob, Content-Disposition, 게이트웨이) | 레거시 apigateway 직접 호출과 차이 |
| T4 | `clsfSystm`의 `upClsfSystmSn` 점진 로드 여부 | flat 목록 vs 계층 API |
| T5 | 1차 mock vs 즉시 `dcService` 실연동 | 마이그레이션 플랜은 mock 우선, entity는 준비됨 |
| T6 | 부모 폼 수치 반영 | 요구 없음(레거시 동일). 요청 시 별도 스펙 |
| T7 | `level=1` 응답 UI 활용 여부 | 시도 선택 시 호출하나 구군은 adstdstr — 응답은 캐시·검증용일 수 있음 |
+22 -7
View File
@@ -1,8 +1,16 @@
import { NextRequest, NextResponse } from "next/server";
import { AUTH_USER_ID, CLAIM_NAME, PORT, PROXY_HOST, SERVER_API_URL, SITE_ID } from "@/shared/config";
import {
AUTH_USER_ID,
CLAIM_NAME,
PORT,
PROXY_HOST,
SERVER_API_URL,
SITE_ID,
} from "@/shared/config";
const serverApiUrl = process.env.SERVER_API_URL;
const dcServiceApiUrl = process.env.DC_SERVICE_API_URL;
// CSP 헤더 설정 함수 (img-src만)
function addSecurityHeaders(response: NextResponse): NextResponse {
@@ -22,7 +30,15 @@ export function middleware(req: NextRequest) {
if (pathname.startsWith("/server")) {
const queryParams = searchParams.toString();
const newUrl = `${serverApiUrl}${pathname.replace("/server", "")}${
let serverUrl: string | undefined;
if (pathname.includes("/dc-service")) {
serverUrl = dcServiceApiUrl;
} else {
serverUrl = serverApiUrl;
}
const newUrl = `${serverUrl}${pathname.replace("/server", "")}${
queryParams ? `?${queryParams}` : ""
}`;
@@ -34,7 +50,6 @@ export function middleware(req: NextRequest) {
return addSecurityHeaders(response);
}
// tus-js-client PATCH 요청: Location 헤더로 /server 없이 반환된 경로 직접 처리
// (예: /attach-service/api/v1/tus/upload/{id})
if (pathname.startsWith("/attach-service")) {
@@ -56,10 +71,10 @@ export function middleware(req: NextRequest) {
return addSecurityHeaders(response);
}
// if (pathname === "/") {
// const response = NextResponse.redirect(new URL("/dashboard", req.url));
// return addSecurityHeaders(response);
// }
if (pathname === "/") {
const response = NextResponse.redirect(new URL("/dashboard", req.url));
return response;
}
logMessages.push("\n--------------------------------\n");
console.log(logMessages.join("\n"));
+45
View File
@@ -1,8 +1,53 @@
import type { NextConfig } from "next";
const subDomain = process.env.NEXT_PUBLIC_SUB_DOMAIN || "http://localhost:13000";
const webhwpCtrlBase = (
process.env.NEXT_PUBLIC_WEBHYP_CTRL_URL || "http://hwp.onasys.co.kr/webhwpctrl"
).replace(/\/$/, "");
const webhwpAssetPrefixes = ["js", "hwpsdk", "dist", "commonFrame", "wasm"] as const;
const nextConfig: NextConfig = {
output: "standalone",
reactStrictMode: true,
transpilePackages: ["@common/assets"],
experimental: {
globalNotFound: true,
},
async rewrites() {
return {
beforeFiles: [
{
source: "/_next/static/:path*",
destination: `${subDomain}/_next/static/:path*`,
has: [
{
type: "header",
key: "referer",
value: "(.*)/cms(.*)",
},
],
},
],
afterFiles: [
{
source: "/cms/:path*",
destination: `${subDomain}/cms/:path*`,
},
...webhwpAssetPrefixes.map((prefix) => ({
source: `/webhwpctrl/${prefix}/:path*`,
destination: `${webhwpCtrlBase}/${prefix}/:path*`,
})),
{
source: "/webhwpctrl/file/:path*",
destination: `${webhwpCtrlBase}/file/:path*`,
},
],
fallback: [],
};
},
};
export default nextConfig;
+3
View File
@@ -20,10 +20,12 @@
"@faker-js/faker": "^9.9.0",
"@frontend-opensource/use-react-hooks": "^1.1.4",
"@hookform/resolvers": "^4.1.3",
"@radix-ui/react-tooltip": "^1.2.8",
"@tanstack/react-query": "^5.75.5",
"@tanstack/react-query-devtools": "^5.75.5",
"@tanstack/react-table": "^8.21.2",
"axios": "^1.8.1",
"class-variance-authority": "^0.7.1",
"dayjs": "^1.11.13",
"js-cookie": "^3.0.5",
"lucide-react": "^0.474.0",
@@ -34,6 +36,7 @@
},
"devDependencies": {
"@eslint/eslintrc": "^3",
"@hookform/devtools": "^4.4.0",
"@types/js-cookie": "^3.0.6",
"eslint": "^9.0.0",
"eslint-config-next": "15.3.8",
Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 132 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Before

Width:  |  Height:  |  Size: 4.4 KiB

After

Width:  |  Height:  |  Size: 4.4 KiB

Before

Width:  |  Height:  |  Size: 5.5 KiB

After

Width:  |  Height:  |  Size: 5.5 KiB

Before

Width:  |  Height:  |  Size: 6.5 KiB

After

Width:  |  Height:  |  Size: 6.5 KiB

Before

Width:  |  Height:  |  Size: 6.5 KiB

After

Width:  |  Height:  |  Size: 6.5 KiB

Before

Width:  |  Height:  |  Size: 5.4 KiB

After

Width:  |  Height:  |  Size: 5.4 KiB

Before

Width:  |  Height:  |  Size: 5.5 KiB

After

Width:  |  Height:  |  Size: 5.5 KiB

Before

Width:  |  Height:  |  Size: 3.2 KiB

After

Width:  |  Height:  |  Size: 3.2 KiB

Before

Width:  |  Height:  |  Size: 3.5 KiB

After

Width:  |  Height:  |  Size: 3.5 KiB

Before

Width:  |  Height:  |  Size: 3.5 KiB

After

Width:  |  Height:  |  Size: 3.5 KiB

Before

Width:  |  Height:  |  Size: 4.0 KiB

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 483 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 483 KiB

+63
View File
@@ -0,0 +1,63 @@
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 538 755">
<defs>
<style>
.cls-1 {
fill: #fff;
}
</style>
</defs>
<!-- Generator: Adobe Illustrator 28.7.9, SVG Export Plug-In . SVG Version: 1.2.0 Build 218) -->
<g>
<g id="Layer_1">
<g id="han" data-label-shift="dx,dy">
<path class="cls-1" d="M159.2,197l-5,5.8,5.1,3.7,13.2,9.7-7.3,3.5-8.2-1.2-9.4,1.4,1.4,4.9-3.5,7.3,3.8,2.6-.9,4.7,8.9-2.3,4.2-3.7,5.2,4.2-6.1,2.3.9,12,3,7-.9,3.3-.5,1.6,5.4,6.8,5.2,13.4h-3.6c0-.1,6.4,3.8,6.4,3.8l4.8,6h1.2l3.6-5.4,3.6-.6,13.8,5.9,19.7-1.1,4.6-6.5,3-5.2,8.2-1.7,11.7-17.8,7.1,1.9,4.9,10,13.2,9.6,3.8,13-1.4,12.2-.5,9.5,1.6,1.1-.6,1.3v1.1c.1,0-2.2,2.4-2.2,2.4l-17.5,7.4,7.6,19.2,16.3,1.1,8.4,10.8,12.6.6,4.2-5.2-4.6-7.9-9.2-6.2,12.1-7.1,6.4,5.2,1.3-5.6-6.6-6.5,17.5-5.8,4.8,4.4,4.8-2.1-4.7-6.5,4.5-8.8,6.3-.4,4.7-3,8,3,24.1,4.5,11.5-7.8-2.8-6.4,6.5-11.7,10.5-5.5,7.6-7.9,10.2-2.3,13.4,4.6,4.4-8,12.4,8.2,3.4-3.1.2-15.2.4-11.3,13.4-3.2,4.6-.4-1.9,9.9,9.8,4.6,1.6,12.8,12.2,9.2,9.8-8.4,15-8.9-3.7-19-21.8-40.6-5.7-10.6,1.2-6.8-4.9-6.1-4-4.9,1.2-5.2-26.3-33.1-5.8-12.1-7.1-14.9-11.9-20.9-2.9-9.4-2.1-6.7-1.8-5.2-8.7-25.5-8.6-14.4-.9-11-5.2-11-3-6.3-6,6.5-5.2,22.8-9.8,11-5.5,2.8-7.4,3.7-17.1.5-12.7-1.6-8.2,2.3-5.2-3.4-3.4-2.2-18.8-2.3-21.8,4.5-19-3.7-3.5,4.7-11.2-7.3-5.2,4.2-6.1-.7-11.5,3.5-14.1,10.8-3.7,10.1-12.9,9.8-4,7.3-8.5,6.8-2.3,1.9-9.1,4.5-4,18.3-9.2,11.5-14.3,1.2-2.1,30,5.6,1.4,3.3,9.2-1.4,2.7.9,2.6,2.9-.7,1.8,3.2-4.5,2.2,1.7,8.6,3.8,6.9,8.9,3.4Z"/>
</g>
<g id="yeongsan" data-label-shift="dx,dy">
<path class="cls-1" d="M57.4,578.4s.2,1.4.2,2.3.7,1.6.7,1.9.5,1.4.7,2.3c.2.9,1.2,1.2,1.2,1.2h0s.5,1.4.5,1.4c0,0-.5.7-.9,1.4-.5.7,1.6.9,1.6.9l2.8-.7s1.4-.7,1.4-1.2,0,0-.2-.7c-.2-.7-.5-.7-.9-1.2-.5-.5.5-.2.5-.2l.5.2,2.6-.5s.9-.5,1.4-.7c.5-.2-.2-.5-.2-.9s-.2-1.2-.2-1.2l.2-.9v-1.2c0-.5.7-.7.9-1.2.2-.5.5-.7.9-1.2.5-.5,0-.7,0-1.6s-.5-.5-.5-.9-.5,0-.5,0l-.9.5-.9.7s-.2.9-.5,1.2c-.2.2-1.4.2-1.4.2,0,0-.2-.5-1.2-.9-.9-.5,0,0-.5,0s-1.2-.2-1.2-.2c0,0-1.2-.7-1.6-.9-.5-.2-.5-.9-.5-.9h-1.2s-1.9,1.4-2.8,1.9c-.9.5,0,1.2,0,1.2Z"/>
<path class="cls-1" d="M45.2,585.7c.2.2,0,.2.7.9.7.7.5,1.6.9,1.6s.2-.5,1.2,0c.9.5,1.4.5,1.9.7.5.2,1.6.9,1.9.9s1.4.7,1.4.9-.2.2,0,.5c.2.2,0,.5.5,1.4.5.9,1.9,2.6,1.9,2.6,0,0-.7.7.5.5,1.2-.2,1.9-.2,1.9-.9s.2-1.2.2-1.4-.2-.2-.5-1.2c-.2-.9-.7-1.6-.7-1.6,0,0,1.2-.2,0-1.2-1.2-.9-.2-1.2-1.2-.9-.9.2-1.9.2-1.9.2-.2-1.2-.2-1.9-.2-1.9l-.5-.5.7-1.4h0c.5,0,.9-.2,1.2-.2s.9-.7.9-.7c0,0,.2-.2,0-.7-.2-.5-.2-.2-.9-.7s-1.6-.7-1.6-.7l-2.1-1.2-1.4-.9c-.7-.2-2.6.9-2.6.9,0,0,.9-.5,0,.7-.9,1.2-2.3,1.9-2.3,1.9,0,0-.2.5,0,.9.2.5,0,1.2.2,1.4Z"/>
<path class="cls-1" d="M28.6,585.5s0,.7,1.2.7h2.1c.5,0,.9.7.9.7v1.9l1.2.7s1.4,0,1.9-.5c.5-.5.5-.7.5-.7l-.5-1.4,2.3-.7s.5-.5.7-1.2c.2-.7-.2-1.2,0-2.3.2-1.2,0-2.8,0-2.8,0,0,.9-1.4.9-2.1s1.9-2.6,1.9-2.8h0v-.7h-1.4c-.2,0-1.7.5-2.1.7-.5.2,0,0-.9,1.2s-.2,1.6-.2,1.6l-1.9.5-1.4.7-.9.2s-1.2-.2-2.1-.2-.5.9-.5.9c0,0-1.2,1.4-1.9,1.6-.7.2-.7.7-.7.7,0,0,.9,2.3.9,2.8v.5Z"/>
<path class="cls-1" d="M41.7,591.4c-.5.2-.7-1.2-.5,0,.2,1.2,1.2,2.1,1.2,2.1l1.4.9s.9-.2,1.4,0c.5.2.9,0,.9,0l1.9.7v.2s.7-.2.5-1.6c-.2-1.4,0-1.4,0-1.4l-.7-.9-2.6-1.4h0s-2.8-.7-3-.5c-.2.2-.5-.2-.5.2s.5,1.4,0,1.6Z"/>
<path class="cls-1" d="M34.2,597.7s0,0,0,0c0,0,0,0,0,0Z"/>
<path class="cls-1" d="M45,598.9l-.7-.7-.5-.9s.2-1.4-.2-1.4-1.9-.5-1.9-.5l-1.4-.7h0s-1.4,0-1.4,0c0,0-.9,0-1.2.7-.2.7-.9.5-.9.9s-2.1,1.2-2.5,1.4c0,0,.2.2.4.5.5.7.5,1.4,1.2,1.4s2.1.2,2.3,0c.2-.2.9-.7,1.2-.5.2.2.5.5.5.9s-.5,1.2-.5,1.6.5,0,0,.5c-.5.5.2,1.4.5,1.6.2.2-.7,2.1-.7,2.1,0,0-.5.5-.5.7s1.4.7,1.6,0c.2-.7.7-1.2.9-1.4.2-.2.9-.5.9-.5,0,0-.5.2.7.2s2.1.2,2.1-.5v-1.9s-.2-1.2,0-1.4c.2-.2,0-2.3,0-2.3Z"/>
<path class="cls-1" d="M18.5,619.7c.7,0,1.9-.9,2.3,0,.5.9,1.9,2.6,1.9,2.6,0,0,.2-.2,1.4,0,1.2.2,1.2.5,2.1,0,.9-.5,1.4-1.4,1.4-1.4l1.2-1.2,3.3-1.4s-.2-.7-.7-2.1c-.5-1.4-.7-2.1-.7-2.1,0,0,1.2.2.5-.9-.7-1.2-.9-1.9-.9-1.9l-.5-1.6h0s-.7-.9-.7-.9l-2.1.2s-.2,1.2,0,1.9c.2.7.2.9,0,1.4-.2.5-.7-.5-1.2,0-.5.5-2.3.2-2.3.2h-1.2l-.9,1.4-1.2.9-2.3.9-2.1,1.4s-.5,0,0,.9c.5.9,2.1,1.6,2.8,1.6Z"/>
<path class="cls-1" d="M33.1,624h-.9l-1.4-.7-2.1.7s-.9,1.2-.9,1.6.7,1.9,1.4,2.3c.7.5,1.6.7,1.9,1.6.2.9.2,1.9.2,1.9,0,0,1.9.7,2.3-.7.5-1.4.2-2.3.7-2.6.5-.2,1.9-1.6,1.9-1.6,0,0-.5-.5.7-.5s1.6-.5,1.6-.7v-1.9l-.9-.9h.9l.7-.9s.2-.7,0-1.2c-.2-.5-.5-1.9-.5-1.9l-2.6.5h0l-1.4,1.4-.5.9s.2.9,0,1.2c-.2.2-1.2,1.4-1.2,1.4Z"/>
<path class="cls-1" d="M65.6,620.2l1.9-.7-2.1-2.6-3.5-1.9h0s-3.3.7-3.3.7l1.6,2.1.9,1.4s-.5.5-.9.9c-.5.5-1.6.7-1.6.7,0,0-.5.5-.5.9s-.9,0-2.1.7c-1.2.7-4.5,1.9-4.5,1.9h-.9c.9,0,1.6,2.6,2.3,2.6h3.1s-.2-.5.9-.7c1.2-.2,2.6-1.2,2.6-1.2,1.4.2,2.3-.7,3,.5.7,1.2,1.4.9,1.6,1.4.2.5,1.2,2.1,1.2,2.1l-.7,2.6s1.2.9,1.6.7c.5-.2,1.9-1.4,1.9-1.4l.9-1.9s-.5-1.4,0-1.9c.5-.5-1.6-1.4-1.6-1.4l-2.8-.7-1.9-2.6v-1.2l2.8-1.2Z"/>
<path class="cls-1" d="M64.2,635.5v-1.6s-3.3,1.4-3.3,1.6.9,1.6.9,1.6h1.6l.7-1.6Z"/>
<path class="cls-1" d="M59.8,639.2c0,1.2.5,2.8,1.2,3,.7.2,1.6,0,1.6,0v-3l-1.6-.9s-1.2-.2-1.2.9Z"/>
<path class="cls-1" d="M38.4,638.3c1.2,0,2.8-4.5,2.8-4.5v-1.4h0s-3.5,0-3.5,0l-2.1,1.4-3.5.7s-.2,1.9,1.4,1.9.7-.1.6-.2c0,0,.3,0,.6.2,1.6.5,3.3.7,3.3,1.2s-.7.7.5.7Z"/>
<path class="cls-1" d="M15.4,630.1h0s0,0,0,0h0Z"/>
<path class="cls-1" d="M7,642.7c.2-.5,1.2-.7,1.2-1.4s-1.6-2.6-.5-3.1c1.2-.5,2.6-.9,2.8-1.2.2-.2,1.2-.7,1.6-.5s.9.9.9.9l1.4-.5.5-.9s.2-.9.5-1.4c.2-.5.7-1.9.7-1.9v-1.2l-.7-1.6c-.3.2-2.6,2.1-2.8,2.3-.2.2-3,1.2-3.3,1.2s-3.1.2-3.1.2l-3.8.5-2.6,1.9,1.9,2.1s-.2,1.9,0,2.1c.2.2-.5,1.2.5,1.6.9.5,1.6.9,1.6.9,0,0,2.8.2,3-.2Z"/>
<path class="cls-1" d="M16.6,649.1c0-.7-1.2-1.6-1.2-1.6l-.7-.7-.9-.9s-.2-1.2-.2-1.4-.7-.9-.7-.9c0,0-2.3.2-2.3.5s-.7.7-.7.7c0,0-.2.7-1.6.7s-2.8-.5-2.6,0c.2.5-.2.9-.2,1.6s-.5,1.9-.5,1.9v1.2s.2,1.2.7,1.4c.5.2,1.2.5,1.4.7.2.2,1.4.9,1.2,1.4-.2.5,2.3.2,2.3.2l.5-.5c.2-.2,1.9-1.2,1.9-1.2,0,0,0-.9.5-.9s3.3-.5,3.3-.5v-1.6Z"/>
<polygon class="cls-1" points="12.9 643.4 12.9 643.4 12.9 643.4 12.9 643.4"/>
<path class="cls-1" d="M27.7,639.9c.5.5,1.4,1.6,2.1,1.9.7.2,1.2.5,1.4,1.2.2.7.2,1.4.5,2.1.2.7,1.9.7,1.9,1.2s.5-.2,1.4,0c.9.2.2-.2,1.6,1.2,1.4,1.4,2.3,2.1,2.6,2.6.2.5.9,0,.9,0l1.2-.9s-.2-1.6,0-1.6.2-2.1.2-2.3-.5-2.3-.5-2.3c0,0-1.2-1.4-1.4-1.4s-2.1-.7-2.1-.7l-1.2-1.2-.9-1.2-1.4-.5h0l-3.7-.7h-2.1l-1.2,1.6s.2.7.7,1.2Z"/>
<path class="cls-1" d="M32.6,663.4c.5.2,2.3.5,2.8.5s1.6-.2,1.9-.5c.2-.2.9-.2,1.6-.2s3.5.2,3.5.2c0,0,.5-.7.2-1.4-.2-.7-.9-1.4-.9-1.4l-.2-.7-.7-.5.7-1.2v-.9s-.7-.5-1.4-.5-1.4.2-1.4-.2-.9-1.9-.9-1.9l-1.4.7h0c-.9.5-1.9.7-2.1.9-.2.2-3.3.2-3.1.7.2.5.7,1.2.9,1.4.2.2.9,1.6.9,1.6,0,0-.5,1.6-.5,1.9s-.5,1.2,0,1.4Z"/>
<path class="cls-1" d="M21.3,670.4c0-.2,0-1.4.5-1.6.5-.2.7-.5.7-.7s-.7-1.2-.7-1.4-1.2-1.2-1.2-1.2l-.5-1.2-.2-1.2-.2-1.9h0s-.9-1.9-1.2-1.9-1.4-.2-1.4,0-.5.9-.5.9v.7c0,.2-.2.7,0,1.2.2.5-.2,1.4,0,1.6.2.2.2.7.5,1.4.2.7.7,1.2.7,1.4s-.2,1.2-.2,1.2c0,0-.5-.7-.5.5s-1.9,1.9-.5,2.1c1.4.2,2.8.5,3,.5s1.6-.2,1.6-.5Z"/>
<path class="cls-1" d="M27.4,673s-.5-.9,0-1.6c.3-.5.5-.9.7-1.2.2-.5.9-.5.9-.9s.5-2.3,0-2.8c-.5-.5-.9-1.6-1.4-2.3-.5-.7-.2-.9-1.2-1.6-.9-.7-1.9-1.2-1.9-1.2l-1.2.2h0s-.7,2.1-.7,2.3.2,2.3.7,2.6c.5.2,1.6,1.4,1.9,1.9.2.5.2,1.2.2,1.6s-.7,2.1-.9,2.1,0,0-1.2.5c-1.2.5-2.6.2-3,.9-.5.7-1.2,1.4-1.2,1.4v1.4c0,.2-.2.7.5.7s2.3-.2,2.8-.5c.5-.2,1.4-.7,1.4-.7l2.3-2.1,1.2-.7Z"/>
<path class="cls-1" d="M63.7,683.1c-.2-.5-1.4-2.1-1.4-2.1l-.5-.9s0-1.6-.9-1.9c-.9-.2-3-.2-3-.2l-1.6-2.3s-1.4-2.6-1.6-2.6-1.4,0-2.1-.2c-.7-.2-2.6-1.2-2.6-1.2l-.9.7c.2.7,1.6,2.8,1.6,2.8l1.2,2.3-.5,1.9s-1.9.5-2.3.5h-3s-.5-.7-.7.7c-.2,1.4-2.6,2.6-2.6,2.6h-3s-.9,1.6-.9,2.1-6.1,3.1-6.1,3.1l-1.9,2.6-1.9.5s-.5.7-.5.9-1.2,1.6-1.2,1.6h-.7s-2.3.5-2.3.9.5,1.6.5,2.1v1.6s0,1.6.2,1.6,1.4.7,1.4.7l.7,1.2s.5.2.5.5.7,1.2.7,1.2l1.2,1.2s-.5,1.6,0,2.1c.5.5.9.5,1.4.7.5.2,4.2.7,4.2.7,0,0,1.9.2,2.1.5.2.2,1.4.5,2.1,0,.7-.5,7-1.6,7-1.6,0,0-.7-.9,0-1.2.7-.2,1.9-.5,3-1.4,1.2-.9,3.7-1.2,3.7-1.2,0,0-.5-1.2.2-1.6.7-.5,2.6-2.1,2.8-2.1s2.1,1.4,2.1,1.4c0,0-.7.7.5.7s1.4-.5,1.9-2.1c.5-1.6,1.9-2.3,1.9-2.3l.5-.7s-.5-.5,0-1.6c.5-1.2.9-2.6.9-2.6v-3.5s-.5,0,.5-.5c.9-.5,2.1-2.3,1.4-3.1-.7-.7-1.6-1.9-1.9-2.3Z"/>
<polygon class="cls-1" points="49 672.3 49 672.3 49 672.3 49 672.3"/>
<path class="cls-1" d="M93.5,737.5c-2.3-1.2-4.2-2.3-4.2-2.3h-1.9l-1.2,3.5s1.4,0,1.2.9c-.2.9-1.6.5-1.2,1.6.5,1.2-.5.7,1.6,1.6,2.1.9,2.8,1.9,3.7.9.9-.9,1.9-2.6,1.9-2.6h0l.7-1.2s1.6-1.4-.7-2.6Z"/>
<path class="cls-1" d="M86.2,745l-2.8-1.9s-2.8,2.6-2.8,3.1-2.1,3.3-1.6,4,1.2,1.6,2.8,1.6,3.3-1.6,5.4-2.6c2.1-.9,2.8-2.3,3.7-1.9.9.5,2.1-.5,2.1-.5h0l-1.9-1.2-4.9-.7Z"/>
<path class="cls-1" d="M101.7,742h0l-3.5,1.2s-.9,1.2-.9,1.6.5,2.6.5,2.6c0,0-.5.5-.5,1.6v2.3s1.2,3.1,2.1,3.5c.9.5,2.6-.5,3.1-1.9.5-1.4-.9-5.6-.9-5.6,0,0-2.8-1.2-2.1-1.4.7-.2,2.8-.5,3.1-.5s.9-.7.9-.7l-.7-2.8h-.9Z"/>
<path class="cls-1" d="M115.1,720.4l-1.2-1.6-.5-1.6h0v-2.6l-2.1-3.3s-1.6-1.2-1.9-1.6c-.2-.5-3-2.3-3-2.1s-2.3,2.3-2.3,2.6-3.7,2.8-3.7,2.8c0,0,1.2,4,1.2,4.2s-1.9.2-.5,1.9c1.4,1.6,5.9,2.1,5.9,2.1,0,0,.2-1.4.5.5.2,1.9-.5,2.8-.5,3.1s1.2,1.2,2.6,1.2,3.3-.2,3.5,0c.2.2,3.5.5,3.5.5,0,0,.2,0,0-2.1-.2-2.1-1.4-3.8-1.4-3.8Z"/>
<path class="cls-1" d="M125.6,711.9c.5,0,1.4-1.9,1.4-1.9,0,0-.5-.7.9-.5,1.4.2.9,0,1.6.5.7.5,1.2.5,1.4.5s1.2-.7.5-1.4c-.7-.7-1.4-.9-1.9-1.6-.5-.7-.5-2.6-.5-2.6,0,0-.5-1.4-.7-1.4h-2.8l-.9.9h0c-.7,0-3.5-.7-3.5-.7l-.5,2.8-2.1,1.4s-.9.5-.5,1.2c.5.7.9,1.2.7,1.6-.2.5-1.6,0-1.4.7.2.7,1.6,1.9,1.6,1.9,0,0-.7,1.2-.7,1.6s.9,1.4,1.4,1.4,1.9-2.1,1.9-2.1c0,0,.5-.9.9-1.2.5-.2,2.1-1.2,2.1-1.2h.9Z"/>
<path class="cls-1" d="M141.5,712.4c0-.2-.9-.5-1.2-.7-.2-.2-1.6-.7-1.6-.7l-3-.9h-1.7s-.7,2.1-.7,2.3-.5,1.2,0,1.4c.5.2,2.1.7,2.1.7v1.2c0,.5-.7.7.5,1.2,1.2.5,4.2-.5,4.2-.5h2.6s.9-1.4.5-1.9c-.5-.5-1.6-1.9-1.6-2.1Z"/>
<path class="cls-1" d="M128.6,725.1s.2-.2.5,0c.2.2,1.4-.5,1.4-.5,0,0-.2-.5.5-.5s1.9.5,1.9.5c0,0,.7-.2.9-.7.2-.5-.2-.9,0-1.4.2-.5,0-1.6,0-1.6l-.7-1.6s-.9-.2-1.4-.2-1.2-.2-1.2-.2l-.5-.2-.9-.7h0s-2.3-.2-2.6.5c-.2.7-.7,1.6-.9,1.9-.2.2-1.9.9-1.9.9l1.4,1.4s.2.7,1.2,1.2c.9.5,2.3,1.4,2.3,1.4Z"/>
<path class="cls-1" d="M121.1,719.9c-.3-.3-.7-.5-1.2-.5h0c-.6,0-1.1.6-1.2,1.2,0,.4.2.8.5,1.2.1.2.3.5.7.7.5.3,1.4.6,1.6.2.2-.2,0-.5-.2-1.6,0-.7,0-.9-.2-1.2Z"/>
<path class="cls-1" d="M137.3,747.6c-.9-.5-1.9-.9-1.9-.9l-.5-1.2.9-1.2.2-2.3-4.2-.5-2.1.5h0s-1.2,2.1-1.4,2.6c-.2.5-2.1,1.9-2.1,2.1s0,.7-.2,1.4c-.2.7-.9,1.9,0,2.3.9.5,2.1.7,2.1.7,0,0,2.6-1.4,2.8-.7.2.7.2,1.2,1.2,1.9.9.7,2.1.9,2.3.9s.2-1.2.9-1.4c.7-.2,2.6-1.9,2.6-1.9,0,0,.2-1.9-.7-2.3Z"/>
<path class="cls-1" d="M267.1,679.6s.5-.5,0-1.6c-.5-1.2-.7-2.1-.7-2.1l-.7-1.2-.5-1.4s-.5-.5-.2-1.2c.2-.7,0-2.6,0-2.6l-.2-.7.7-.9h0c.2-.2.5-2.1.5-2.1l-3.3-2.3s-1.4.9-1.2,1.9c.2.9.9,2.1.9,2.6s.2,1.6,0,2.1c-.2.5-.9,1.2-.9,1.4s-.7,1.4-.9,1.9c-.2.5-2.8,1.9-2.8,1.9,0,0-1.9,1.9-1.9,2.1s-1.2.2-.7,1.6c.5,1.4.5,3.3.5,3.3,0,0-1.2.9-.5,1.6.7.7,1.4,1.6,2.8,2.1,1.4.5,4.2,1.6,4.2,1.6l3.1.5s2.3-.9,1.9-1.4c-.5-.5-1.6-1.4-1.6-1.4l-.5-1.2s0-1.2.5-1.9,1.6-2.6,1.6-2.6Z"/>
<polygon class="cls-1" points="279.4 600.4 279.4 586.1 272 579.9 262.7 571.1 261.3 561.5 254.5 559.9 251.7 557.3 244.7 562.9 243.5 566.9 235.1 563.3 234.4 553 235.1 535.7 240.9 533.6 245.9 532.1 247.1 523.8 256.9 510.3 248.3 507 239.9 515.4 232.7 509.4 238.7 493.8 231.6 486.6 229.2 475.8 217.2 472.2 206.4 484.2 205.2 493.8 195.7 486.6 186.1 495 186.1 502.2 176.5 510.6 159.8 515.4 157.4 523.8 140.6 521.4 127.4 517.8 124.5 512.7 119.4 508.3 115.3 512.5 110.2 512.4 96.4 517.8 89.3 530 84.4 535 85.6 538.3 88.3 540.1 87.2 541.1 82.3 539.9 76.8 551.3 72.3 553.6 67.3 564.8 76.6 566.5 73.6 571.4 75.3 574.4 80.6 583.9 85.4 585.9 85.4 589.7 80 596 78.4 589.4 69.9 588.5 68.8 590 71.3 593.4 75.4 595.9 74.3 598.4 69.7 600 68.7 603.3 63 605.4 61.9 611.5 67.8 615.5 70.4 613.1 73.2 605.9 74.3 613.6 75.3 626.5 69.7 634.5 69.7 639.2 68.1 643.4 67.8 644.3 80.4 650.4 92.7 661.4 89.3 661.9 86.5 659.8 85.6 664 79 654.2 69.4 650 67.8 656.3 70.6 661.9 74.3 663.3 77.1 670.4 72.7 669.9 66.1 661.5 62.9 648.1 58.5 642.1 51.9 654.2 55.1 668.3 59.6 674.6 61.9 673.9 65.8 676.6 67.1 680.5 69.9 680.2 72.7 677.9 79 686.6 77.7 698.2 82.8 699.7 79.7 706.7 76.6 709.9 77.4 712.1 82.5 712.8 82.7 721.2 93.1 719.9 97.3 713.3 97.1 709.8 112.1 701.6 110.7 695.9 117.2 694.3 120.8 688.2 120.2 673.4 122.8 671.1 124.7 675.1 124.5 684.5 122.4 694.3 125.7 699.9 130.4 702.1 134.8 704.2 136.9 700.4 143.5 702.3 145.8 697.6 149.1 698.3 148.3 688.6 152.1 687 152.9 684.2 151.7 682 155 673 162 671.1 167.4 666.2 174.9 662.4 179.6 664 183.8 662.6 187.1 655.8 192.4 654.7 194.6 657.2 202.1 657.2 202.7 663.8 200.6 669.2 196 669.8 194.8 663.8 189.6 664 187.5 671.6 189.1 675.6 185.9 681.9 181.9 681.2 183.1 676 181.4 674.3 176 692.2 189.2 694.5 191.7 701.4 195.5 706.3 203.9 704.4 207.4 697.8 213.3 694.1 214.2 689.9 209.3 687.1 210 684 218 684.7 221 686.6 224.2 683.9 222.7 674.6 209.2 661.4 209.5 657 212.8 653.7 210.5 650.9 215.4 646.2 211.9 643.7 213.5 642.5 216.5 642.5 222 642.5 227.6 640.4 228.1 635.9 230.9 638 231.2 641.7 231.8 647.4 236.2 650.7 238.4 657 234.6 663.8 232.6 672.3 234.9 676.9 238.7 676.9 243.5 679.8 244.5 675.1 243.3 671.1 245.9 662.9 249.9 659.4 255 664.1 261.6 661 262.3 655.8 265.1 651.9 267 645.5 264.6 642 261.1 642.5 257.9 642 248 646 246.3 642 239.9 634.6 244.2 626.8 246.3 631 251.6 632.8 262.5 623.5 278.8 628.6 285.4 617.2 285.4 607.6 279.4 600.4"/>
</g>
<g id="nakdong" data-label-shift="dx,dy">
<path class="cls-1" d="M405.4,649.3l-2.1-.2-1.6,1.2-.9,1.6-1.2.2-.9-.5v-1.2l.2-.9,1.4-.9.9-.7v-.9l.9-.9.7-1.2-.2-1.6-.2-1.4.5-3v-1.9l-1.6-1.6-.9-.9.2-1.9.7-2.8h0c0,0,1.6-.5,1.6-.5,0,0,1.2-.9,1.2-1.2s.2-.7.2-.7l-.2-.9-1.4-.9-1.9-.7-1.6.2-1.2.5-.9,1.2-.7,1.2-.2,1.2.5,1.9v.9l-.5.7-.7.2-1.2.2-.9.5-.5.5-.2,1.2-.2.5h-1.4l-1.4.5s-.9.2-1.2.2-.7.7-.7.7l-1.2.5h-1.4c-.2,0-.7.2-.7.2l-.5.5v.5l.2.7s.7.7.9.7,0,.7,0,.7l.2.9v.7l.2.9.5.5.7.5s.5.5.7.5.2.7.2.7c0,0,.5.7.5.9v2.1h-.2s-.7-.2-.9-.2-.5-.5-.5-.5l-.9-.7h-.9l-.9-.5-.5-.7-.7-1.2-.7-.5-.5-.2-.5.2-.7.7-.7.2h-.9l-1.4-.9-1.4-.9-1.4-.7h-1.2l-.5.2-.7.9-.5.7-1.2.7s-.2,0-.5.2c-.2.2-.7.5-.7.5l-.5.7-.7,1.2-.5,1.2-.9.9v3.3l1.2,1.4s.7,1.4.7,1.6.2,1.4.2,1.4l.7,1.2.7,1.6,1.6.2,1.4-.9.7-1.2.7-.7h2.6l1.4-1.2.9-1.6.7-.9.7-.5.5.5.5.7v2.6s.5.5.7.5,0,.7,0,.7l-.7,1.2-1.2,1.9-.5.7-.2.5-.2.5-.9.5-1.2.2-1.4.2-.7.5-.5.5-.2.7,1.4.5.5.5v.7l.5.5.7.2h1.2l2.1.2.7.5.2.7-.2.5-.7.5s-.9.7-1.2.7-.5.9-.5.9l-.2.7.2.9v.7l.9.2.9.7,1.2.2v.9l-.2.2-.9.5-1.4.5-.7.2-.5.7v.9l.5.7s.5.5.7.5,1.4.2,1.4.2c0,0,1.4.2,1.6.2s.9-.5.9-.5l1.2-.5,1.2-.7.5-.7v-.7l.2-1.2s.5-.9.5-1.2.9-.5.9-.5l1.4-.2.2-.7-.9-.9-.7-1.4.5-1.6v-1.2l.7-.7,1.6-.2,1.6-.2.7-.9.2-1.2v-2.1l.7-.7,1.9.2,1.6-.2.5,2.1,1.2,1.4,2.1.9,1.6-.7.2-1.2-.2-1.2-1.6-1.2-.7-1.4.2-1.2-1.2-.7-.9-.9.5-1.4h1.9c.2,0,.7-.5.7-.5l.7-.9v-1.6h.9c.2,0,.7-.5.7-.5l.2-1.4s.2-.5.7-.7c.5-.2,0-1.4,0-1.4v-1.4Z"/>
<path class="cls-1" d="M330.3,650.8v-1.2l-.9-.5h0s-4.2-1.2-4.2-.9-2.8,0-2.8,0l-1.4.9s-.2.7-.2.9.2,1.2.2,1.2l.5.2.9.7,2.8.5h1.9l.9-.7.9-.7.9-.2.5-.2Z"/>
<polygon class="cls-1" points="333.8 654.8 332.6 654.1 332.2 652.9 331.7 652.7 331 652.9 329.8 653.9 329.6 654.8 329.1 656 329.1 657.6 329.4 659 329.8 659.7 330.8 659.7 331.9 659.5 332.4 659 333.8 659 335 658.8 335.2 657.8 335.2 656.9 334.7 655.7 333.8 654.8"/>
<polygon class="cls-1" points="308 649.2 307.6 648.4 307.6 647.5 308 646.3 308.7 645.2 308.7 644.2 308.3 644 307.3 643.5 306.4 642.8 305.5 641.9 304.7 641.2 303.1 641.4 302.2 642.8 302.2 644.7 301.2 645.2 300.8 644.2 300.5 642.6 301 641.4 301.7 639.8 302.4 638.4 303.6 637.2 303.6 636.5 303.3 635.8 302.6 635.8 301 636 299.8 637 298.4 638.1 298.2 639.5 297.3 640 295.6 640.9 294.7 642.4 293.5 643.5 293.3 644.9 293.3 645.9 293.5 647 294.2 648.2 295.4 648.4 297 649.2 299.4 649.2 301.2 648.7 303.1 649.2 304.1 649.9 306.2 651 307.8 652 308.3 651.7 309.4 651.7 309.7 651 309.2 650.3 308 649.2"/>
<path class="cls-1" d="M305.2,653.4l-1.2-.5-.9-.7-.7-.2h-2.1l-1.6-.2-.9-.7h-1.6l-1.2,1.2-1.6,1.2-.9.7v.7l-1.4-.2-.5-1.2-.9-1.4-.2-.7-.5-.9-1.2-.5-1.2-.5-.5-.5s-.2-.5-.2-.7-.2-1.2-.2-1.2v-.5c0-.2-.7-.7-.7-.7l-.2-.7-.5-1.2-.2-1.4.7-.9.2-.9,1.6-.2.7-.5.5-.2.2-.7.2-1.2.5-.5.7-.9v-.7l-.2-1.2-.5-1.4.2-1.4-2.1-1.4h-3.1l-1.9.2-1.4,1.2-.9,1.4-.5,1.2-.5,1.4v.7l-1.6.5-.9.5-.7.9s.2.5,0,.7c-.2.2-1.2.9-1.2.9v1.4l-.5,1.2-.7.5-.9.5-.2.9v1.4l.2,1.2-.2,1.4.5,1.6.5,1.9,1.2,1.9h0v1.6l.2,1.4.7.9.9.7.2.7-.2.7-.9.9-.9.7-.5.7-.2.7,1.2.7.7.5,1.4.7v.7l.2,1.2.5.9.9.5.9-.2h1.9l1.2-.2.9-.5.9-.9v-1.4l-.5-.9-.2-1.4.2-.7.7-.5,1.9-.2,1.2-.9h2.3l.5.9v.7s-.5.7-.5.9-.2,1.2-.2,1.2l-.5,1.4v.5l-.2.9.2.5.2.5.2,1.2v1.2l.5.9,2.1.2,2.3.7,1.6-.2,1.2.2.9-.7s.5.5.7.5.5.9.5.9l1.6.7,1.6.2h.7l.2-1.2-.2-1.4-.7-.7-.2-.9v-1.2l.5-.5.9-.9.7-.2.5-.5v-2.3s-.5-2.1-.5-2.3v-.9l.2-1.2.5-1.4s-.2-.9,0-.9.7-.7.7-.7l.7-.5.2-.9-.2-.9-1.2-.5Z"/>
<polygon class="cls-1" points="533.7 451.9 529.9 457.3 516.8 465.7 509.4 457.5 516.6 447.7 513.8 417.3 513.1 408.8 521.3 392.4 522.9 355.1 523.6 353.3 531.1 333.9 526.2 315.4 526.2 282.1 519.8 263.8 504.8 272.7 495 281.2 482.8 272 481.1 259.2 471.4 254.5 473.3 244.6 468.7 245 455.3 248.2 454.9 259.5 454.7 274.8 451.4 277.9 438.9 269.7 434.5 277.6 421.1 273 410.9 275.3 403.3 283.3 392.8 288.8 386.2 300.5 389 306.9 377.6 314.7 353.5 310.3 345.4 307.2 340.7 310.3 334.5 310.7 330 319.5 334.6 326 329.8 328.1 325 323.7 307.5 329.5 314.2 336 312.9 341.5 306.5 336.4 294.4 343.5 303.6 349.6 308.1 357.5 304 362.7 314.1 371.6 316.5 383.6 314.1 388.4 326.1 392 323.3 402.6 325.2 414.4 315.5 413.8 315 423.6 307.5 439.1 298 443 298.5 447.6 301.2 454.4 296.8 462.5 286.2 472.3 276.7 473.4 269.4 480.7 267.1 483.1 264.5 485.8 256.9 505.2 256.9 510.3 247.1 523.8 245.9 532.1 240.9 533.6 235.1 535.7 234.4 553 235.1 563.3 243.5 566.9 244.7 562.9 251.7 557.3 254.5 559.9 261.3 561.5 262.7 571.1 272 579.9 279.4 586.1 279.4 600.4 285.4 607.6 285.4 617.2 278.8 628.6 282.6 628.4 288.8 622.6 289.3 620.3 291.9 621.5 292.3 624.3 296.3 623 298.7 624.3 301.6 622.6 298.9 615.9 301.2 614.9 303.4 615.5 304.7 611.2 309.9 609.7 307.1 614.2 306.9 625.2 305.5 632.3 314.8 637.2 317 641.5 318.3 642.1 322.4 640.3 325.1 641.7 326.8 641.4 329.4 634.9 335.5 635.5 338.5 640.5 342.8 638.4 346.2 633 347.4 636.3 348.6 639.8 343.1 642.3 344.4 645.9 349.4 647.4 351.4 645.9 353.5 647.7 353.3 655.5 347.7 654.1 346.2 655.7 351 659.7 353.7 666.6 356.3 667.8 358.7 665.9 359.9 659.7 358.5 655.6 361.6 654.2 365.6 646.5 363.1 643.5 360.7 647.8 358.5 646.8 361.3 632.3 361.1 630.7 361 629.5 368.3 628 371.4 624.3 365.9 619.1 357.2 620.8 355.4 623.6 351.9 624.1 354.8 618.5 361.5 616.3 367.3 614.4 366.1 610.6 379 609.8 381.7 611.6 383.5 619.4 389.9 616.8 383.5 596.4 387.2 591.5 388.9 592.4 387.7 599.2 390.1 604.4 394.7 605 398 608.8 399.5 604.8 401.5 606.5 400.5 612.2 406.2 614.7 414 613.3 414.9 615.6 420.1 616.2 424.6 617.3 428.8 614.1 432.5 616.6 438.5 610.1 436.6 622.3 438 626.7 441.3 625.8 442.5 620.6 445.7 622.8 453.5 612.9 457 616.4 461.6 616.6 461.7 613.8 459.8 610.5 463.1 606.6 469.9 608.2 480.9 594.4 480.7 591.3 485.5 581.8 491 579.8 494.6 576.1 498.5 573.7 497.1 571.8 499.6 567.6 499.9 561.3 498 558.2 504.1 554 504 546.1 505.5 548.8 506.9 554.5 511.6 551.2 514.6 544.4 514.4 537.4 515.8 532.7 513.9 528 514 525.4 524.7 493.4 527.1 486.2 527.8 477.8 535.1 466.5 538 455.6 533.7 451.9"/>
</g>
<g id="geum" data-label-shift="dx,dy">
<path class="cls-1" d="M298,443l9.5-3.9,7.5-15.6.5-9.8,9.7.6-1.9-11.8,2.8-10.6-12-3.6,2.4-4.8-2.4-12-10.1-8.9-12.6-.6-8.4-10.8-16.3-1.1-7.6-19.2,17.5-7.4,2.3-2.4v-1.1c-.1,0,.4-1.3.4-1.3l-1.6-1.1.5-9.5,1.4-12.2-3.8-13-13.2-9.6-4.9-10-7.1-1.9-11.7,17.8-8.2,1.7-3,5.2-4.6,6.5-19.7,1.1-13.8-5.9-3.6.6-3.6,5.4h-1.2l-4.8-6-6.4-3.9-5-.2-9.1-18.5-5.4,3-2.4-5.7-11.4-2.8-11.7-9.2h-3.9c0,.1-3.4,4.8-3.4,4.8l1,6.2,2.1,5.4-1.2.8-4.4-7.5-6.7-3.2-6.3-.3-5.2,3.3,5.9,3.4-3.6,2.2,5.3,4.4,2.5.8.4,3-6.5,6.1-8.7,11.2-4-1.9,6.4-13.5-1.6-1.9,1.1-7.9-2.1-3-4.7,14.5-3,1.8-3.8-5.7-4.4,2.7.5,8.4-1.5,1.7-3.3-.8-4.2,3.2-5.1,13.8.5,1.5,3.9-.2.2-6.5,5.6,2.5,2.8,5.3-7.4,2.4v3c0,0,5.9,1.2,5.9,1.2l4.3-1.5,2.1-3.3,4-.3-1.4,6,4.1,3.7-2.4,9.4,4.3,6.1,1.1,27,11.6,2.1-6.6-26.7,2.3-4.1-6.3-4.9,1.7-1.9,1-6.9,2-1.5,2.2,9,4.4,3.2,3.1-1.9,3.1-6.1,1.8,1.5-1.9,8.6,2,14.4,1.9,13.7-2.8,6.5,8.2,7.8v2.1l-6.9,2.9,2.9,21.8-1.6,1.9-5.9,6.7,1.3,2.7,3.3-2.7,8.2,2.8,6.2,7.7-1.2,2.8,5.1,13.1,5.6,3.1-19.1.5-1.8,3.3,6.4,3.1-.6,10.7,7.3,2.8,3-3.3,8.9,1.9,9.4-3.4.3,1.4.2.9-3.1,5.4-5.1-.9-9.4,3.5,6.8,6.4,4.3,1.4-.2,5.6-20.6-5.8-6.4,13.7-18.1,10.4-1.9,6.6,5.9,4.7h19.9s3.8,4.2,3.8,4.2l-.5,3.4,3,5.1,13.2,3.6,16.8,2.4,2.4-8.4,16.8-4.8,9.6-8.4v-7.2l9.6-8.4,9.6,7.2,1.2-9.6,10.8-12,12,3.6,2.4,10.8,7.2,7.2-6,15.6,7.2,6,8.4-8.4,8.6,3.3v-5.1s7.6-19.4,7.6-19.4l12.2-12.4,9.6-1.1,10.5-9.8,4.5-8.1-2.7-6.8-.6-4.6Z"/>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 219 KiB

File diff suppressed because one or more lines are too long
+91
View File
@@ -0,0 +1,91 @@
/**
* Copyright (c) Tiny Technologies, Inc. All rights reserved.
* Licensed under the LGPL or a commercial license.
* For LGPL see License.txt in the project root for license information.
* For commercial licenses see https://www.tiny.cloud/
*/
/**
* Jquery integration plugin.
*
* @class tinymce.core.JqueryIntegration
* @private
*/
!function(){function f(){
// Reference to tinymce needs to be lazily evaluated since tinymce
// might be loaded through the compressor or other means
return d.tinymce}var p,c,u,s=[],d="undefined"!=typeof global?global:window,m=d.jQuery;m.fn.tinymce=function(o){var e,t,i,n,l=this,r="";
// No match then just ignore the call
return l.length?
// Get editor instance
o?(l.css("visibility","hidden"),
// Load TinyMCE on demand, if we need to
d.tinymce||c||!(e=o.script_url)?
// Delay the init call until tinymce is loaded
1===c?s.push(a):a():(c=1,t=e.substring(0,e.lastIndexOf("/")),
// Check if it's a dev/src version they want to load then
// make sure that all plugins, themes etc are loaded in source mode as well
-1!=e.indexOf(".min")&&(r=".min"),
// Setup tinyMCEPreInit object this will later be used by the TinyMCE
// core script to locate other resources like CSS files, dialogs etc
// You can also predefined a tinyMCEPreInit object and then it will use that instead
d.tinymce=d.tinyMCEPreInit||{base:t,suffix:r},
// url contains gzip then we assume it's a compressor
-1!=e.indexOf("gzip")&&(i=o.language||"en",e=e+(/\?/.test(e)?"&":"?")+"js=true&core=true&suffix="+escape(r)+"&themes="+escape(o.theme||"modern")+"&plugins="+escape(o.plugins||"")+"&languages="+(i||""),
// Check if compressor script is already loaded otherwise setup a basic one
d.tinyMCE_GZ||(d.tinyMCE_GZ={start:function(){function n(e){f().ScriptLoader.markDone(f().baseURI.toAbsolute(e))}
// Add core languages
n("langs/"+i+".js"),
// Add themes with languages
n("themes/"+o.theme+"/theme"+r+".js"),n("themes/"+o.theme+"/langs/"+i+".js"),
// Add plugins with languages
m.each(o.plugins.split(","),function(e,t){t&&(n("plugins/"+t+"/plugin"+r+".js"),n("plugins/"+t+"/langs/"+i+".js"))})},end:function(){}})),(n=document.createElement("script")).type="text/javascript",n.onload=n.onreadystatechange=function(e){e=e||window.event,2===c||"load"!=e.type&&!/complete|loaded/.test(n.readyState)||(f().dom.Event.domLoaded=1,c=2,
// Execute callback after mainscript has been loaded and before the initialization occurs
o.script_loaded&&o.script_loaded(),a(),m.each(s,function(e,t){t()}))},n.src=e,document.body.appendChild(n)),l):f()?f().get(l[0].id):null:l;function a(){var a=[],c=0;
// Apply patches to the jQuery object, only once
u||(v(),u=!0),
// Create an editor instance for each matched node
l.each(function(e,t){var n,i=t.id,r=o.oninit;
// Generate unique id for target element if needed
i||(t.id=i=f().DOM.uniqueId()),
// Only init the editor once
f().get(i)||(
// Create editor instance and render it
n=f().createEditor(i,o),a.push(n),n.on("init",function(){var e,t=r;l.css("visibility",""),
// Run this if the oninit setting is defined
// this logic will fire the oninit callback ones each
// matched editor instance is initialized
r&&++c==a.length&&("string"==typeof t&&(e=-1===t.indexOf(".")?null:f().resolve(t.replace(/\.\w+$/,"")),t=f().resolve(t)),
// Call the oninit function with the object
t.apply(e||f(),a))}))}),
// Render the editor instances in a separate loop since we
// need to have the full editors array used in the onInit calls
m.each(a,function(e,t){t.render()})}},
// Add :tinymce pseudo selector this will select elements that has been converted into editor instances
// it's now possible to use things like $('*:tinymce') to get all TinyMCE bound elements.
m.extend(m.expr[":"],{tinymce:function(e){var t;return!!(e.id&&"tinymce"in d&&(t=f().get(e.id))&&t.editorManager===f())}});
// This function patches internal jQuery functions so that if
// you for example remove an div element containing an editor it's
// automatically destroyed by the TinyMCE API
var v=function(){function r(e){
// If the function is remove
"remove"===e&&this.each(function(e,t){var n=u(t);n&&n.remove()}),this.find("span.mceEditor,div.mceEditor").each(function(e,t){var n=f().get(t.id.replace(/_parent$/,""));n&&n.remove()})}function o(i){var e,t=this;
// Handle set value
/*jshint eqnull:true */if(null!=i)r.call(t),
// Saves the contents before get/set value of textarea/div
t.each(function(e,t){var n;(n=f().get(t.id))&&n.setContent(i)});else if(0<t.length&&(e=f().get(t[0].id)))return e.getContent()}function l(e){return e&&e.length&&d.tinymce&&e.is(":tinymce")}
// Removes any child editor instances by looking for editor wrapper elements
var u=function(e){var t=null;return e&&e.id&&d.tinymce?f().get(e.id):t},s={};
// Loads or saves contents from/to textarea if the value
// argument is defined it will set the TinyMCE internal contents
// Patch some setter/getter functions these will
// now be able to set/get the contents of editor instances for
// example $('#editorid').html('Content'); will update the TinyMCE iframe instance
m.each(["text","html","val"],function(e,t){var a=s[t]=m.fn[t],c="text"===t;m.fn[t]=function(e){var t=this;if(!l(t))return a.apply(t,arguments);if(e!==p)return o.call(t.filter(":tinymce"),e),a.apply(t.not(":tinymce"),arguments),t;// return original set for chaining
var i="",r=arguments;return(c?t:t.eq(0)).each(function(e,t){var n=u(t);i+=n?c?n.getContent().replace(/<(?:"[^"]*"|'[^']*'|[^'">])*>/g,""):n.getContent({save:!0}):a.apply(m(t),r)}),i}}),
// Makes it possible to use $('#id').append("content"); to append contents to the TinyMCE editor iframe
m.each(["append","prepend"],function(e,t){var n=s[t]=m.fn[t],r="prepend"===t;m.fn[t]=function(i){var e=this;return l(e)?i!==p?("string"==typeof i&&e.filter(":tinymce").each(function(e,t){var n=u(t);n&&n.setContent(r?i+n.getContent():n.getContent()+i)}),n.apply(e.not(":tinymce"),arguments),e):void 0:n.apply(e,arguments)}}),
// Makes sure that the editor instance gets properly destroyed when the parent element is removed
m.each(["remove","replaceWith","replaceAll","empty"],function(e,t){var n=s[t]=m.fn[t];m.fn[t]=function(){return r.call(this,t),n.apply(this,arguments)}}),s.attr=m.fn.attr,
// Makes sure that $('#tinymce_id').attr('value') gets the editors current HTML contents
m.fn.attr=function(e,t){var n=this,i=arguments;if(!e||"value"!==e||!l(n))return s.attr.apply(n,i);if(t!==p)return o.call(n.filter(":tinymce"),t),s.attr.apply(n.not(":tinymce"),i),n;// return original set for chaining
var r=n[0],a=u(r);return a?a.getContent({save:!0}):s.attr.apply(m(r),i)}}}();
+3
View File
@@ -0,0 +1,3 @@
This is where language files should be placed.
Please DO NOT translate these directly use this service: https://www.transifex.com/projects/p/tinymce/
File diff suppressed because one or more lines are too long
+504
View File
@@ -0,0 +1,504 @@
GNU LESSER GENERAL PUBLIC LICENSE
Version 2.1, February 1999
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
[This is the first released version of the Lesser GPL. It also counts
as the successor of the GNU Library Public License, version 2, hence
the version number 2.1.]
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
Licenses are intended to guarantee your freedom to share and change
free software--to make sure the software is free for all its users.
This license, the Lesser General Public License, applies to some
specially designated software packages--typically libraries--of the
Free Software Foundation and other authors who decide to use it. You
can use it too, but we suggest you first think carefully about whether
this license or the ordinary General Public License is the better
strategy to use in any particular case, based on the explanations below.
When we speak of free software, we are referring to freedom of use,
not price. Our General Public Licenses are designed to make sure that
you have the freedom to distribute copies of free software (and charge
for this service if you wish); that you receive source code or can get
it if you want it; that you can change the software and use pieces of
it in new free programs; and that you are informed that you can do
these things.
To protect your rights, we need to make restrictions that forbid
distributors to deny you these rights or to ask you to surrender these
rights. These restrictions translate to certain responsibilities for
you if you distribute copies of the library or if you modify it.
For example, if you distribute copies of the library, whether gratis
or for a fee, you must give the recipients all the rights that we gave
you. You must make sure that they, too, receive or can get the source
code. If you link other code with the library, you must provide
complete object files to the recipients, so that they can relink them
with the library after making changes to the library and recompiling
it. And you must show them these terms so they know their rights.
We protect your rights with a two-step method: (1) we copyright the
library, and (2) we offer you this license, which gives you legal
permission to copy, distribute and/or modify the library.
To protect each distributor, we want to make it very clear that
there is no warranty for the free library. Also, if the library is
modified by someone else and passed on, the recipients should know
that what they have is not the original version, so that the original
author's reputation will not be affected by problems that might be
introduced by others.
Finally, software patents pose a constant threat to the existence of
any free program. We wish to make sure that a company cannot
effectively restrict the users of a free program by obtaining a
restrictive license from a patent holder. Therefore, we insist that
any patent license obtained for a version of the library must be
consistent with the full freedom of use specified in this license.
Most GNU software, including some libraries, is covered by the
ordinary GNU General Public License. This license, the GNU Lesser
General Public License, applies to certain designated libraries, and
is quite different from the ordinary General Public License. We use
this license for certain libraries in order to permit linking those
libraries into non-free programs.
When a program is linked with a library, whether statically or using
a shared library, the combination of the two is legally speaking a
combined work, a derivative of the original library. The ordinary
General Public License therefore permits such linking only if the
entire combination fits its criteria of freedom. The Lesser General
Public License permits more lax criteria for linking other code with
the library.
We call this license the "Lesser" General Public License because it
does Less to protect the user's freedom than the ordinary General
Public License. It also provides other free software developers Less
of an advantage over competing non-free programs. These disadvantages
are the reason we use the ordinary General Public License for many
libraries. However, the Lesser license provides advantages in certain
special circumstances.
For example, on rare occasions, there may be a special need to
encourage the widest possible use of a certain library, so that it becomes
a de-facto standard. To achieve this, non-free programs must be
allowed to use the library. A more frequent case is that a free
library does the same job as widely used non-free libraries. In this
case, there is little to gain by limiting the free library to free
software only, so we use the Lesser General Public License.
In other cases, permission to use a particular library in non-free
programs enables a greater number of people to use a large body of
free software. For example, permission to use the GNU C Library in
non-free programs enables many more people to use the whole GNU
operating system, as well as its variant, the GNU/Linux operating
system.
Although the Lesser General Public License is Less protective of the
users' freedom, it does ensure that the user of a program that is
linked with the Library has the freedom and the wherewithal to run
that program using a modified version of the Library.
The precise terms and conditions for copying, distribution and
modification follow. Pay close attention to the difference between a
"work based on the library" and a "work that uses the library". The
former contains code derived from the library, whereas the latter must
be combined with the library in order to run.
GNU LESSER GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License Agreement applies to any software library or other
program which contains a notice placed by the copyright holder or
other authorized party saying it may be distributed under the terms of
this Lesser General Public License (also called "this License").
Each licensee is addressed as "you".
A "library" means a collection of software functions and/or data
prepared so as to be conveniently linked with application programs
(which use some of those functions and data) to form executables.
The "Library", below, refers to any such software library or work
which has been distributed under these terms. A "work based on the
Library" means either the Library or any derivative work under
copyright law: that is to say, a work containing the Library or a
portion of it, either verbatim or with modifications and/or translated
straightforwardly into another language. (Hereinafter, translation is
included without limitation in the term "modification".)
"Source code" for a work means the preferred form of the work for
making modifications to it. For a library, complete source code means
all the source code for all modules it contains, plus any associated
interface definition files, plus the scripts used to control compilation
and installation of the library.
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running a program using the Library is not restricted, and output from
such a program is covered only if its contents constitute a work based
on the Library (independent of the use of the Library in a tool for
writing it). Whether that is true depends on what the Library does
and what the program that uses the Library does.
1. You may copy and distribute verbatim copies of the Library's
complete source code as you receive it, in any medium, provided that
you conspicuously and appropriately publish on each copy an
appropriate copyright notice and disclaimer of warranty; keep intact
all the notices that refer to this License and to the absence of any
warranty; and distribute a copy of this License along with the
Library.
You may charge a fee for the physical act of transferring a copy,
and you may at your option offer warranty protection in exchange for a
fee.
2. You may modify your copy or copies of the Library or any portion
of it, thus forming a work based on the Library, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) The modified work must itself be a software library.
b) You must cause the files modified to carry prominent notices
stating that you changed the files and the date of any change.
c) You must cause the whole of the work to be licensed at no
charge to all third parties under the terms of this License.
d) If a facility in the modified Library refers to a function or a
table of data to be supplied by an application program that uses
the facility, other than as an argument passed when the facility
is invoked, then you must make a good faith effort to ensure that,
in the event an application does not supply such function or
table, the facility still operates, and performs whatever part of
its purpose remains meaningful.
(For example, a function in a library to compute square roots has
a purpose that is entirely well-defined independent of the
application. Therefore, Subsection 2d requires that any
application-supplied function or table used by this function must
be optional: if the application does not supply it, the square
root function must still compute square roots.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Library,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Library, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote
it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Library.
In addition, mere aggregation of another work not based on the Library
with the Library (or with a work based on the Library) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may opt to apply the terms of the ordinary GNU General Public
License instead of this License to a given copy of the Library. To do
this, you must alter all the notices that refer to this License, so
that they refer to the ordinary GNU General Public License, version 2,
instead of to this License. (If a newer version than version 2 of the
ordinary GNU General Public License has appeared, then you can specify
that version instead if you wish.) Do not make any other change in
these notices.
Once this change is made in a given copy, it is irreversible for
that copy, so the ordinary GNU General Public License applies to all
subsequent copies and derivative works made from that copy.
This option is useful when you wish to copy part of the code of
the Library into a program that is not a library.
4. You may copy and distribute the Library (or a portion or
derivative of it, under Section 2) in object code or executable form
under the terms of Sections 1 and 2 above provided that you accompany
it with the complete corresponding machine-readable source code, which
must be distributed under the terms of Sections 1 and 2 above on a
medium customarily used for software interchange.
If distribution of object code is made by offering access to copy
from a designated place, then offering equivalent access to copy the
source code from the same place satisfies the requirement to
distribute the source code, even though third parties are not
compelled to copy the source along with the object code.
5. A program that contains no derivative of any portion of the
Library, but is designed to work with the Library by being compiled or
linked with it, is called a "work that uses the Library". Such a
work, in isolation, is not a derivative work of the Library, and
therefore falls outside the scope of this License.
However, linking a "work that uses the Library" with the Library
creates an executable that is a derivative of the Library (because it
contains portions of the Library), rather than a "work that uses the
library". The executable is therefore covered by this License.
Section 6 states terms for distribution of such executables.
When a "work that uses the Library" uses material from a header file
that is part of the Library, the object code for the work may be a
derivative work of the Library even though the source code is not.
Whether this is true is especially significant if the work can be
linked without the Library, or if the work is itself a library. The
threshold for this to be true is not precisely defined by law.
If such an object file uses only numerical parameters, data
structure layouts and accessors, and small macros and small inline
functions (ten lines or less in length), then the use of the object
file is unrestricted, regardless of whether it is legally a derivative
work. (Executables containing this object code plus portions of the
Library will still fall under Section 6.)
Otherwise, if the work is a derivative of the Library, you may
distribute the object code for the work under the terms of Section 6.
Any executables containing that work also fall under Section 6,
whether or not they are linked directly with the Library itself.
6. As an exception to the Sections above, you may also combine or
link a "work that uses the Library" with the Library to produce a
work containing portions of the Library, and distribute that work
under terms of your choice, provided that the terms permit
modification of the work for the customer's own use and reverse
engineering for debugging such modifications.
You must give prominent notice with each copy of the work that the
Library is used in it and that the Library and its use are covered by
this License. You must supply a copy of this License. If the work
during execution displays copyright notices, you must include the
copyright notice for the Library among them, as well as a reference
directing the user to the copy of this License. Also, you must do one
of these things:
a) Accompany the work with the complete corresponding
machine-readable source code for the Library including whatever
changes were used in the work (which must be distributed under
Sections 1 and 2 above); and, if the work is an executable linked
with the Library, with the complete machine-readable "work that
uses the Library", as object code and/or source code, so that the
user can modify the Library and then relink to produce a modified
executable containing the modified Library. (It is understood
that the user who changes the contents of definitions files in the
Library will not necessarily be able to recompile the application
to use the modified definitions.)
b) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (1) uses at run time a
copy of the library already present on the user's computer system,
rather than copying library functions into the executable, and (2)
will operate properly with a modified version of the library, if
the user installs one, as long as the modified version is
interface-compatible with the version that the work was made with.
c) Accompany the work with a written offer, valid for at
least three years, to give the same user the materials
specified in Subsection 6a, above, for a charge no more
than the cost of performing this distribution.
d) If distribution of the work is made by offering access to copy
from a designated place, offer equivalent access to copy the above
specified materials from the same place.
e) Verify that the user has already received a copy of these
materials or that you have already sent this user a copy.
For an executable, the required form of the "work that uses the
Library" must include any data and utility programs needed for
reproducing the executable from it. However, as a special exception,
the materials to be distributed need not include anything that is
normally distributed (in either source or binary form) with the major
components (compiler, kernel, and so on) of the operating system on
which the executable runs, unless that component itself accompanies
the executable.
It may happen that this requirement contradicts the license
restrictions of other proprietary libraries that do not normally
accompany the operating system. Such a contradiction means you cannot
use both them and the Library together in an executable that you
distribute.
7. You may place library facilities that are a work based on the
Library side-by-side in a single library together with other library
facilities not covered by this License, and distribute such a combined
library, provided that the separate distribution of the work based on
the Library and of the other library facilities is otherwise
permitted, and provided that you do these two things:
a) Accompany the combined library with a copy of the same work
based on the Library, uncombined with any other library
facilities. This must be distributed under the terms of the
Sections above.
b) Give prominent notice with the combined library of the fact
that part of it is a work based on the Library, and explaining
where to find the accompanying uncombined form of the same work.
8. You may not copy, modify, sublicense, link with, or distribute
the Library except as expressly provided under this License. Any
attempt otherwise to copy, modify, sublicense, link with, or
distribute the Library is void, and will automatically terminate your
rights under this License. However, parties who have received copies,
or rights, from you under this License will not have their licenses
terminated so long as such parties remain in full compliance.
9. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Library or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Library (or any work based on the
Library), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Library or works based on it.
10. Each time you redistribute the Library (or any work based on the
Library), the recipient automatically receives a license from the
original licensor to copy, distribute, link with or modify the Library
subject to these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties with
this License.
11. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Library at all. For example, if a patent
license would not permit royalty-free redistribution of the Library by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Library.
If any portion of this section is held invalid or unenforceable under any
particular circumstance, the balance of the section is intended to apply,
and the section as a whole is intended to apply in other circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
12. If the distribution and/or use of the Library is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Library under this License may add
an explicit geographical distribution limitation excluding those countries,
so that distribution is permitted only in or among countries not thus
excluded. In such case, this License incorporates the limitation as if
written in the body of this License.
13. The Free Software Foundation may publish revised and/or new
versions of the Lesser General Public License from time to time.
Such new versions will be similar in spirit to the present version,
but may differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the Library
specifies a version number of this License which applies to it and
"any later version", you have the option of following the terms and
conditions either of that version or of any later version published by
the Free Software Foundation. If the Library does not specify a
license version number, you may choose any version ever published by
the Free Software Foundation.
14. If you wish to incorporate parts of the Library into other free
programs whose distribution conditions are incompatible with these,
write to the author to ask for permission. For software which is
copyrighted by the Free Software Foundation, write to the Free
Software Foundation; we sometimes make exceptions for this. Our
decision will be guided by the two goals of preserving the free status
of all derivatives of our free software and of promoting the sharing
and reuse of software generally.
NO WARRANTY
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Libraries
If you develop a new library, and you want it to be of the greatest
possible use to the public, we recommend making it free software that
everyone can redistribute and change. You can do so by permitting
redistribution under these terms (or, alternatively, under the terms of the
ordinary General Public License).
To apply these terms, attach the following notices to the library. It is
safest to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least the
"copyright" line and a pointer to where the full notice is found.
<one line to give the library's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Also add information on how to contact you by electronic and paper mail.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the library, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the
library `Frob' (a library for tweaking knobs) written by James Random Hacker.
<signature of Ty Coon>, 1 April 1990
Ty Coon, President of Vice
That's all there is to it!
+9
View File
@@ -0,0 +1,9 @@
/**
* Copyright (c) Tiny Technologies, Inc. All rights reserved.
* Licensed under the LGPL or a commercial license.
* For LGPL see License.txt in the project root for license information.
* For commercial licenses see https://www.tiny.cloud/
*
* Version: 5.10.9 (2023-11-15)
*/
!function(){"use strict";function f(t,e,n){t.execCommand("UL"===e?"InsertUnorderedList":"InsertOrderedList",!1,!1===n?null:{"list-style-type":n})}function i(t){return function(){return t}}function t(t){return t}function e(){return s}var n=tinymce.util.Tools.resolve("tinymce.PluginManager"),g=tinymce.util.Tools.resolve("tinymce.util.Tools"),u=i(!1),l=i(!0),s={fold:function(t,e){return t()},isSome:u,isNone:l,getOr:t,getOrThunk:r,getOrDie:function(t){throw new Error(t||"error: getOrDie called on none.")},getOrNull:i(null),getOrUndefined:i(void 0),or:t,orThunk:r,map:e,each:function(){},bind:e,exists:u,forall:l,filter:function(){return s},toArray:function(){return[]},toString:i("none()")};function r(t){return t()}function d(t){return t&&/^(TH|TD)$/.test(t.nodeName)}function m(c,a){return function(s){function t(t){var e,n,r,o,i,u,l;s.setActive((e=c,r=a,i=-1!==(o=function(t,e){for(var n=0;n<t.length;n++)if(e(t[n]))return n;return-1}((n=t).parents,d))?n.parents.slice(0,o):n.parents,0<(u=g.grep(i,(l=e,function(t){return t&&/^(OL|UL|DL)$/.test(t.nodeName)&&(e=t,l.$.contains(l.getBody(),e));var e}))).length&&u[0].nodeName===r))}return c.on("NodeChange",t),function(){return c.off("NodeChange",t)}}}function c(t,e,n,r,o,i){var u,l,s,c,a,d;1<i.length?(c=r,a=o,d=i,(s=t).ui.registry.addSplitButton(e,{tooltip:n,icon:"OL"===a?"ordered-list":"unordered-list",presets:"listpreview",columns:3,fetch:function(t){t(g.map(d,function(t){return{type:"choiceitem",value:"default"===t?"":t,icon:"list-"+("OL"===a?"num":"bull")+"-"+("disc"===t||"decimal"===t?"default":t),text:t.replace(/\-/g," ").replace(/\b\w/g,function(t){return t.toUpperCase()})}}))},onAction:function(){return s.execCommand(c)},onItemAction:function(t,e){f(s,a,e)},select:function(e){var t,n=(t=s).dom.getParent(t.selection.getNode(),"ol,ul"),r=t.dom.getStyle(n,"listStyleType");return p(r).map(function(t){return e===t}).getOr(!1)},onSetup:m(s,a)})):(l=r,(u=t).ui.registry.addToggleButton(e,{active:!1,tooltip:n,icon:"OL"===o?"ordered-list":"unordered-list",onSetup:m(u,o),onAction:function(){return u.execCommand(l)}}))}var a=function(n){function t(){return o}function e(t){return t(n)}var r=i(n),o={fold:function(t,e){return e(n)},isSome:l,isNone:u,getOr:r,getOrThunk:r,getOrDie:r,getOrNull:r,getOrUndefined:r,or:t,orThunk:t,map:function(t){return a(t(n))},each:function(t){t(n)},bind:e,exists:e,forall:e,filter:function(t){return t(n)?o:s},toArray:function(){return[n]},toString:function(){return"some("+n+")"}};return o},p=function(t){return null==t?s:a(t)};n.add("advlist",function(t){var n,e,r,o;t.hasPlugin("lists")?(c(e=t,"numlist","Numbered list","InsertOrderedList","OL",(r=e.getParam("advlist_number_styles","default,lower-alpha,lower-greek,lower-roman,upper-alpha,upper-roman"))?r.split(/[ ,]/):[]),c(e,"bullist","Bullet list","InsertUnorderedList","UL",(o=e.getParam("advlist_bullet_styles","default,circle,square"))?o.split(/[ ,]/):[]),(n=t).addCommand("ApplyUnorderedListStyle",function(t,e){f(n,"UL",e["list-style-type"])}),n.addCommand("ApplyOrderedListStyle",function(t,e){f(n,"OL",e["list-style-type"])})):console.error("Please use the Lists plugin together with the Advanced List plugin.")})}();
+9
View File
@@ -0,0 +1,9 @@
/**
* Copyright (c) Tiny Technologies, Inc. All rights reserved.
* Licensed under the LGPL or a commercial license.
* For LGPL see License.txt in the project root for license information.
* For commercial licenses see https://www.tiny.cloud/
*
* Version: 5.10.9 (2023-11-15)
*/
!function(){"use strict";function a(e){return e.getAttribute("id")||e.getAttribute("name")||""}function c(e){return e&&"a"===e.nodeName.toLowerCase()&&!e.getAttribute("href")&&""!==a(e)}function d(e){return e.dom.getParent(e.selection.getStart(),l)}function r(e,t){var o,a,n,r,i,l=d(e);l?(n=e,r=t,(i=l).removeAttribute("name"),i.id=r,n.addVisual(),n.undoManager.add()):(a=t,(o=e).undoManager.transact(function(){var e,n;o.getParam("allow_html_in_named_anchor",!1,"boolean")||o.selection.collapse(!0),o.selection.isCollapsed()?o.insertContent(o.dom.createHTML("a",{id:a})):(n=(e=o).dom,u(n).walk(e.selection.getRng(),function(e){s.each(e,function(e){var t;c(t=e)&&!t.firstChild&&n.remove(e,!1)})}),o.formatter.remove("namedAnchor",null,null,!0),o.formatter.apply("namedAnchor",{value:a}),o.addVisual())})),e.focus()}function i(r){return function(e){for(var t,n=0;n<e.length;n++){var o=e[n],a=void 0;!(a=t=o)||a.attr("href")||!a.attr("id")&&!a.attr("name")||t.firstChild||o.attr("contenteditable",r)}}}var e=tinymce.util.Tools.resolve("tinymce.PluginManager"),u=tinymce.util.Tools.resolve("tinymce.dom.RangeUtils"),s=tinymce.util.Tools.resolve("tinymce.util.Tools"),l="a:not([href])";e.add("anchor",function(e){var t,n,o;(t=e).on("PreInit",function(){t.parser.addNodeFilter("a",i("false")),t.serializer.addNodeFilter("a",i(null))}),(n=e).addCommand("mceAnchor",function(){var o,e,t;t=(e=d(o=n))?a(e):"",o.windowManager.open({title:"Anchor",size:"normal",body:{type:"panel",items:[{name:"id",type:"input",label:"ID",placeholder:"example"}]},buttons:[{type:"cancel",name:"cancel",text:"Cancel"},{type:"submit",name:"save",text:"Save",primary:!0}],initialData:{id:t},onSubmit:function(e){var t=o,n=e.getData().id;(/^[A-Za-z][A-Za-z0-9\-:._]*$/.test(n)?(r(t,n),0):(t.windowManager.alert("Id should start with a letter, followed only by letters, numbers, dashes, dots, colons or underscores."),1))||e.close()}})}),(o=e).ui.registry.addToggleButton("anchor",{icon:"bookmark",tooltip:"Anchor",onAction:function(){return o.execCommand("mceAnchor")},onSetup:function(e){return o.selection.selectorChangedWithUnbind("a:not([href])",e.setActive).unbind}}),o.ui.registry.addMenuItem("anchor",{icon:"bookmark",text:"Anchor...",onAction:function(){return o.execCommand("mceAnchor")}}),e.on("PreInit",function(){e.formatter.register("namedAnchor",{inline:"a",selector:l,remove:"all",split:!0,deep:!0,attributes:{id:"%value"},onmatch:c})})})}();
+9
View File
@@ -0,0 +1,9 @@
/**
* Copyright (c) Tiny Technologies, Inc. All rights reserved.
* Licensed under the LGPL or a commercial license.
* For LGPL see License.txt in the project root for license information.
* For commercial licenses see https://www.tiny.cloud/
*
* Version: 5.10.9 (2023-11-15)
*/
!function(){"use strict";function k(e){return/^[(\[{ \u00a0]$/.test(e)}function w(e){return 3===e.nodeType}function i(e){return 1===e.nodeType}function o(e,t){var n;return t<0&&(t=0),!w(e)||(n=e.data.length)<t&&(t=n),t}function y(e,t,n){!i(t)||t.hasChildNodes()?e.setStart(t,o(t,n)):e.setStartBefore(t)}function v(e,t,n){!i(t)||t.hasChildNodes()?e.setEnd(t,o(t,n)):e.setEndAfter(t)}function r(e,t){var n,i,o,r,a,f=e.getParam("autolink_pattern",A),s=e.getParam("default_link_target",!1);if(null===e.dom.getParent(e.selection.getNode(),"a[href]")){var d=e.selection.getRng().cloneRange();if(d.startOffset<5){if(!(r=d.endContainer.previousSibling)){if(!d.endContainer.firstChild||!d.endContainer.firstChild.nextSibling)return;r=d.endContainer.firstChild.nextSibling}if(y(d,r,a=r.length),v(d,r,a),d.endOffset<5)return;n=d.endOffset,i=r}else{if(!w(i=d.endContainer)&&i.firstChild){for(;!w(i)&&i.firstChild;)i=i.firstChild;w(i)&&(y(d,i,0),v(d,i,i.nodeValue.length))}n=1===d.endOffset?2:d.endOffset-1-t}for(var l=n;y(d,i,2<=n?n-2:0),v(d,i,1<=n?n-1:0),--n,!k(d.toString())&&0<=n-2;);k(d.toString())?(y(d,i,n),v(d,i,l),n+=1):(0===d.startOffset?y(d,i,0):y(d,i,n),v(d,i,l)),u=d.toString(),/[?!,.;:]/.test(u.charAt(u.length-1))&&v(d,i,l-1);var u,c,g,h,C=(u=d.toString().trim()).match(f),m=e.getParam("link_default_protocol","http","string");C&&((g=c=C[0]).length>=(h="www.").length&&g.substr(0,0+h.length)===h?c=m+"://"+c:-1===c.indexOf("@")||/^([A-Za-z][A-Za-z\d.+-]*:\/\/)|mailto:/.test(c)||(c="mailto:"+c),o=e.selection.getBookmark(),e.selection.setRng(d),e.execCommand("createlink",!1,c),!1!==s&&e.dom.setAttrib(e.selection.getNode(),"target",s),e.selection.moveToBookmark(o),e.nodeChanged())}}var e=tinymce.util.Tools.resolve("tinymce.PluginManager"),a=tinymce.util.Tools.resolve("tinymce.Env"),A=new RegExp("^"+/(?:[A-Za-z][A-Za-z\d.+-]{0,14}:\/\/(?:[-.~*+=!&;:'%@?^${}(),\w]+@)?|www\.|[-;:&=+$,.\w]+@)[A-Za-z\d-]+(?:\.[A-Za-z\d-]+)*(?::\d+)?(?:\/(?:[-.~*+=!;:'%@$(),\/\w]*[-~*+=%@$()\/\w])?)?(?:\?(?:[-.~*+=!&;:'%@?^${}(),\/\w]+))?(?:#(?:[-.~*+=!&;:'%@?^${}(),\/\w]+))?/g.source+"$","i");e.add("autolink",function(e){var t,n;(t=e).on("keydown",function(e){if(13===e.keyCode)return r(t,-1)}),a.browser.isIE()?t.on("focus",function(){if(!n){n=!0;try{t.execCommand("AutoUrlDetect",!1,!0)}catch(e){}}}):(t.on("keypress",function(e){if(41===e.keyCode||93===e.keyCode||125===e.keyCode)return r(t,-1)}),t.on("keyup",function(e){if(32===e.keyCode)return r(t,0)}))})}();
@@ -0,0 +1,9 @@
/**
* Copyright (c) Tiny Technologies, Inc. All rights reserved.
* Licensed under the LGPL or a commercial license.
* For LGPL see License.txt in the project root for license information.
* For commercial licenses see https://www.tiny.cloud/
*
* Version: 5.10.9 (2023-11-15)
*/
!function(){"use strict";function y(e){return e.getParam("min_height",e.getElement().offsetHeight,"number")}function p(e,t){var n=e.getBody();n&&(n.style.overflowY=t?"":"hidden",t||(n.scrollTop=0))}function v(e,t,n,i){var o=parseInt(e.getStyle(t,n,i),10);return isNaN(o)?0:o}var l=Object.hasOwnProperty,e=tinymce.util.Tools.resolve("tinymce.PluginManager"),b=tinymce.util.Tools.resolve("tinymce.Env"),r=tinymce.util.Tools.resolve("tinymce.util.Delay"),u=function(e,t,n,i,o){r.setEditorTimeout(e,function(){C(e,t),n--?u(e,t,n,i,o):o&&o()},i)},C=function(e,t,n){var i,o,r,s,a,l,u,g,c,m,f,d=e.dom,h=e.getDoc();h&&(e.plugins.fullscreen&&e.plugins.fullscreen.isFullscreen()?p(e,!0):(i=h.documentElement,o=e.getParam("autoresize_bottom_margin",50,"number"),r=y(e),s=v(d,i,"margin-top",!0),a=v(d,i,"margin-bottom",!0),(l=(l=i.offsetHeight+s+a+o)<0?0:l)+(u=e.getContainer().offsetHeight-e.getContentAreaContainer().offsetHeight)>y(e)&&(r=l+u),(g=e.getParam("max_height",0,"number"))&&g<r?(r=g,p(e,!0)):p(e,!1),r!==t.get()&&(c=r-t.get(),d.setStyle(e.getContainer(),"height",r+"px"),t.set(r),e.fire("ResizeEditor"),b.browser.isSafari()&&b.mac&&(m=e.getWin()).scrollTo(m.pageXOffset,m.pageYOffset),!e.hasFocus()||"setcontent"!==(null==(f=n)?void 0:f.type.toLowerCase())||!0!==f.selection&&!0!==f.paste||e.selection.scrollIntoView(),b.webkit&&c<0&&C(e,t,n))))};e.add("autoresize",function(e){var t,n,i,o,r,s,a=e.settings;l.call(a,"resize")||(e.settings.resize=!1),e.inline||(s=0,r=t={get:function(){return s},set:function(e){s=e}},(o=e).addCommand("mceAutoResize",function(){C(o,r)}),i=t,(n=e).on("init",function(){var e=n.getParam("autoresize_overflow_padding",1,"number"),t=n.dom;t.setStyles(n.getDoc().documentElement,{height:"auto"}),t.setStyles(n.getBody(),{paddingLeft:e,paddingRight:e,"min-height":0})}),n.on("NodeChange SetContent keyup FullscreenStateChanged ResizeContent",function(e){C(n,i,e)}),n.getParam("autoresize_on_init",!0,"boolean")&&n.on("init",function(){u(n,i,20,100,function(){u(n,i,5,1e3)})}))})}();
+9
View File
@@ -0,0 +1,9 @@
/**
* Copyright (c) Tiny Technologies, Inc. All rights reserved.
* Licensed under the LGPL or a commercial license.
* For LGPL see License.txt in the project root for license information.
* For commercial licenses see https://www.tiny.cloud/
*
* Version: 5.10.9 (2023-11-15)
*/
!function(){"use strict";function o(t,e){var r=t||e,n=/^(\d+)([ms]?)$/.exec(""+r);return(n[2]?{s:1e3,m:6e4}[n[2]]:1)*parseInt(r,10)}function n(t){var e=document.location;return t.getParam("autosave_prefix","tinymce-autosave-{path}{query}{hash}-{id}-").replace(/{path}/g,e.pathname).replace(/{query}/g,e.search).replace(/{hash}/g,e.hash).replace(/{id}/g,t.id)}function i(t,e){if(a(e))return t.dom.isEmpty(t.getBody());var r=d.trim(e);if(""===r)return!0;var n=(new DOMParser).parseFromString(r,"text/html");return t.dom.isEmpty(n)}function u(t){var e=parseInt(v.getItem(n(t)+"time"),10)||0;return!((new Date).getTime()-e>o(t.getParam("autosave_retention"),"20m")&&(g(t,!1),1))}function s(t){var e=n(t);!i(t)&&t.isDirty()&&(v.setItem(e+"draft",t.getContent({format:"raw",no_events:!0})),v.setItem(e+"time",(new Date).getTime().toString()),t.fire("StoreDraft"))}function f(t){var e=n(t);u(t)&&(t.setContent(v.getItem(e+"draft"),{format:"raw"}),t.fire("RestoreDraft"))}function c(t){t.undoManager.transact(function(){f(t),g(t)}),t.focus()}function m(r){return function(t){function e(){return t.setDisabled(!u(r))}return t.setDisabled(!u(r)),r.on("StoreDraft RestoreDraft RemoveDraft",e),function(){return r.off("StoreDraft RestoreDraft RemoveDraft",e)}}}var t=tinymce.util.Tools.resolve("tinymce.PluginManager"),a=function(t){return void 0===t},l=tinymce.util.Tools.resolve("tinymce.util.Delay"),v=tinymce.util.Tools.resolve("tinymce.util.LocalStorage"),d=tinymce.util.Tools.resolve("tinymce.util.Tools"),g=function(t,e){var r=n(t);v.removeItem(r+"draft"),v.removeItem(r+"time"),!1!==e&&t.fire("RemoveDraft")},y=tinymce.util.Tools.resolve("tinymce.EditorManager");t.add("autosave",function(t){var e,r,n,a;return t.editorManager.on("BeforeUnload",function(t){var e;d.each(y.get(),function(t){t.plugins.autosave&&t.plugins.autosave.storeDraft(),!e&&t.isDirty()&&t.getParam("autosave_ask_before_unload",!0)&&(e=t.translate("You have unsaved changes are you sure you want to navigate away?"))}),e&&(t.preventDefault(),t.returnValue=e)}),n=e=t,a=o(n.getParam("autosave_interval"),"30s"),l.setEditorInterval(n,function(){s(n)},a),e.ui.registry.addButton("restoredraft",{tooltip:"Restore last draft",icon:"restore-draft",onAction:function(){c(e)},onSetup:m(e)}),e.ui.registry.addMenuItem("restoredraft",{text:"Restore last draft",icon:"restore-draft",onAction:function(){c(e)},onSetup:m(e)}),t.on("init",function(){t.getParam("autosave_restore_when_empty",!1)&&t.dom.isEmpty(t.getBody())&&f(t)}),r=t,{hasDraft:function(){return u(r)},storeDraft:function(){return s(r)},restoreDraft:function(){return f(r)},removeDraft:function(t){return g(r,t)},isEmpty:function(t){return i(r,t)}}})}();
+9
View File
@@ -0,0 +1,9 @@
/**
* Copyright (c) Tiny Technologies, Inc. All rights reserved.
* Licensed under the LGPL or a commercial license.
* For LGPL see License.txt in the project root for license information.
* For commercial licenses see https://www.tiny.cloud/
*
* Version: 5.10.9 (2023-11-15)
*/
!function(){"use strict";function i(t){function o(o,e){t=t.replace(o,e)}return t=n.trim(t),o(/\n/gi,"<br />"),o(/\[b\]/gi,"<strong>"),o(/\[\/b\]/gi,"</strong>"),o(/\[i\]/gi,"<em>"),o(/\[\/i\]/gi,"</em>"),o(/\[u\]/gi,"<u>"),o(/\[\/u\]/gi,"</u>"),o(/\[url=([^\]]+)\](.*?)\[\/url\]/gi,'<a href="$1">$2</a>'),o(/\[url\](.*?)\[\/url\]/gi,'<a href="$1">$1</a>'),o(/\[img\](.*?)\[\/img\]/gi,'<img src="$1" />'),o(/\[color=(.*?)\](.*?)\[\/color\]/gi,'<font color="$1">$2</font>'),o(/\[code\](.*?)\[\/code\]/gi,'<span class="codeStyle">$1</span>&nbsp;'),o(/\[quote.*?\](.*?)\[\/quote\]/gi,'<span class="quoteStyle">$1</span>&nbsp;'),t}var o=tinymce.util.Tools.resolve("tinymce.PluginManager"),n=tinymce.util.Tools.resolve("tinymce.util.Tools");o.add("bbcode",function(o){o.on("BeforeSetContent",function(o){o.content=i(o.content)}),o.on("PostProcess",function(o){function e(o,e){t=t.replace(o,e)}var t;o.set&&(o.content=i(o.content)),o.get&&(o.content=(t=o.content,t=n.trim(t),e(/<a.*?href=\"(.*?)\".*?>(.*?)<\/a>/gi,"[url=$1]$2[/url]"),e(/<font.*?color=\"(.*?)\".*?class=\"codeStyle\".*?>(.*?)<\/font>/gi,"[code][color=$1]$2[/color][/code]"),e(/<font.*?color=\"(.*?)\".*?class=\"quoteStyle\".*?>(.*?)<\/font>/gi,"[quote][color=$1]$2[/color][/quote]"),e(/<font.*?class=\"codeStyle\".*?color=\"(.*?)\".*?>(.*?)<\/font>/gi,"[code][color=$1]$2[/color][/code]"),e(/<font.*?class=\"quoteStyle\".*?color=\"(.*?)\".*?>(.*?)<\/font>/gi,"[quote][color=$1]$2[/color][/quote]"),e(/<span style=\"color: ?(.*?);\">(.*?)<\/span>/gi,"[color=$1]$2[/color]"),e(/<font.*?color=\"(.*?)\".*?>(.*?)<\/font>/gi,"[color=$1]$2[/color]"),e(/<span style=\"font-size:(.*?);\">(.*?)<\/span>/gi,"[size=$1]$2[/size]"),e(/<font>(.*?)<\/font>/gi,"$1"),e(/<img.*?src=\"(.*?)\".*?\/>/gi,"[img]$1[/img]"),e(/<span class=\"codeStyle\">(.*?)<\/span>/gi,"[code]$1[/code]"),e(/<span class=\"quoteStyle\">(.*?)<\/span>/gi,"[quote]$1[/quote]"),e(/<strong class=\"codeStyle\">(.*?)<\/strong>/gi,"[code][b]$1[/b][/code]"),e(/<strong class=\"quoteStyle\">(.*?)<\/strong>/gi,"[quote][b]$1[/b][/quote]"),e(/<em class=\"codeStyle\">(.*?)<\/em>/gi,"[code][i]$1[/i][/code]"),e(/<em class=\"quoteStyle\">(.*?)<\/em>/gi,"[quote][i]$1[/i][/quote]"),e(/<u class=\"codeStyle\">(.*?)<\/u>/gi,"[code][u]$1[/u][/code]"),e(/<u class=\"quoteStyle\">(.*?)<\/u>/gi,"[quote][u]$1[/u][/quote]"),e(/<\/(strong|b)>/gi,"[/b]"),e(/<(strong|b)>/gi,"[b]"),e(/<\/(em|i)>/gi,"[/i]"),e(/<(em|i)>/gi,"[i]"),e(/<\/u>/gi,"[/u]"),e(/<span style=\"text-decoration: ?underline;\">(.*?)<\/span>/gi,"[u]$1[/u]"),e(/<u>/gi,"[u]"),e(/<blockquote[^>]*>/gi,"[quote]"),e(/<\/blockquote>/gi,"[/quote]"),e(/<br \/>/gi,"\n"),e(/<br\/>/gi,"\n"),e(/<br>/gi,"\n"),e(/<p>/gi,""),e(/<\/p>/gi,"\n"),e(/&nbsp;|\u00a0/gi," "),e(/&quot;/gi,'"'),e(/&lt;/gi,"<"),e(/&gt;/gi,">"),e(/&amp;/gi,"&"),t))})})}();
File diff suppressed because one or more lines are too long
+9
View File
@@ -0,0 +1,9 @@
/**
* Copyright (c) Tiny Technologies, Inc. All rights reserved.
* Licensed under the LGPL or a commercial license.
* For LGPL see License.txt in the project root for license information.
* For commercial licenses see https://www.tiny.cloud/
*
* Version: 5.10.9 (2023-11-15)
*/
!function(){"use strict";tinymce.util.Tools.resolve("tinymce.PluginManager").add("code",function(e){var t,o;function n(){return o.execCommand("mceCodeEditor")}return(t=e).addCommand("mceCodeEditor",function(){var n,e;e=(n=t).getContent({source_view:!0}),n.windowManager.open({title:"Source Code",size:"large",body:{type:"panel",items:[{type:"textarea",name:"code"}]},buttons:[{type:"cancel",name:"cancel",text:"Cancel"},{type:"submit",name:"save",text:"Save",primary:!0}],initialData:{code:e},onSubmit:function(e){var t=n,o=e.getData().code;t.focus(),t.undoManager.transact(function(){t.setContent(o)}),t.selection.setCursorLocation(),t.nodeChanged(),e.close()}})}),(o=e).ui.registry.addButton("code",{icon:"sourcecode",tooltip:"Source code",onAction:n}),o.ui.registry.addMenuItem("code",{icon:"sourcecode",text:"Source code",onAction:n}),{}})}();
File diff suppressed because one or more lines are too long
@@ -0,0 +1,9 @@
/**
* Copyright (c) Tiny Technologies, Inc. All rights reserved.
* Licensed under the LGPL or a commercial license.
* For LGPL see License.txt in the project root for license information.
* For commercial licenses see https://www.tiny.cloud/
*
* Version: 5.10.9 (2023-11-15)
*/
!function(){"use strict";tinymce.util.Tools.resolve("tinymce.PluginManager").add("colorpicker",function(){})}();
@@ -0,0 +1,9 @@
/**
* Copyright (c) Tiny Technologies, Inc. All rights reserved.
* Licensed under the LGPL or a commercial license.
* For LGPL see License.txt in the project root for license information.
* For commercial licenses see https://www.tiny.cloud/
*
* Version: 5.10.9 (2023-11-15)
*/
!function(){"use strict";tinymce.util.Tools.resolve("tinymce.PluginManager").add("contextmenu",function(){})}();
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long

Some files were not shown because too many files have changed in this diff Show More