
--- client/resources/api/index.js
+++ client/resources/api/index.js
... | ... | @@ -65,6 +65,7 @@ |
65 | 65 |
store.commit("setUserNm", mbr.userNm); // 사용자 이름 저장 |
66 | 66 |
store.commit('setRoles', mbr.roles); // 사용자 역할 저장 |
67 | 67 |
|
68 |
+ originalReq._retry = true; // 재시도 플래그 설정 |
|
68 | 69 |
return client(originalReq); // 원래 요청 재시도 |
69 | 70 |
} else { |
70 | 71 |
// 200이 아닌 경우 |
--- client/resources/api/user.js
+++ client/resources/api/user.js
... | ... | @@ -20,6 +20,11 @@ |
20 | 20 |
return apiClient.get(`/user/${userId}/users.json`); |
21 | 21 |
} |
22 | 22 |
|
23 |
+// 회원가입 |
|
24 |
+export const join = mber => { |
|
25 |
+ return apiClient.post(`/user/join.json`, mber); |
|
26 |
+} |
|
27 |
+ |
|
23 | 28 |
// 유저 정보 변경 |
24 | 29 |
export const updateUsers = (userId, updateUserDTO) => { |
25 | 30 |
return apiClient.put(`/user/${userId}/users.json`, updateUserDTO); |
... | ... | @@ -28,4 +33,9 @@ |
28 | 33 |
// 유저 비밀번호 변경 |
29 | 34 |
export const updatePassword = (userId, passwordDTO) => { |
30 | 35 |
return apiClient.put(`/user/${userId}/updatePassword.json`, passwordDTO); |
31 |
-}(파일 끝에 줄바꿈 문자 없음) |
|
36 |
+} |
|
37 |
+ |
|
38 |
+// 유저저 목록 조회 (검색조건 있음) |
|
39 |
+export const findAllUsers = searchReqDTO => { |
|
40 |
+ return apiClient.get(`/user/users.json`, { params: searchReqDTO }); |
|
41 |
+ }(파일 끝에 줄바꿈 문자 없음) |
--- client/views/pages/user/CategoryManagement.vue
+++ client/views/pages/user/CategoryManagement.vue
... | ... | @@ -41,9 +41,9 @@ |
41 | 41 |
</div> |
42 | 42 |
<div class="righi-con wfull"> |
43 | 43 |
<div class="btn-group-small flex-end mb-20"> |
44 |
- <div v-if="copySelectedCategory.useAt === 'N' && isNewInsert && selectedCategory.ctgryId != null" |
|
44 |
+ <div v-if="copySelectedCategory.useAt === 'N' && isNewInsert && ctgryId != null" |
|
45 | 45 |
class="button green-line" @click="updateByUseAtCategory">복구</div> |
46 |
- <div v-if="copySelectedCategory.useAt === 'Y' && isNewInsert && selectedCategory.ctgryId != null" |
|
46 |
+ <div v-if="copySelectedCategory.useAt === 'Y' && isNewInsert && ctgryId != null" |
|
47 | 47 |
class="button red-line" @click="updateByUseAtCategory">삭제</div> |
48 | 48 |
<div class="button pink-line-bg flex align-center" @click="resetCategory"><img :src="check_pink" |
49 | 49 |
alt=""> |
... | ... | @@ -108,9 +108,9 @@ |
108 | 108 |
check_blue: 'client/resources/images/checkbox_blue.png', |
109 | 109 |
searchicon: 'client/resources/images/icon/search.png', |
110 | 110 |
selectedCategories: [], |
111 |
+ ctgryId: null, |
|
111 | 112 |
// 선택된 카테고리 정보를 저장할 객체 |
112 | 113 |
selectedCategory: { |
113 |
- ctgryId: null, |
|
114 | 114 |
ctgryNm: null, |
115 | 115 |
useAt: null, |
116 | 116 |
dc: null |
... | ... | @@ -128,6 +128,7 @@ |
128 | 128 |
searchText: null, |
129 | 129 |
useAt: null |
130 | 130 |
}, |
131 |
+ //신규등록 체크크 |
|
131 | 132 |
isNewInsert: true, |
132 | 133 |
}; |
133 | 134 |
}, |
... | ... | @@ -141,7 +142,6 @@ |
141 | 142 |
if (response.status === 200) { |
142 | 143 |
this.selectedCategories = response.data.data.ctgry; // API 응답에서 카테고리 목록을 가져옴 |
143 | 144 |
console.log("가져온 카테고리들 ", this.searchCategories); |
144 |
- this.selectedCategory = {} |
|
145 | 145 |
} |
146 | 146 |
} catch (error) { |
147 | 147 |
console.error("검색 중 오류 발생:", error); |
... | ... | @@ -150,13 +150,14 @@ |
150 | 150 |
// 클릭한 카테고리의 정보를 오른쪽에 표시 |
151 | 151 |
selectCategory(item) { |
152 | 152 |
this.isNewInsert = true; |
153 |
+ this.ctgryId = item.ctgryId, |
|
153 | 154 |
this.selectedCategory = { |
154 |
- ctgryId: item.ctgryId, |
|
155 | 155 |
ctgryNm: item.ctgryNm, |
156 | 156 |
useAt: item.useAt, |
157 | 157 |
dc: item.dc |
158 | 158 |
}; |
159 | 159 |
this.copySelectedCategory = { |
160 |
+ oldCtgryNm: item.ctgryNm, |
|
160 | 161 |
ctgryId: item.ctgryId, |
161 | 162 |
ctgryNm: item.ctgryNm, |
162 | 163 |
useAt: item.useAt, |
... | ... | @@ -171,7 +172,7 @@ |
171 | 172 |
this.selectedCategory.useAt = 'N' |
172 | 173 |
if (confirm("선택한 카테고리를 삭제 하시겠습니까?")) { |
173 | 174 |
try { |
174 |
- const response = await updateCategory(this.selectedCategory.ctgryId, this.selectedCategory); |
|
175 |
+ const response = await updateCategory(this.ctgryId, this.selectedCategory); |
|
175 | 176 |
if (response.status === 200) { |
176 | 177 |
alert("삭제되었습니다.."); |
177 | 178 |
this.searchCategories(); |
... | ... | @@ -186,7 +187,7 @@ |
186 | 187 |
this.selectedCategory.useAt = 'Y' |
187 | 188 |
if (confirm("선택한 카테고리를 복구 하시겠습니까?")) { |
188 | 189 |
try { |
189 |
- const response = await updateCategory(this.selectedCategory.ctgryId, this.selectedCategory); |
|
190 |
+ const response = await updateCategory(this.ctgryId, this.selectedCategory); |
|
190 | 191 |
if (response.status === 200) { |
191 | 192 |
alert("복구되었습니다.."); |
192 | 193 |
this.searchCategories(); |
... | ... | @@ -199,11 +200,11 @@ |
199 | 200 |
} |
200 | 201 |
} |
201 | 202 |
}, |
202 |
- // 신규 등록록 |
|
203 |
+ // 신규 등록 |
|
203 | 204 |
resetCategory() { |
204 | 205 |
this.isNewInsert = false |
206 |
+ this.ctgryId = null; |
|
205 | 207 |
this.selectedCategory = { |
206 |
- ctgryId: null, |
|
207 | 208 |
ctgryNm: null, |
208 | 209 |
useAt: null, |
209 | 210 |
dc: null |
... | ... | @@ -218,10 +219,10 @@ |
218 | 219 |
// 등록 및 수정 |
219 | 220 |
async insertByUpdateCategory() { |
220 | 221 |
if (!this.isValidationCategory()) { |
221 |
- if (this.selectedCategory.ctgryId == null || this.selectedCategory.ctgryId == '') { |
|
222 |
+ if (this.ctgryId == null || this.ctgryId == '') { |
|
222 | 223 |
if (confirm("카테고리 등록을 하시겠습니까?")) { |
223 | 224 |
try { |
224 |
- const response = await saveCategory(this.selectedCategory.ctgryId, this.selectedCategory); |
|
225 |
+ const response = await saveCategory(this.selectedCategory); |
|
225 | 226 |
if (response.status === 200) { |
226 | 227 |
alert("등록되었습니다.."); |
227 | 228 |
this.searchCategories(); |
... | ... | @@ -232,10 +233,12 @@ |
232 | 233 |
} |
233 | 234 |
} |
234 | 235 |
} else { |
235 |
- if (this.copySelectedCategory.ctgryNm == this.selectCategory.ctgryNm) { |
|
236 |
+ this.updateCategory(); |
|
237 |
+ if (this.copySelectedCategory.oldCtgryNm == this.copySelectedCategory.ctgryNm) { |
|
238 |
+ this.copySelectedCategory.oldCtgryNm = null; |
|
236 | 239 |
if (confirm("카테고리 수정을 하시겠습니까?")) { |
237 | 240 |
try { |
238 |
- const response = await updateCategory(this.selectedCategory.ctgryId, this.selectedCategory); |
|
241 |
+ const response = await updateCategory(this.ctgryId, this.copySelectedCategory); |
|
239 | 242 |
if (response.status === 200) { |
240 | 243 |
alert("수정되었습니다.."); |
241 | 244 |
this.searchCategories(); |
... | ... | @@ -248,8 +251,7 @@ |
248 | 251 |
} else { |
249 | 252 |
if (confirm("카테고리 수정을 하시겠습니까?")) { |
250 | 253 |
try { |
251 |
- this.selectCategory.oldCtgryNm = this.copySelectedCategory.ctgryNm; |
|
252 |
- const response = await updateCategory(this.selectedCategory.ctgryId, this.selectedCategory); |
|
254 |
+ const response = await updateCategory(this.ctgryId, this.copySelectedCategory); |
|
253 | 255 |
if (response.status === 200) { |
254 | 256 |
alert("수정되었습니다.."); |
255 | 257 |
this.searchCategories(); |
... | ... | @@ -269,9 +271,10 @@ |
269 | 271 |
toggleUseAt() { |
270 | 272 |
this.selectedCategory.useAt = this.selectedCategory.useAt === 'Y' ? 'N' : 'Y'; |
271 | 273 |
}, |
274 |
+ //취소소 |
|
272 | 275 |
cancelCategory() { |
276 |
+ this.ctgryId = this.copySelectedCategory.ctgryId, |
|
273 | 277 |
this.selectedCategory = { |
274 |
- ctgryId: this.copySelectedCategory.ctgryId, |
|
275 | 278 |
ctgryNm: this.copySelectedCategory.ctgryNm, |
276 | 279 |
useAt: this.copySelectedCategory.useAt, |
277 | 280 |
dc: this.copySelectedCategory.dc, |
... | ... | @@ -279,8 +282,14 @@ |
279 | 282 |
}, |
280 | 283 |
//카테고리 벨류데이션 체크 |
281 | 284 |
isValidationCategory() { |
282 |
- return this.selectedCategory.ctgryNm == null || this.selectedCategory.ctgryNm == '' || this.selectedCategory.useAt == null || this.selectedCategory.useAt == ''; |
|
285 |
+ return this.selectedCategory.ctgryNm == null || this.selectedCategory.ctgryNm == ''; |
|
283 | 286 |
}, |
287 |
+ //수정 함수 |
|
288 |
+ updateCategory(){ |
|
289 |
+ this.copySelectedCategory.ctgryNm = this.selectedCategory.ctgryNm; |
|
290 |
+ this.copySelectedCategory.useAt = this.selectedCategory.useAt; |
|
291 |
+ this.copySelectedCategory.dc = this.selectedCategory.dc; |
|
292 |
+ } |
|
284 | 293 |
|
285 | 294 |
}, |
286 | 295 |
mounted() { |
--- client/views/pages/user/MemberManagement.vue
+++ client/views/pages/user/MemberManagement.vue
... | ... | @@ -17,17 +17,19 @@ |
17 | 17 |
<div class="search-wrap mb-20"> |
18 | 18 |
<div class="search-area"> |
19 | 19 |
<div class="select-box"> |
20 |
- <select name="" id=""> |
|
21 |
- <option value="all" selected>전체</option> |
|
20 |
+ <select v-model="searchReqDTO.searchType"> |
|
21 |
+ <option value="" selected>전체</option> |
|
22 | 22 |
<option value="id">아이디</option> |
23 |
- <option value="name">이름</option> |
|
23 |
+ <option value="nm">이름</option> |
|
24 | 24 |
</select> |
25 | 25 |
</div> |
26 |
- <div class="wfull" style="height: 100%;"> <input type="text" v-model="searchText"></div> |
|
27 |
- <button class="search-btn"><img :src="searchicon" alt=""></button> |
|
26 |
+ <div class="wfull" style="height: 100%;"> |
|
27 |
+ <input type="text" v-model="searchReqDTO.searchText" @keyup.enter="searchUsers"> |
|
28 |
+ </div> |
|
29 |
+ <button class="search-btn" @click="searchUsers"> |
|
30 |
+ <img :src="searchicon" alt=""> |
|
31 |
+ </button> |
|
28 | 32 |
</div> |
29 |
- |
|
30 |
- |
|
31 | 33 |
</div> |
32 | 34 |
<table class="mb-10"> |
33 | 35 |
<thead> |
... | ... | @@ -38,31 +40,27 @@ |
38 | 40 |
</tr> |
39 | 41 |
</thead> |
40 | 42 |
<tbody> |
41 |
- <tr v-for="item in items" :key="index" :class="{ 'delete-member': item.delete }"> |
|
42 |
- <!-- Category 칼럼 --> |
|
43 |
- <td> |
|
44 |
- {{ item.id }} |
|
45 |
- </td> |
|
46 |
- <!-- Checkbox 칼럼 --> |
|
47 |
- <td> |
|
48 |
- {{ item.name }} |
|
49 |
- </td> |
|
50 |
- <td> |
|
51 |
- {{ item.gownhan }} |
|
52 |
- </td> |
|
43 |
+ <tr v-for="(item, index) in selectedUsers" :key="index" |
|
44 |
+ :class="{ 'delete-member': item.useAt === 'N' }" @click="selectUser(item)"> |
|
45 |
+ <td>{{ item.loginId }}</td> |
|
46 |
+ <td>{{ item.userNm }}</td> |
|
47 |
+ <td>{{ item.authorList[0].authorNm }}</td> |
|
53 | 48 |
</tr> |
54 | 49 |
</tbody> |
55 | 50 |
</table> |
56 | 51 |
</div> |
57 | 52 |
<div class="righi-con wfull"> |
58 | 53 |
<div class="btn-group-small flex-end mb-20"> |
59 |
- <div class="button green-line">복구</div> |
|
60 |
- <div class="button red-line">회원탈퇴</div> |
|
61 |
- <div class="button gray-line">비밀번호 초기화</div> |
|
62 |
- <div class="button pink-line-bg flex align-center"><img :src="check_pink" alt=""> |
|
54 |
+ <div v-if="copySelectedUser.useAt === 'N' && isNewInsert && userId != null" |
|
55 |
+ class="button green-line" @click="updateByUseAtUser">복구</div> |
|
56 |
+ <div v-if="copySelectedUser.useAt === 'Y' && isNewInsert && userId != null" class="button red-line" |
|
57 |
+ @click="updateByUseAtUser">회원탈퇴</div> |
|
58 |
+ <div class="button gray-line" @click="restPassword">비밀번호 초기화</div> |
|
59 |
+ <div class="button pink-line-bg flex align-center" @click="resetUser"><img :src="check_pink" alt=""> |
|
63 | 60 |
<p>신규등록</p> |
64 | 61 |
</div> |
65 |
- <div class="button blue-line-bg flex align-center"><img :src="check_blue" alt=""> |
|
62 |
+ <div class="button blue-line-bg flex align-center" @click="insertByUpdateUser"><img |
|
63 |
+ :src="check_blue" alt=""> |
|
66 | 64 |
<p>등록</p> |
67 | 65 |
</div> |
68 | 66 |
<div class="button gray-bg">취소</div> |
... | ... | @@ -71,65 +69,62 @@ |
71 | 69 |
<dl> |
72 | 70 |
<dd> |
73 | 71 |
<label for="id" class="require">아이디</label> |
74 |
- <input type="text" id="id" value="admin" readonly> |
|
72 |
+ <input type="text" id="id" v-model="loginId" :readonly="isNewInsert"> |
|
75 | 73 |
</dd> |
76 | 74 |
<div class="hr"></div> |
77 | 75 |
<dd> |
78 |
- <label for="pw" class="require">비밀번호</label><input type="text" id="pw" value=""> |
|
79 |
- <div class="invalid-feedback border"> |
|
76 |
+ <label for="pw" class="require">비밀번호</label> |
|
77 |
+ <input type="password" id="pw" v-model="password" :disabled="isNewInsert" |
|
78 |
+ :placeholder="isNewInsert ? '' : '비밀번호를 입력하세요'" @input="validatePassword"> |
|
79 |
+ <div class="invalid-feedback border" v-if="!isPasswordValid && password !== null"> |
|
80 | 80 |
<img :src="erroricon" alt=""> |
81 |
- <span>영문, 숫자, 특수문자를 최소 한 가지씩 조합하고 8자 이상 ~ 20자 이내로 입력해주세요.</span> |
|
81 |
+ <span>영문, 숫자, 특수문자를 최소 한 가지씩 조합하고 9자 이상 ~ 20자 이내로 입력해주세요.</span> |
|
82 | 82 |
</div> |
83 |
- |
|
84 | 83 |
</dd> |
85 | 84 |
<div class="hr"></div> |
86 | 85 |
<dd> |
87 | 86 |
<label for="pwcheck" class="require">비밀번호 확인</label> |
88 |
- <input type="text" id="pwcheck" value=""> |
|
89 |
- <div class="invalid-feedback border"> |
|
87 |
+ <input type="password" id="pwcheck" v-model="passwordCheck" :disabled="isNewInsert" |
|
88 |
+ :placeholder="isNewInsert ? '' : '비밀번호를 재입력하세요'"> |
|
89 |
+ <div class="invalid-feedback border" v-if="passwordCheck !== null && !passwordsMatch"> |
|
90 | 90 |
<img :src="erroricon" alt=""> |
91 | 91 |
<span>비밀번호가 일치하지 않습니다.</span> |
92 | 92 |
</div> |
93 |
- |
|
94 | 93 |
</dd> |
95 | 94 |
<div class="hr"></div> |
96 | 95 |
<dd> |
97 | 96 |
<label for="name" class="require">이름</label> |
98 |
- <input type="text" id="name" value="관리자" readonly> |
|
99 |
- |
|
97 |
+ <input type="text" id="name" v-model="selectedUser.userNm"> |
|
100 | 98 |
</dd> |
101 | 99 |
<div class="hr"></div> |
102 | 100 |
<dd> |
103 | 101 |
<label for="gwonhan" class="require">권한</label> |
104 | 102 |
<div class="select-box"> |
105 |
- <select> |
|
106 |
- <option selected>관리자</option> |
|
107 |
- <option></option> |
|
108 |
- <option></option> |
|
103 |
+ <select v-model="selectedUser.authorList[0].authorCode"> |
|
104 |
+ <option value="ROLE_ADMIN" selected>관리자</option> |
|
105 |
+ <option value="ROLE_USER">사용자</option> |
|
109 | 106 |
</select> |
110 | 107 |
</div> |
111 |
- |
|
112 | 108 |
</dd> |
113 | 109 |
<div class="hr"></div> |
114 | 110 |
<dd> |
115 | 111 |
<label for="use" class="require">사용여부</label> |
116 | 112 |
<div class="switch"> |
117 |
- <input type="checkbox" id="switch" /> |
|
113 |
+ <input type="checkbox" id="switch" :checked="selectedUser.useAt === 'Y'" |
|
114 |
+ @change="toggleUseAt" /> |
|
118 | 115 |
<label for="switch">Toggle</label> |
119 |
- |
|
120 | 116 |
</div> |
121 |
- |
|
122 | 117 |
</dd> |
123 | 118 |
</dl> |
124 | 119 |
</form> |
125 | 120 |
</div> |
126 |
- |
|
127 | 121 |
</div> |
128 |
- |
|
129 | 122 |
</div> |
130 | 123 |
</template> |
124 |
+ |
|
131 | 125 |
<script> |
132 | 126 |
import { DoubleLeftOutlined, LeftOutlined, RightOutlined, DoubleRightOutlined } from '@ant-design/icons-vue'; |
127 |
+import { findAllUsers, updateUsers, updatePassword, join } from "../../../resources/api/user"; |
|
133 | 128 |
|
134 | 129 |
export default { |
135 | 130 |
components: { |
... | ... | @@ -141,32 +136,271 @@ |
141 | 136 |
|
142 | 137 |
data() { |
143 | 138 |
return { |
144 |
- items: [ |
|
145 |
- { id: 'user1', name: '카테고리 1', gownhan: '관리자', delete: false }, |
|
146 |
- { id: 'user2', name: '카테고리 2', gownhan: '사용자', delete: false }, |
|
147 |
- { id: 'user3', name: '카테고리 3', gownhan: '사용자', delete: true }, |
|
148 |
- ], |
|
149 |
- isModalOpen: false, |
|
150 |
- // Define the image sources |
|
151 | 139 |
homeicon: 'client/resources/images/icon/home.png', |
152 | 140 |
erroricon: 'client/resources/images/icon/error.png', |
153 | 141 |
righticon: 'client/resources/images/icon/right.png', |
154 | 142 |
check_pink: 'client/resources/images/checkbox_pink.png', |
155 | 143 |
check_blue: 'client/resources/images/checkbox_blue.png', |
156 | 144 |
searchicon: 'client/resources/images/icon/search.png', |
157 |
- fileNames: [], |
|
158 |
- selectedCategories: [], |
|
145 |
+ selectedUsers: [], |
|
146 |
+ //사용자 로그인 아이다 |
|
147 |
+ loginId: null, |
|
148 |
+ //사용자 아이디 |
|
149 |
+ userId: null, |
|
150 |
+ // 비밀번호 추가 |
|
151 |
+ password: null, |
|
152 |
+ // 비밀번호 확인 추가 |
|
153 |
+ passwordCheck: null, |
|
154 |
+ // 비밀번호 유효성 체크를 위한 변수 |
|
155 |
+ isPasswordValid: false, |
|
156 |
+ // 비밀번호 초기화 |
|
157 |
+ passwordResetAt: { |
|
158 |
+ oldPassword: "qwer1234!", |
|
159 |
+ newPassword: "qwer1234!", |
|
160 |
+ resetAt: true |
|
161 |
+ }, |
|
162 |
+ // 선택된 사용자 수정 |
|
163 |
+ selectedUser: { |
|
164 |
+ userNm: null, |
|
165 |
+ useAt: null, |
|
166 |
+ authorUpdateCheck: false, |
|
167 |
+ authorList: [ |
|
168 |
+ { authorCode: "ROLE_ADMIN" } |
|
169 |
+ ] |
|
170 |
+ }, |
|
171 |
+ // 선택된 사용자 복사 |
|
172 |
+ copySelectedUser: { |
|
173 |
+ userNm: null, |
|
174 |
+ useAt: null, |
|
175 |
+ authorList: [ |
|
176 |
+ { authorCode: "ROLE_ADMIN" } |
|
177 |
+ ] |
|
178 |
+ }, |
|
179 |
+ //회원가입 |
|
180 |
+ joinDTO: { |
|
181 |
+ loginId: null, |
|
182 |
+ userNm: null, |
|
183 |
+ password: null, |
|
184 |
+ authorList: [] |
|
185 |
+ }, |
|
186 |
+ // 사용자 검색 객체 |
|
187 |
+ searchReqDTO: { |
|
188 |
+ searchType: "", |
|
189 |
+ searchText: null, |
|
190 |
+ userSttus: null, |
|
191 |
+ useAt: null |
|
192 |
+ }, |
|
193 |
+ // 신규등록 체크 |
|
194 |
+ isNewInsert: true, |
|
159 | 195 |
}; |
160 | 196 |
}, |
197 |
+ methods: { |
|
198 |
+ //등록 함수 |
|
199 |
+ updateUser() { |
|
200 |
+ this.joinDTO.loginId = this.loginId; |
|
201 |
+ this.joinDTO.userNm = this.selectedUser.userNm; |
|
202 |
+ this.joinDTO.password = this.password; |
|
203 |
+ this.joinDTO.authorList = [this.selectedUser.authorList[0]]; |
|
204 |
+ }, |
|
205 |
+ // 등록 및 수정 |
|
206 |
+ async insertByUpdateUser() { |
|
207 |
+ if (!this.isValidationUser()) { |
|
208 |
+ if (this.userId == null || this.userId == '') { |
|
209 |
+ this.updateUser(); |
|
210 |
+ if (confirm("회원가입을 하시겠습니까?")) { |
|
211 |
+ try { |
|
212 |
+ const response = await join(this.joinDTO); |
|
213 |
+ if (response.status === 200) { |
|
214 |
+ alert("회원가입되었습니다.."); |
|
215 |
+ this.searchUsers(); |
|
216 |
+ |
|
217 |
+ } |
|
218 |
+ } catch (error) { |
|
219 |
+ alert("회원가입이 실패하였습니다."); |
|
220 |
+ this.searchUsers(); |
|
221 |
+ } |
|
222 |
+ } |
|
223 |
+ } |
|
224 |
+ } else { |
|
225 |
+ // 권한이 변경되었는지 확인 |
|
226 |
+ console.log("복사", this.copySelectedUser.authorList[0].authorCode); |
|
227 |
+ console.log("본체", this.selectedUser.authorList[0].authorCode); |
|
228 |
+ const isAuthorChanged = this.copySelectedUser.authorList[0].authorCode !== this.selectedUser.authorList[0].authorCode; |
|
229 |
+ console.log("권한이 같은지 다른지 ", isAuthorChanged); |
|
230 |
+ if (isAuthorChanged) { |
|
231 |
+ this.selectedUser.authorUpdateCheck = true; // 권한 변경 체크 |
|
232 |
+ if (confirm("회원 수정을 하시겠습니까?")) { |
|
233 |
+ try { |
|
234 |
+ const response = await updateUsers(this.userId, this.selectedUser); |
|
235 |
+ if (response.status === 200) { |
|
236 |
+ alert("수정되었습니다.."); |
|
237 |
+ this.searchUsers(); |
|
238 |
+ } |
|
239 |
+ } catch (error) { |
|
240 |
+ alert("수정이 실패하였습니다."); |
|
241 |
+ this.searchUsers(); |
|
242 |
+ } |
|
243 |
+ } |
|
244 |
+ } else { |
|
245 |
+ // 권한이 변경되지 않았다면 기존 수정 로직 실행 |
|
246 |
+ if (confirm("회원 수정을 하시겠습니까?")) { |
|
247 |
+ try { |
|
248 |
+ const response = await updateUsers(this.userId, this.selectedUser); |
|
249 |
+ if (response.status === 200) { |
|
250 |
+ alert("수정되었습니다.."); |
|
251 |
+ this.searchUsers(); |
|
252 |
+ } |
|
253 |
+ } catch (error) { |
|
254 |
+ alert("수정이 실패하였습니다."); |
|
255 |
+ this.searchUsers(); |
|
256 |
+ } |
|
257 |
+ } |
|
258 |
+ } |
|
259 |
+ } |
|
260 |
+ }, |
|
261 |
+ //사용자 벨류데이션 체크 |
|
262 |
+ isValidationUser() { |
|
263 |
+ return this.selectedUser.userNm == null || this.selectedUser.userNm == '' || this.loginId == null || this.loginId == '' || this.password == null || this.password == ''; |
|
264 |
+ }, |
|
265 |
+ validatePassword() { |
|
266 |
+ // 빈 문자열이나 null 체크 |
|
267 |
+ if (!this.password) { |
|
268 |
+ this.isPasswordValid = false; // 빈 문자열일 경우 유효성 false |
|
269 |
+ return; |
|
270 |
+ } |
|
271 |
+ |
|
272 |
+ // 정규식: 영문, 숫자, 특수문자를 최소 한 가지씩 조합하고 8자 이상 20자 이내 |
|
273 |
+ const passwordRegex = /^(?=.*[a-zA-Z])(?=.*[0-9])(?=.*[!@#$%^&*])[A-Za-z\d!@#$%^&*]{9,20}$/; |
|
274 |
+ this.isPasswordValid = passwordRegex.test(this.password); |
|
275 |
+ }, |
|
276 |
+ // 사용자 전체조회 |
|
277 |
+ async searchUsers() { |
|
278 |
+ try { |
|
279 |
+ const response = await findAllUsers(this.searchReqDTO); |
|
280 |
+ if (response.status === 200) { |
|
281 |
+ this.selectedUsers = response.data.data.users; |
|
282 |
+ console.log("가져온 사용자들 ", response); |
|
283 |
+ } |
|
284 |
+ } catch (error) { |
|
285 |
+ console.error("검색 중 오류 발생:", error); |
|
286 |
+ } |
|
287 |
+ }, |
|
288 |
+ // 선택한 사용자 |
|
289 |
+ selectUser(item) { |
|
290 |
+ this.isNewInsert = true; |
|
291 |
+ |
|
292 |
+ this.loginId = item.loginId; |
|
293 |
+ this.userId = item.userId; |
|
294 |
+ this.password = null; |
|
295 |
+ this.passwordCheck = null; |
|
296 |
+ |
|
297 |
+ this.selectedUser = { |
|
298 |
+ userNm: item.userNm, |
|
299 |
+ useAt: item.useAt, |
|
300 |
+ authorList: [item.authorList[0]] |
|
301 |
+ }; |
|
302 |
+ |
|
303 |
+ // 깊은 복사를 통해 copySelectedUser를 설정 |
|
304 |
+ this.copySelectedUser = JSON.parse(JSON.stringify(this.selectedUser)); |
|
305 |
+ |
|
306 |
+ console.log("선택 된 카테고리", this.selectedUser.authorList[0]); |
|
307 |
+ }, |
|
308 |
+ // 스위치 사용여부 |
|
309 |
+ toggleUseAt() { |
|
310 |
+ if (!this.isNewInsert) { |
|
311 |
+ alert("회원가입 시 사용여부 변경이 불가능합니다."); |
|
312 |
+ return; // 변경을 막기 위해 함수 종료 |
|
313 |
+ } |
|
314 |
+ |
|
315 |
+ this.selectedUser.useAt = this.selectedUser.useAt === 'Y' ? 'N' : 'Y'; |
|
316 |
+ }, |
|
317 |
+ // 삭제 또는 복구 로직 |
|
318 |
+ async updateByUseAtUser() { |
|
319 |
+ if (this.selectedUser.useAt === 'Y') { |
|
320 |
+ this.selectedUser.useAt = 'N' |
|
321 |
+ if (confirm("선택한 사용자를 탈퇴 하시겠습니까?")) { |
|
322 |
+ try { |
|
323 |
+ const response = await updateUsers(this.userId, this.selectedUser); |
|
324 |
+ if (response.status === 200) { |
|
325 |
+ alert("탈퇴되었습니다.."); |
|
326 |
+ this.copySelectedUser.useAt = 'N'; |
|
327 |
+ this.searchUsers(); |
|
328 |
+ } |
|
329 |
+ } catch (error) { |
|
330 |
+ alert("탈퇴가 실패하였습니다."); |
|
331 |
+ this.searchUsers(); |
|
332 |
+ |
|
333 |
+ } |
|
334 |
+ } |
|
335 |
+ } else { |
|
336 |
+ this.selectedUser.useAt = 'Y' |
|
337 |
+ if (confirm("선택한 사용자를 복구 하시겠습니까?")) { |
|
338 |
+ try { |
|
339 |
+ const response = await updateUsers(this.userId, this.selectedUser); |
|
340 |
+ if (response.status === 200) { |
|
341 |
+ alert("복구되었습니다.."); |
|
342 |
+ this.copySelectedUser.useAt = 'Y'; |
|
343 |
+ this.searchUsers(); |
|
344 |
+ } |
|
345 |
+ } catch (error) { |
|
346 |
+ alert("복구가 실패하였습니다."); |
|
347 |
+ this.searchUsers(); |
|
348 |
+ |
|
349 |
+ } |
|
350 |
+ } |
|
351 |
+ } |
|
352 |
+ }, |
|
353 |
+ // 비밀번호 초기화 |
|
354 |
+ async restPassword() { |
|
355 |
+ if (confirm("비밀번호 초기화를 하시겠습니까?")) { |
|
356 |
+ if (this.userId == null || this.userId == '') { |
|
357 |
+ alert("신규등록은 초기화가 불가능합니다.") |
|
358 |
+ } else { |
|
359 |
+ try { |
|
360 |
+ const response = await updatePassword(this.userId, this.passwordResetAt); |
|
361 |
+ if (response.status === 200) { |
|
362 |
+ alert("초기화화되었습니다.."); |
|
363 |
+ this.searchUsers(); |
|
364 |
+ } |
|
365 |
+ } catch (error) { |
|
366 |
+ alert("초기화가 실패하였습니다."); |
|
367 |
+ this.searchUsers(); |
|
368 |
+ |
|
369 |
+ } |
|
370 |
+ } |
|
371 |
+ } |
|
372 |
+ }, |
|
373 |
+ // 사용자 초기화 |
|
374 |
+ resetUser() { |
|
375 |
+ this.isNewInsert = false; |
|
376 |
+ |
|
377 |
+ this.loginId = null; |
|
378 |
+ this.userId = null; |
|
379 |
+ |
|
380 |
+ this.selectedUser = { |
|
381 |
+ userNm: null, |
|
382 |
+ useAt: "Y", |
|
383 |
+ authorList: [ |
|
384 |
+ { authorCode: "ROLE_ADMIN" } |
|
385 |
+ ] |
|
386 |
+ }; |
|
387 |
+ |
|
388 |
+ this.copySelectedUser = { |
|
389 |
+ userNm: null, |
|
390 |
+ useAt: null, |
|
391 |
+ authorList: [ |
|
392 |
+ { authorCode: "ROLE_ADMIN" } |
|
393 |
+ ] |
|
394 |
+ }; |
|
395 |
+ }, |
|
396 |
+ }, |
|
161 | 397 |
computed: { |
162 |
- filteredItems() { |
|
163 |
- // This could be modified to support filtering based on searchQuery |
|
164 |
- return this.items.filter(item => |
|
165 |
- item.id.includes(this.searchQuery) |
|
166 |
- ); |
|
398 |
+ passwordsMatch() { |
|
399 |
+ return this.password === this.passwordCheck; |
|
167 | 400 |
} |
168 | 401 |
}, |
169 |
- methods: { |
|
402 |
+ mounted() { |
|
403 |
+ this.searchUsers(); // 컴포넌트가 마운트될 때 사용자 목록을 조회 |
|
170 | 404 |
} |
171 | 405 |
}; |
172 | 406 |
</script> |
--- client/views/pages/user/MyInfo.vue
+++ client/views/pages/user/MyInfo.vue
... | ... | @@ -41,7 +41,7 @@ |
41 | 41 |
@input="validatePassword"> |
42 | 42 |
<div class="invalid-feedback border" v-if="!isPasswordValid && userPassword.newPassword !== null"> |
43 | 43 |
<img :src="erroricon" alt=""> |
44 |
- <span>영문, 숫자, 특수문자를 최소 한 가지씩 조합하고 8자 이상 ~ 20자 이내로 입력해주세요.</span> |
|
44 |
+ <span>영문, 숫자, 특수문자를 최소 한 가지씩 조합하고 9자 이상 ~ 20자 이내로 입력해주세요.</span> |
|
45 | 45 |
</div> |
46 | 46 |
</dd> |
47 | 47 |
<div class="hr"></div> |
... | ... | @@ -103,8 +103,8 @@ |
103 | 103 |
return; |
104 | 104 |
} |
105 | 105 |
|
106 |
- // 정규식: 영문, 숫자, 특수문자를 최소 한 가지씩 조합하고 8자 이상 20자 이내 |
|
107 |
- const passwordRegex = /^(?=.*[a-zA-Z])(?=.*[0-9])(?=.*[!@#$%^&*])[A-Za-z\d!@#$%^&*]{8,20}$/; |
|
106 |
+ // 정규식: 영문, 숫자, 특수문자를 최소 한 가지씩 조합하고 9자 이상 20자 이내 |
|
107 |
+ const passwordRegex = /^(?=.*[a-zA-Z])(?=.*[0-9])(?=.*[!@#$%^&*])[A-Za-z\d!@#$%^&*]{9,20}$/; |
|
108 | 108 |
this.isPasswordValid = passwordRegex.test(this.userPassword.newPassword); |
109 | 109 |
}, |
110 | 110 |
async fnDeleteUser() { |
Add a comment
Delete comment
Once you delete this comment, you won't be able to recover it. Are you sure you want to delete this comment?