하석형 하석형 04-04
250404 하석형 관리자 menuList 조회 시 자식 메뉴에 context Path 추가, 게시판 내용 조회 시 bbsMngId에 context Path 제거
@e1e96b0651690a88d155babe20bb71a543ec128c
client/resources/js/queryParams.js
--- client/resources/js/queryParams.js
+++ client/resources/js/queryParams.js
@@ -40,7 +40,9 @@
         /** 게시판 pageId 추출 **/
         fnBbsIdExtraction() {
             if(this.$route.path != null && this.$route.path != undefined && this.$route.path != '') {
-                let url = this.$route.path;
+                console.log("this.$route.path", this.$route.path)
+                let url = this.$filters.logicalPath(this.$route.path);
+                console.log("url", url)
                 const regex = /^\/[^\/]+\/([^\/]+)\//; // 두 번째 '/'와 세 번째 '/' 사이의 문자열 추출
                 const match = url.match(regex); // 라우터 경로와 정규식 매칭
                 if(match) {
client/views/common/filters.js
--- client/views/common/filters.js
+++ client/views/common/filters.js
@@ -4,9 +4,15 @@
 const filters = {
 
     // Context Path를 포함한 URL 생성
-    ctxPath(value) {
+    ctxPath(path) {
         const contextPath = store.state.contextPath || '';
-        return contextPath + value;
+        return contextPath + path;
+    },
+
+    // Context Path를 제외한 URL 생성
+    logicalPath(path) {
+        const contextPath = store.state.contextPath || '';
+        return (contextPath !== '/' && path.startsWith(contextPath)) ? path.slice(contextPath.length) : path;
     },
 
     // 아이디 정규식(5~20자의 영문 소문자, 숫자와 특수기호(_),(-)만 사용)
client/views/layout/AdminMenu.vue
--- client/views/layout/AdminMenu.vue
+++ client/views/layout/AdminMenu.vue
@@ -71,16 +71,18 @@
                 };
                 const res = await findBySysMenu(params);
                 if (res.status === 200) {
-                    // `isOpen` 속성을 추가하여 초기 상태 설정
-                    this.menuList = res.data.data.menuList.map(menu => ({
-                        ...menu,
-                        isOpen: false, // 1뎁스 닫힘
-                        childList: menu.childList.map(sub => ({
-                            ...sub,
-                            isOpen: false, // 2뎁스도 닫힘
-                            routerUrl: this.$filters.ctxPath(sub.routerUrl)
-                        }))
-                    }));
+                    this.menuList = this.formatMenuList(res.data.data.menuList);
+                    // // `isOpen` 속성을 추가하여 초기 상태 설정
+                    // this.menuList = res.data.data.menuList.map(menu => ({
+                    //     ...menu,
+                    //     isOpen: false, // 1뎁스 닫힘
+                    //     childList: menu.childList.map(sub => ({
+                    //         ...sub,
+                    //         isOpen: false, // 2뎁스도 닫힘
+                    //         routerUrl: this.$filters.ctxPath(sub.routerUrl)
+                    //     }))
+                    // }));
+
                     // 전체 메뉴 트리 store에 저장
                     this.$store.commit('setMenuList', this.menuList);
 
@@ -141,7 +143,26 @@
                 }
             }
             return null;
-        }
+        },
+
+        // 메뉴 리스트를 가공
+        formatMenuList(menuList) {
+            // `isOpen` 속성을 추가하여 초기 상태 설정
+            return menuList.map(menu => {
+                const formatted = {
+                    ...menu,
+                    isOpen: false,
+                    routerUrl: menu.routerUrl !== "" ? this.$filters.ctxPath(menu.routerUrl) : menu.routerUrl, // 최상위 메뉴가 아닐 때만 context path 가공
+                };
+
+                // 자식이 있으면 재귀 호출
+                if (menu.childList && menu.childList.length > 0) {
+                    formatted.childList = this.formatMenuList(menu.childList);
+                }
+
+                return formatted;
+            });
+        },
     },
     watch: {
         // 나중에 네비게이션 가드에서 form 받을 수 있으면 form adm/main으로 갈때 sotre.state값0로 바꿔주기
client/views/pages/AppRouter.js
--- client/views/pages/AppRouter.js
+++ client/views/pages/AppRouter.js
@@ -162,6 +162,7 @@
   });
 
   AppRouter.beforeEach(async (to, from, next) => {
+    const contextPath = store.state.contextPath; // Context Path 정보
     const routeExists = AppRouter.getRoutes().some(route => route.path === to.path || (route.name && route.name === to.name));
     if (!routeExists) {
       next({ name: 'notfound' });
@@ -214,8 +215,13 @@
       let path = to.path;
       // 게시판일 경우 .page로 끝나는 경로가 있으므로 마지막 '/' 이전 경로로 설정
       if (to.path.includes('BBS_MNG')) {
-        const lastSlashIndex = to.path.lastIndexOf(filters.ctxPath('/')); // 마지막 '/' 인덱스
-        path = to.path.substring(0, lastSlashIndex); // 마지막 '/' 이전 경로
+        let logicalPath = to.path;
+        // context path 제거
+        if (contextPath !== '/' && logicalPath.startsWith(contextPath)) {
+          logicalPath = logicalPath.substring(contextPath.length);
+        }
+        const lastSlashIndex = logicalPath.lastIndexOf('/'); // 마지막 '/' 인덱스
+        path = logicalPath.substring(0, lastSlashIndex); // 마지막 '/' 이전 경로
       }
       store.commit('setPath', path);
       store.commit('setPageAuth', pageAuth);
@@ -248,8 +254,13 @@
       // 권한이 있고 접근 가능한 경우
       if (hasAcc) {
         if (to.path.includes('.page')) {
-          const lastSlashIndex = to.path.lastIndexOf(filters.ctxPath('/')); // 마지막 '/' 인덱스
-          const path = to.path.substring(0, lastSlashIndex); // 마지막 '/' 이전 경로
+          let logicalPath = to.path;
+          // context path 제거
+          if (contextPath !== '/' && logicalPath.startsWith(contextPath)) {
+            logicalPath = logicalPath.substring(contextPath.length);
+          }
+          const lastSlashIndex = logicalPath.lastIndexOf('/'); // 마지막 '/' 인덱스
+          const path = logicalPath.substring(0, lastSlashIndex); // 마지막 '/' 이전 경로
           store.commit('setPath', path);
         }
         // 접속 통계
client/views/pages/adm/system/LoginPolicy/LoginPolicy.vue
--- client/views/pages/adm/system/LoginPolicy/LoginPolicy.vue
+++ client/views/pages/adm/system/LoginPolicy/LoginPolicy.vue
@@ -167,15 +167,16 @@
       if (!this.validation()) {
         return;
       }
-      const isCheck = confirm("Context Path를 변경하면 로그아웃됩니다.\n계속하시겠습니까?");
-        if (isCheck) {
+      // const isCheck = confirm("Context Path를 변경하면 로그아웃됩니다.\n계속하시겠습니까?");
+      const isCheck = confirm("Context Path를 변경하시겠습니까?");
+      if (isCheck) {
         try {
-          let ctx = {path: this.cntxtPth};
+          let ctx = { path: this.cntxtPth };
           const res = await saveCntxtPth(ctx);
           alert(res.data.message);
           if (res.status == 200) {
             let storeCtx = this.cntxtPth;
-            if(storeCtx == '/') {
+            if (storeCtx == '/') {
               storeCtx = '';
             }
             store.commit("setContextPath", storeCtx); // 캐시 초기화 요청을 보내기 위한 Context Path 정보 저장
@@ -201,17 +202,17 @@
         this.$refs.cntxtPth.focus();
         return false;
       }
-      if(this.cntxtPth.length > 50) {
+      if (this.cntxtPth.length > 50) {
         alert("Context Path는 50자 이내로 입력해주세요.");
         this.$refs.cntxtPth.focus();
         return false;
       }
-      if(this.cntxtPth == this.defaultCntxtPth) {
+      if (this.cntxtPth == this.defaultCntxtPth) {
         alert("변경된 내용이 없습니다.");
         this.$refs.cntxtPth.focus();
         return false;
       }
-      if(!regex.test(this.cntxtPth)) {
+      if (!regex.test(this.cntxtPth)) {
         alert("Context Path는 '/'로 시작해야 하며, 알파벳, 숫자, '-' 또는 '_'만 포함할 수 있습니다.");
         this.$refs.cntxtPth.focus();
         return false;
client/views/pages/user/portal/search/Search.vue
--- client/views/pages/user/portal/search/Search.vue
+++ client/views/pages/user/portal/search/Search.vue
@@ -328,7 +328,7 @@
         fnView(item, subItem) {
             let menuPath = null;
             if(item.routerUrl.includes('.page')) {
-                const lastSlashIndex = item.routerUrl.lastIndexOf(this.$filters.ctxPath('/')); // 마지막 '/' 인덱스
+                const lastSlashIndex = item.routerUrl.lastIndexOf('/'); // 마지막 '/' 인덱스
                 menuPath = item.routerUrl.substring(0, lastSlashIndex) ; // 마지막 '/' 이전 경로
             }
 
Add a comment
List