최정임 최정임 2023-06-22
230622 최정임 반응형 작업중
@1e020dceaf9339bce1a61b9adcff49cd1739e1a6
Global.ts
--- Global.ts
+++ Global.ts
@@ -3,8 +3,8 @@
 const BASE_DIR = __dirname;
 const LOG_BASE_DIR = `${__dirname}/server/logs`;
 const SERVICE_STATUS = process.env.NODE_ENV;//development, production
-const PORT = 80;
-const API_SERVER_HOST = 'localhost:8080';
+const PORT = 8080;
+const API_SERVER_HOST = 'localhost:8081';
 
 module.exports = {
     PROJECT_NAME,
client/resources/css/responsive.css
--- client/resources/css/responsive.css
+++ client/resources/css/responsive.css
@@ -1,0 +1,7 @@
+@media all and (max-width: 479px) {
+    #root{width: fit-content;}
+  .main-warp > div {
+    display: block;
+  }
+  .header_menu nav{display: none;}
+}
client/views/pages/AppRouter.js
--- client/views/pages/AppRouter.js
+++ client/views/pages/AppRouter.js
@@ -14,6 +14,7 @@
 import ChargeManagement from '../pages/SystemManagement/ChargeManagement.vue';
 import DataRecord from '../pages/SystemManagement/DataRecord.vue';
 import UserAddForm from '../pages/SystemManagement/UserAddForm.vue';
+import UserModifyForm from '../pages/SystemManagement/UserModifyForm.vue';
 import ManagerAddForm from '../pages/SystemManagement/ManagerAddForm.vue';
 import Mypage from '../pages/User/Mypage.vue';
 import Login from '../pages/main/Login.vue';
@@ -41,6 +42,7 @@
     { path: '/ChargeManagement.page', name: 'ChargeManagement', component: ChargeManagement},
     { path: '/DataRecord.page', name: 'DataRecord', component: DataRecord},
     { path: '/UserAddForm.page', name: 'UserAddForm', component: UserAddForm},
+    { path: '/UserModifyForm.page', name: 'UserModifyForm', component: UserModifyForm},
     { path: '/ManagerAddForm.page', name: 'ManagerAddForm', component: ManagerAddForm},
     { path: '/IdFind.page', name: 'IdFind', component: IdFind},
 ];
client/views/pages/RealtimeStatus/RealtimeStatus.vue
--- client/views/pages/RealtimeStatus/RealtimeStatus.vue
+++ client/views/pages/RealtimeStatus/RealtimeStatus.vue
@@ -15,7 +15,10 @@
             </li>
           </ul>
         </div>
-        <div class="search">
+        <button class="hide-on-mobile" @click="toggleVisibility">
+          Click Me
+        </button>
+        <div class="search" v-if="isButtonVisible">
           <h2>지역설정</h2>
           <div class="box">
             <div class="flex-between m-b">
@@ -207,6 +210,29 @@
 .right {
   width: -webkit-fill-available;
 }
+.hide-on-mobile {
+    display: none;
+  }
+@media all and (max-width: 768px) {
+  .left .wrap{display: -webkit-box;}
+  .slider {
+    overflow-x: hidden;
+  }
+  .hide-on-mobile {
+  display: block;
+}
+  .list {
+    display: flex;
+    flex-wrap: nowrap;
+    padding: 0;
+    margin: 0;
+    list-style: none;
+    transform: translateX(0);
+    transition: transform 0.3s ease-in-out;
+    width: 1800px;
+  }
+  .list li{}
+}
 </style>
 <script>
 import MapPage from "../../component/MapPage.vue";
@@ -214,6 +240,7 @@
 export default {
   data() {
     return {
+      isButtonVisible: true,
       tabs: [
         {
           id: 1,
@@ -240,6 +267,9 @@
     Map: Map,
   },
   methods: {
+    toggleVisibility() {
+      this.isButtonVisible = !this.isButtonVisible;
+    },
     changeTab(tabId) {
       this.activeTab = tabId;
     },
client/views/pages/SystemManagement/UserManagement.vue
--- client/views/pages/SystemManagement/UserManagement.vue
+++ client/views/pages/SystemManagement/UserManagement.vue
@@ -61,7 +61,7 @@
               <th>비고</th>
             </tr>
           </thead>
-          <tbody>
+          <tbody>            
             <tr v-for="(item, idx) in userList" :key="idx" @click="userSelectOnePage(item)">
               <td data-title="NO">{{ idx + 1 }}</td>
               <td data-title="ID">{{ item.user_id }}</td>
@@ -152,14 +152,15 @@
 
     //사용자 상세조회 페이지 이동
     userSelectOnePage: function(user) {
-      this.$router.push({ path: '/', query: {}});
+      this.$router.push({ path: '/UserModifyForm.page'});
     },
 
     //사용자 등록 페이지 이동
     userInsertPage: function() {
       this.$router.push({path: '/UserAddForm.page'});
     }
-  },
+    },
+
   watch: {},
   computed: {},
   components: {
 
client/views/pages/SystemManagement/UserModifyForm.vue (added)
+++ client/views/pages/SystemManagement/UserModifyForm.vue
@@ -0,0 +1,410 @@
+<template>
+  <div class="wrap">
+    <div class="tab-wrap">
+      <ul>
+        <li>
+          <a href="" class="tab active">사용자 관리</a>
+        </li>
+        <li>
+          <a href="" class="tab">접속기록 조회</a>
+        </li>
+      </ul>
+    </div>
+    <div>
+      <div>
+        <h2 class="page-title">사용자 등록</h2>
+      </div>
+      <hr class="margin">
+      <div class="form-wrap">
+        <div class="flex m-b">
+          <span>아이디 : </span>
+          <input type="text" placeholder="ID" v-model="user.user_id">
+          <button type="button" class="idchk green-btn" @click="idChcek">중복확인</button>
+        </div>
+        <div class="flex m-b">
+          <span>비밀번호 : </span>
+          <input type="password" placeholder="Password" v-model="user.user_pw" @change="passwordSyncCheck()">
+        </div>
+        <div class="flex m-b">
+          <span>비밀번호 확인 : </span>
+          <input type="password" placeholder="Confirm Password" v-model="passwordCheck" @change="passwordSyncCheck()">
+        </div>
+        <div v-if="passwordCheckFlag === true" style="color:chartreuse">비밀번호 일치</div>
+        <div v-else-if="passwordCheckFlag === false" style="color:red">비밀번호 불일치</div>
+        <div class="flex m-b">
+          <span>이름 : </span>
+          <input type="text" placeholder="Name" v-model="user.user_nm">
+        </div>
+        <div class="flex m-b">
+          <span>전화번호 : </span>
+          <input type="text" placeholder=" '-' 을 제외하고 입력해주세요." maxlength="13" v-model="telno" @change="phoneCheck" @keyup="getPhoneMask(telno)">
+          <p style="color:red" v-if="telno_boolean === false">&nbsp;전화번호 9~11자리를 입력해주세요.</p>
+        </div>
+        <div class="flex m-b">
+          <span>이메일 : </span>
+          <input type="text" placeholder=" 예) qwer@naver.com" v-model="user.user_eml" @change="emailCheck">
+          <p style="color:red" v-if="email_boolean === false">&nbsp;잘못된 이메일 형식입니다.</p>
+        </div>
+        <div class="flex m-b">
+          <span>관리구역 : </span>
+          <select name="" id="">
+            <option value="">시/도</option>
+          </select>
+          <select name="" id="">
+            <option value="">시/군/구</option>
+          </select>
+          <select name="" id="">
+            <option value="">읍/면/동</option>
+          </select>
+        </div>
+        <div class="flex m-b">
+          <span>비고 : </span>
+          <input type="text" placeholder="참고사항을 입력해주세요." v-model="user.rm">
+        </div>
+        <div class="flex m-b">
+          <span>권한 : </span>
+          <label for="radio_1">
+            <input type="radio" name="radio" id="radio_1" value="시청관리자" v-model="user.user_author">
+            시청관리자
+          </label>
+          <label for="radio_2">
+            <input type="radio" name="radio" id="radio_2" value="지자체관리자" v-model="user.user_author">
+            지자체관리자
+          </label>
+        </div>
+
+        <div class="btn-wrap">
+          <button type="button" class="green-btn" @click="userInsertCheck">등록</button>
+          <router-link to="/UserManagement.page">
+            <span class="btn-2 gray-btn">취소</span>
+          </router-link>
+        </div>
+      </div>
+    </div>
+  </div>
+
+  <div class="modal-wrap" v-if="modal_insert == true">
+    <div class="modal-bg">
+    </div>
+    <div class="modal">
+      <p>사용자를 <span class="txt-point">등록</span>하시겠습니까?</p>
+      <div class="btn-wrap">
+        <button type="button" class="green-btn" @click="userInsert">확인</button>
+        <button type="button" class="gray-btn" @click="modal_insert = false">취소</button>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+import axios from 'axios';
+import COMMON_UTIL from '../../../resources/js/commonUtil.ts';
+
+export default {
+  data: () => {
+    return {
+      user: {
+        user_id: null,
+        user_pw: null,
+        user_nm: null,
+        user_telno: null,
+        user_eml: null,
+        user_author: null,
+        rm: null
+      },
+      passwordCheck: null,
+      passwordCheckFlag: null,
+      telno_boolean: true,
+      email_boolean: true,
+      idChcek_boolean: false,
+      telno: null,
+      modal_insert: false
+
+    };
+  },
+  methods: {
+    //ID 중복 검사
+    idChcek: function() {
+      const vm = this;
+      axios({
+        url: '/user/userSelectOne.json',
+        method: 'post',
+        herders: {
+          'Content-Type': "application/json; charset=UTF-8",
+        },
+        data: vm.user
+      }).then( function (response) {
+        console.log("idCheck - response : ", response.data);
+        if(response.data != null) {
+          alert("중복된 ID 입니다.");
+          vm.idChcek_boolean = false;
+          return false;
+        } else {
+          alert("사용가능한 ID 입니다.");
+          vm.idChcek_boolean = true;
+          return true;
+        }
+      }).catch( function (error) {
+        console.log("idCheck - error : ", error);
+        alert("중복검사 오류, 다시 시도해주세요.");
+        vm.idChcek_boolean = false;
+      });
+    },
+  
+    //비밀번호 일치 여부 검사
+    passwordSyncCheck: function () {
+      if (this.user.user_pw != this.passwordCheck && this.user.user_pw != "" && this.passwordCheck != "" &&
+          this.user.user_pw != null && this.passwordCheck != null) {
+        this.passwordCheckFlag = false;
+      } else if (this.user.user_pw === this.passwordCheck && this.user.user_pw != "" && this.passwordCheck != ""&&
+                 this.user.user_pw != null && this.passwordCheck != null) {
+        this.passwordCheckFlag = true;
+      } else if (this.user.user_pw === "" || this.passwordCheck === "") {
+        this.passwordCheckFlag = null;
+      }
+    },
+
+    //전화번호 입력 시 자동 '-' 삽입
+    getPhoneMask: function(telNumber) {
+      var res = COMMON_UTIL.getMask(telNumber)
+      this.telno = res
+      //서버 전송 값에는 '-' 를 제외하고 숫자만 저장
+      this.user.user_telno = this.telno.replace(/[^0-9]/g, '')
+    },
+    
+    emailCheck: function() {
+      this.email_boolean = true;
+      if (COMMON_UTIL.checkEmail(this.user.user_eml) === false) this.email_boolean = false;
+    },
+
+    phoneCheck: function() {
+      this.telno_boolean = true;
+      if (COMMON_UTIL.checkPhone(this.user.user_telno) === false) this.telno_boolean = false;
+    },
+
+    // 등록버튼 클릭 시 빈칸 검사
+    userInsertCheck: function() {
+      if (COMMON_UTIL.isEmpty(this.user.user_id) === false) {
+        alert('ID를 입력해주세요.');
+        return false;
+      }
+
+      if (this.idChcek_boolean === false) {
+        alert("ID중복검사를 완료해주세요.")
+        return false;
+      }
+
+      if (COMMON_UTIL.isEmpty(this.user.user_pw) === false) {
+        alert('비밀번호를 입력해주세요.');
+        return false;
+      }
+
+      if (this.passwordCheckFlag === false || this.passwordCheckFlag === null) {
+        alert('비밀번호가 일치하지 않습니다.');
+        return false;
+      }
+
+      if (COMMON_UTIL.isEmpty(this.user.user_nm) === false) {
+        alert('이름을 입력해주세요.');
+        return false;
+      }
+
+      if (COMMON_UTIL.isEmpty(this.user.user_telno) === false) {
+        alert('전화번호를 입력해주세요.');
+        return false;
+      }
+
+      if (COMMON_UTIL.checkPhone(this.user.user_telno) === false) {
+        alert('전화번호 형식을 확인해주세요.');
+        return false;
+      }
+
+      if (COMMON_UTIL.isEmpty(this.user.user_eml) === false) {
+        alert('이메일을 입력해주세요.');
+        return false;
+      }
+
+      if (COMMON_UTIL.checkEmail(this.user.user_eml) === false) {
+        alert('이메일 형식을 확인해주세요.');
+        return false;
+      }
+
+      // if (COMMON_UTIL.isEmpty(this.user.) === false) {
+      //   alert('관리구역을 선택해주세요.');
+      //   return false;
+      // }
+
+      if (COMMON_UTIL.isEmpty(this.user.user_author) === false) {
+        alert('권한을 선택해주세요.');
+        return false;
+      }
+      this.modal_insert = true
+    },
+
+    // 사용자 등록
+    userInsert: function() {
+      const vm = this;
+      axios({
+        url: '/user/userInsert.json',
+        method: 'post',
+        herders: {
+          'Content-Type': "application/json; charset=UTF-8",
+        },
+        data: vm.user
+      }).then(function (response) {
+        console.log("userInsert - response : ", response);
+        let result = response.data;
+        if (result > 0) {
+          alert("사용자 등록을 완료 하였습니다.");
+          vm.userSelectListPage();
+        } else {
+          alert("등록 실패, 관리자에게 문의해주세요.");
+          vm.modal_1 = false;
+        }
+      }).catch(function (error) {
+        console.log("userInsert - error : ", error);
+        alert("사용자 등록 오류, 관리자에게 문의해주세요.");
+        vm.modal_1 = false;
+      })
+    },
+
+    userSelectListPage: function () {
+      this.$router.push({ path : '/UserManagement.page'});
+    },
+  },
+  watch: {},
+  computed: {},
+  mounted() {
+    console.log("Main4 mounted");
+  },
+};
+</script>
+
+<style scoped>
+.wrap {
+  width: 155rem;
+  margin: 100px auto;
+}
+
+.tab-wrap {
+  margin-bottom: 30px;
+}
+
+.tab-wrap ul {
+  display: flex;
+  gap: 2rem;
+}
+
+.tab {
+  display: inline-block;
+  width: 20rem;
+  height: 3rem;
+  line-height: 3rem;
+  text-align: center;
+  border-radius: 5px;
+  background: #fff;
+  color: #949292;
+  border: 1px solid #949292;
+}
+
+.tab.active {
+  background: #13833b;
+  color: #fff;
+  border-color: #13833b;
+}
+
+h2.page-title {
+  font-size: 24px;
+}
+
+hr.margin {
+  margin: 30px 0;
+}
+
+.form-wrap {
+  width: 52rem;
+  margin: 0 auto;
+}
+
+.idchk {
+  margin-left: 1rem;
+}
+
+.btn-wrap {
+  margin-top: 30px;
+  text-align: center;
+}
+
+.btn-2 {
+  display: inline-block;
+  padding: 0.3rem 2rem;
+  font-size: 13.333px;
+  color: #000;
+}
+
+.btn-wrap>*:not(:last-child) {
+  margin-right: 2rem;
+}
+
+.form-wrap .flex span {
+  display: inline-block;
+  width: 10rem;
+  padding: 0 5px;
+}
+
+.form-wrap input:not([type="radio"]) {
+  min-width: 30rem;
+}
+
+.form-wrap select {
+  min-width: 9rem;
+}
+
+.form-wrap select:not(:last-child) {
+  margin-right: 1.5rem;
+}
+
+.form-wrap input[type="radio"] {
+  vertical-align: middle;
+}
+
+.form-wrap label:not(:last-child) {
+  margin-right: 2rem;
+}
+
+.modal-wrap {
+  position: fixed;
+  top: 0;
+  left: 0;
+  right: 0;
+  bottom: 0;
+}
+
+.modal-bg {
+  position: absolute;
+  width: 100%;
+  height: 100%;
+  background-color: rgba(0, 0, 0, .6);
+}
+
+.modal {
+  position: absolute;
+  top: 50%;
+  left: 50%;
+  transform: translate(-50%, -50%);
+  max-width: 350px;
+  padding: 5rem;
+  z-index: 2;
+  background-color: #fff;
+  border-radius: 1rem;
+  text-align: center;
+}
+
+.modal .btn-wrap {
+  margin-top: 15px;
+  text-align: center;
+}
+.txt-point {
+  color: #13833b;
+}
+</style>(No newline at end of file)
package-lock.json
--- package-lock.json
+++ package-lock.json
@@ -1,5 +1,5 @@
 {
-  "name": "crosswalk",
+  "name": "crosswalk-1",
   "lockfileVersion": 2,
   "requires": true,
   "packages": {
Add a comment
List