
File name
Commit message
Commit date
File name
Commit message
Commit date
File name
Commit message
Commit date
File name
Commit message
Commit date
File name
Commit message
Commit date
<template>
<div class="container">
<div class="page-titleZone flex justify-between align-center">
<p class="main-title flex80">사용자 관리</p>
<PageNavigation />
</div>
<div class="content-wrap">
<div class="content content-box flex100">
<div class="column-list">
<div class="content-titleZone flex justify-between align-center">
<p class="box-title">사용자 목록</p>
<div class="flex justify-end align-center">
<select class="square-select" v-model="search_data.key">
<option :value="null" disabled>선택</option>
<option value="ui.user_id">아이디</option>
<option value="ui.user_nm">이름</option>
<option value="orgnzt_info.dept_nm">부서</option>
</select>
<div class="search-square">
<input type="text" class="square-input" v-model="search_data.value" placeholder="검색어를 입력해주세요." @keyup.enter="searchUser" />
<button class="square-button blue-btn" @click="searchUser">
<svg-icon type="mdi" :path="searchPath" class="square-icon"></svg-icon>
</button>
</div>
</div>
</div>
<div class="flex justify-between align-center">
<div class="count-zone">
<p>총 <span>{{ memberList.length }}</span>건 중 <span>{{ selectedMembers.length }}</span>건 선택</p>
</div>
<div class="cunt-selectZone">
<select v-model="selectedPerPage" @change="updatePerPage">
<option value="10">10개 보기</option>
<option value="20">20개 보기</option>
</select>
</div>
</div>
<div class="table-zone">
<table class="list-table">
<colgroup>
<col style="width: 5%" />
<col style="width: 5%" />
<col style="width: 16%" />
<col style="width: 16%" />
<col style="width: 16%" />
<col style="width: 16%" />
<col style="width: 16%" />
<col style="width: 5%" />
</colgroup>
<thead>
<tr>
<th>
<input type="checkbox" @click="memberCheckAll" v-model="checkAll" />
</th>
<th>No</th>
<th>아이디</th>
<th>이름</th>
<th>이메일</th>
<th>부서</th>
<th>등록날짜</th>
<th>잠김여부</th>
</tr>
</thead>
<tbody>
<tr v-for="(member, index) in memberList" :key="index" @click="loadHostData(member)">
<td>
<input type="checkbox" @click.stop="" v-model="selectedMembers" :value="member.userId" name="memberList" />
</td>
<td>{{ memberIdx - index }}</td>
<td>{{ member.userId }}</td>
<td>{{ member.userNm }}</td>
<td>{{ member.userEmail }}</td>
<td>{{ member.deptNm }}</td>
<td>{{ $filters.dateTime(member.creatDt) }}</td>
<td>{{ member.lockAt == false ? "X" : "Y" }}</td>
</tr>
</tbody>
</table>
</div>
<!-- <div v-if="this.author == 'ROLE_ADMIN'" class="flex justify-end"> -->
<PaginationButton v-model:currentPage="search.currentPage" :perPage="search.perPage" :totalCount="search.totalRows" :maxRange="5" :click="fetchMemberList" />
<div class="flex justify-end">
<button class="red-border-btn small-btn" @click="deleteSelectedMembers">선택 삭제</button>
</div>
</div>
<div class="data-set">
<div class="form-box">
<div class="content-titleZone">
<p class="box-title" v-if="!dataLoaded">사용자 등록</p>
<p class="box-title" v-else>사용자 수정</p>
</div>
<div class="table-zone">
<table class="form-table2">
<colgroup>
<col style="width: 10%" />
<col style="width: 40%" />
<col style="width: 10%" />
<col style="width: 40%" />
</colgroup>
<tbody>
<tr>
<th>아이디</th>
<td style="display: flex">
<input type="text" name="" id="userId" class="full-input" v-model="memberData.userId" :disabled="dataLoaded" />
<button @click="checkDuplicate" style="flex-grow: 1" class="small-btn blue-border-btn" v-if="!dataLoaded"> 중복확인 </button>
</td>
<th>이름</th>
<td>
<input type="text" name="" id="userNm" class="full-input" v-model="memberData.userNm" />
</td>
</tr>
<tr v-if="!dataLoaded">
<th>비밀번호</th>
<td>
<input id="userPassword" type="password" class="full-input" style="width: 100%" v-model="memberData.userPassword" />
</td>
<th>비밀번호 변경 확인</th>
<td>
<input id="passwordConfirm" type="password" class="full-input" style="width: 100%" v-model="passwordConfirm" />
</td>
</tr>
<tr>
<th>이메일</th>
<td style="display: flex">
<input type="text" name="" id="email" class="full-input" v-model="memberData.userEmail" />
<button style="flex-grow: 1" class="small-btn blue-border-btn" v-if="
dataLoaded &&
originalmemberData.userEmail !== memberData.userEmail
" @click="mailDuplicateCheck()"> 중복확인 </button>
<button style="flex-grow: 1" class="small-btn blue-border-btn" v-if="!dataLoaded" @click="mailDuplicateCheck()"> 중복확인 </button>
</td>
<th>권한</th>
<td style="display: flex">
<select class="full-select" v-model="memberData.author" @change="changeAuthor">
<option :value="null" disabled>권한을 선택해주세요.</option>
<option v-for="(author, idx) in authorList" :key="idx" :value="author.author">{{ author.author_dc }}</option>
</select>
</td>
</tr>
<tr>
<th>부서</th>
<td>
<select name="" id="deptNm" class="full-select" v-model="memberData.dept_code">
<option :value="null" disabled>부서를 선택해주세요.</option>
<option v-for="(department, idx) in departmentList" :key="idx" :value="department.dept_code"> {{ department.dept_nm }} </option>
</select>
</td>
<th><template v-if="dataLoaded">잠김여부</template></th>
<td style="display: flex">
<template v-if="dataLoaded">
<input type="text" class="full-input" :value="memberData.lockAt ? '사용불가' : '사용가능'" readonly>
<button class="blue-border-btn small-btn" @click="toggleLockAtStatus" style="flex-grow: 1"> {{ memberData.lockAt ? "잠금해제" : "잠금설정" }} </button>
</template>
</td>
</tr>
</tbody>
</table>
</div>
<!-- <div v-if="this.author == 'ROLE_ADMIN' || memberData.userId == this.userId" class="flex justify-end"> -->
<div class="flex justify-end">
<template v-if="dataLoaded">
<button class="blue-border-btn small-btn" @click="openModal()">비밀번호 변경</button>
<button class="blue-btn small-btn" @click="updateMember()">수정</button>
<button class="red-border-btn small-btn" @click="insertForm()">취소</button>
</template>
<template v-else>
<button class="blue-btn small-btn" @click="memberInsert()">등록</button>
<button class="darkg-border-btn small-btn" @click="resetForm()">초기화</button>
</template>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- 비밀번호 변경 모달 -->
<div v-show="modalOpen" class="modal-wrapper">
<div class="modal-container small-modal">
<div class="modal-title text-ct">
<h2>비밀번호 변경</h2>
</div>
<div class="modal-content-monthly">
<div class="table-zone">
<table class="form-table2">
<colgroup>
<col style="width: 40%" />
<col style="width: 60%" />
</colgroup>
<tbody>
<tr>
<th>새 비밀번호</th>
<td>
<input type="password" id="pwChange" class="full-input" v-model="pwChange" />
</td>
</tr>
<tr>
<th>새 비밀번호 확인</th>
<td>
<input type="password" id="pwChangeCheck" class="full-input" v-model="pwChangeCheck" />
</td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="modal-end flex justify-between" style="flex-wrap: nowrap;">
<button class="blue-btn large-btn" @click="passwordChange()">변경</button>
<button class="gray-btn large-btn" @click="closeModal()">취소</button>
</div>
</div>
</div>
</template>
<script>
import PageNavigation from "../../component/PageNavigation.vue";
import PaginationButton from "../../component/PaginationButton.vue";
import SvgIcon from "@jamescoyle/vue-icon";
import { mdiMagnify } from "@mdi/js";
import axios from "axios";
import store from "../AppStore";
export default {
data() {
return {
search: this.$getDefaultSerchVO(),
search_data: this.$getDefaultSerchItem(null, "String"),
searchPath: mdiMagnify,
inputValue: null,
memberData: {
userId: null,
userPassword: null,
userNm: null,
deptNm: null,
userEmail: null,
author: null,
dept_code: null,
lockAt: null,
},
userId: null,
authList: null,
author: null,
dept_code: null,
memberList: [],
passwordConfirm: null,
changePwConfirm: null,
changPw: null,
departmentList: [],
authorList: [],
isDuplicateChecked: false,
emailDuplicateChecked: false,
memberIdx: 0,
selectedMembers: [],
checkAll: false,
//페이지 당 보여줄 수
selectedPerPage: "10",
//비밀번호 변경 모달창
modalOpen: false,
pwChange: null,
pwChangeCheck: null,
changeEmail: null,
//부서
dept_search_data: this.$getDefaultSerchItem(null, "String"),
deptSearch: this.$getDefaultSerchVO(),
};
},
methods: {
searchInit: function () {
this.search.searchObjectList.push(this.search_data);
},
deptSearchInit: function () {
this.deptSearch.searchObjectList.push(this.dept_search_data);
},
insertForm: function () {
this.dataLoaded = false;
this.resetForm();
},
toggleLockAtStatus() {
this.memberData.lockAt = !this.memberData.lockAt;
},
//사용자 등록
memberInsert: function () {
const vm = this;
if (!vm.memberInsertValidation()) {
return;
}
axios({
url: "/member",
method: "post",
headers: {
"Content-Type": "application/json; charset=UTF-8",
},
data: vm.memberData,
})
.then(function (response) {
if (response.data.checkMessage.status === 200) {
vm.$showAlert("사용자 등록", "사용자 등록이 완료되었습니다.");
vm.fetchMemberList();
vm.resetData();
} else {
vm.$showAlert("사용자 등록", response.data.checkMessage.message);
}
})
.catch(function (error) {
vm.$showAlert(
"사용자 등록",
"사용자 등록에 실패했습니다. 다시 시도해주세요."
);
});
},
//검색기준 유효성 검사
searchUser: function () {
if (!this.search_data.key) {
this.$showAlert("회원 검색", "검색 기준을 선택하세요.");
return;
}
this.fetchMemberList();
},
//사용자 목록 조회
fetchMemberList() {
const vm = this;
axios({
url: "/member/list",
method: "post",
data: vm.search,
})
.then(function (response) {
if (response.data) {
vm.memberList = response.data.resultData.selectMemberList;
vm.search.totalRows = response.data.resultData.totalRow;
vm.memberIdx =
vm.search.totalRows -
(vm.search.currentPage - 1) * vm.search.perPage;
} else {
this.$showAlert(
"에러 발생",
"에러가 발생했습니다. 관리자에게 문의해 주세요."
);
}
})
.catch(function (error) {
vm.$showAlert(
"회원 목록",
"목록 불러오기 오류, 관리자에게 문의바랍니다."
);
});
},
//사용자 정보 변경
updateMember: async function () {
const vm = this;
if (
JSON.stringify(vm.memberData) ===
JSON.stringify(vm.originalmemberData) &&
(vm.changPw === null || vm.changPw === "")
) {
vm.$showAlert("사용자 수정", "수정된 정보가 없습니다.");
return;
}
if (!vm.updateMemberInfoValidation()) return;
axios
.put("/member", vm.memberData)
.then((response) => {
if (response.data.checkMessage.status === 200) {
vm.$showAlert("사용자 수정", "사용자 정보가 수정되었습니다.");
vm.changPw = null;
vm.changePwConfirm = null;
vm.resetData();
vm.fetchMemberList();
} else {
vm.$showAlert("사용자 수정", response.data.checkMessage.message);
}
})
.catch((error) => {
// vm.$showAlert('사용자 수정', '수정 오류, 관리자에게 문의해주세요.');
});
},
//사용자 정보 변경용 유효성 검사
updateMemberInfoValidation: function () {
const vm = this;
//1.사용자 이름 유효성 검사
let validateName = /^[가-힣A-Za-z\s]+$/;
if (!validateName.test(vm.memberData.userNm)) {
vm.$showAlert(
"사용자 수정",
"이름에 숫자와 특수문자를 입력할 수 없습니다."
);
return false;
}
//2.이메일 null 검사
if (!vm.memberData.userEmail) {
vm.$showAlert("사용자 수정", "이메일을 입력하세요.");
document.getElementById("email").focus();
return false;
}
//3.이메일 유효성 검사
if (!vm.$email(vm.memberData.userEmail)) {
vm.$showAlert("사용자 수정", "이메일 형식이 올바르지 않습니다.");
document.getElementById("email").focus();
return false;
}
//4.이메일 중복 검사 여부 체크
//이메일을 안바꾼 경우(전처리)
if (
vm.dataLoaded &&
vm.originalmemberData.userEmail === vm.memberData.userEmail
) {
vm.emailDuplicateChecked = true;
}
if (!vm.emailDuplicateChecked) {
vm.$showAlert("사용자 수정", "이메일 중복확인 후 등록해주세요.");
return false;
}
return true;
},
getAuthorList() {
const vm = this;
axios({
url: "/member/getAuthorInfo",
method: "get",
})
.then(function (response) {
vm.authorList = response.data.resultData.getAuthorInfo;
})
.catch(function (error) {
this.$showAlert(
"에러 발생",
"에러가 발생했습니다. 관리자에게 문의해 주세요."
);
});
},
//ID중복 검사
checkDuplicate() {
const vm = this;
if (!vm.$idCheck(vm.memberData.userId)) {
vm.$showAlert(
"사용자 등록",
"아이디 형식이 올바르지 않습니다. (5~20자의 영문 소문자, 숫자와 특수기호(_),(-)만 사용가능)"
);
document.getElementById("userId").focus();
return false;
}
axios({
url: "/member/" + vm.memberData.userId,
method: "get",
headers: {
"Content-Type": "application/json; charset=UTF-8",
},
})
.then((response) => {
if (response.data.resultData.checkDuplicateUserId) {
vm.$showAlert("아이디 중복확인", "사용중인 아이디입니다.");
vm.isDuplicateChecked = false;
} else {
vm.$showAlert("아이디 중복확인", "사용할 수 있는 아이디입니다.");
vm.isDuplicateChecked = true;
}
})
.catch((error) => {
this.$showAlert(
"에러 발생",
"에러가 발생했습니다. 관리자에게 문의해 주세요."
);
});
},
//사용자 선택 삭제
async deleteSelectedMembers() {
const vm = this;
if (vm.selectedMembers.length === 0) {
vm.$showAlert("사용자 삭제", "선택한 사용자가 없습니다.");
return;
}
if (
!(await vm.$showConfirm(
"사용자삭제",
"선택한 사용자를 삭제하시겠습니까?"
))
) {
return;
}
axios({
url: "/member",
method: "delete",
headers: {
"Content-Type": "application/json",
},
data: vm.selectedMembers,
})
.then(function (response) {
if (response.data.checkMessage.status === 200) {
vm.$showAlert("사용자 삭제", "선택한 사용자가 삭제되었습니다.");
vm.checkAll = false;
vm.selectedMembers = [];
vm.fetchMemberList();
} else {
// vm.$showAlert('사용자 삭제','선택한 사용자 삭제에 실패하였습니다. 다시 시도해주세요.')
vm.$showAlert("사용자 삭제", response.data.checkMessage.message);
}
})
.catch(function (error) {
vm.$showAlert("사용자 삭제", "삭제오류, 관리자에게 문의바랍니다.");
});
},
//사용자 등록 유효성 검사
memberInsertValidation: function () {
const vm = this;
//1.ID null 검사
if (vm.$isEmpty(vm.memberData.userId)) {
vm.$showAlert("사용자 등록", "아이디(ID)를 입력해주세요.");
document.getElementById("userId").focus();
return false;
}
//2. ID 중복 검사
if (!vm.isDuplicateChecked) {
vm.$showAlert("사용자 등록", "아이디 중복확인 후 등록해주세요.");
return false;
}
//3. 이름 null 검사
if (vm.$isEmpty(vm.memberData.userNm)) {
vm.$showAlert("사용자 등록", "이름을 입력해주세요.");
document.getElementById("userNm").focus();
return false;
}
//4. 이름 유효성 검사
let validateName = /^[가-힣A-Za-z\s]+$/;
if (!validateName.test(vm.memberData.userNm)) {
vm.$showAlert(
"사용자 등록",
"이름에 숫자와 특수문자를 입력할 수 없습니다."
);
document.getElementById("userNm").focus();
return false;
}
//5. 비밀번호 null 검사
if (vm.$isEmpty(vm.memberData.userPassword)) {
vm.$showAlert("사용자 등록", "비밀번호를 입력해주세요.");
document.getElementById("userPassword").focus();
return false;
}
//6. 비밀번호 유효성 검사
if (!vm.$pwCheck(vm.memberData.userPassword)) {
vm.$showAlert(
"사용자 등록",
"비밀번호 형식이 올바르지 않습니다. (8~16자의 영문 대문자, 소문자, 숫자, 특수문자 사용가능)"
);
document.getElementById("userPassword").focus();
return false;
}
//7. 비밀번호와 비밀번호 확일 일치여부 검사
if (vm.memberData.userPassword !== vm.passwordConfirm) {
vm.$showAlert(
"사용자 등록",
"비밀번호가 일치하지 않습니다. 다시 입력해주세요."
);
document.getElementById("passwordConfirm").focus();
return false;
}
//8.이메일 null 검사
if (!vm.memberData.userEmail) {
vm.$showAlert("사용자 등록", "이메일을 입력하세요.");
document.getElementById("email").focus();
return false;
}
//9.이메일 유효성 검사
if (!vm.$email(vm.memberData.userEmail)) {
vm.$showAlert("사용자 등록", "이메일 형식이 올바르지 않습니다.");
document.getElementById("email").focus();
return false;
}
//10.이메일 중복검사 여부 확인
if (!vm.emailDuplicateChecked) {
vm.$showAlert("사용자 등록", "이메일 중복확인 후 등록해주세요.");
document.getElementById("email").focus();
return false;
}
//11. 권한 null 검사
if (vm.$isEmpty(vm.memberData.author)) {
vm.$showAlert("사용자 등록", "권한을 선택해주세요.");
document.getElementById("author").focus();
return false;
}
return true;
},
resetData() {
this.memberData = {}; // 데이터를 초기화합니다.
this.dataLoaded = false; // 데이터 로드 상태를 초기화합니다.
this.passwordConfirm = null;
this.changePwConfirm = null;
},
//사용자 선택 삭제용 선택 기능
check: function (member) {
this.selectedMembers.push(member.userId);
},
//사용자 선택 삭제용 전체 선택 기능
memberCheckAll() {
this.checkAll = !this.checkAll;
if (this.checkAll) {
this.memberList.forEach((member) => {
this.selectedMembers.push(member.userId);
});
} else {
this.selectedMembers = [];
}
},
resetForm() {
this.memberData = {
userId: null,
userPassword: null,
userNm: null,
deptNm: null,
userEmail: null,
author: null,
};
this.passwordConfirm = null;
this.changePwConfirm = null;
},
loadHostData(member) {
this.memberData = Object.assign({}, member); // 클릭한 호스트의 데이터를 복사하여 저장합니다.
this.originalmemberData = Object.assign({}, member);
this.changeAuthor();
this.dataLoaded = true; // 데이터가 로드되었음을 표시합니다.
},
//10개보기, 20개보기
changePerPage: function () {
this.search.perPage = this.selectedPerPage;
this.fetchMemberList();
},
closeModal: function () {
this.modalOpen = false;
},
//비밀번호 변경 모달 열기
openModal: function () {
this.modalOpen = true;
this.pwChange = null;
this.pwChangeCheck = null;
},
//비밀번호 변경 유효성 검사
passwordChangeValidation: function () {
const vm = this;
//1.변경 비밀번호의 null검사
if (vm.$isEmpty(vm.pwChange)) {
vm.$showAlert("비밀번호 변경", "변경할 비밀번호를 입력하세요.");
document.getElementById("pwChange").focus();
return false;
}
//2.변경 비밀번호의 형식검사
if (!vm.$pwCheck(vm.pwChange)) {
vm.$showAlert("비밀번호 변경", "비밀번호 형식이 올바르지 않습니다.");
document.getElementById("pwChange").focus();
return false;
}
//3.변경 비밀번호와 비밀번호 확인의 일치여부 확인
if (vm.pwChange !== vm.pwChangeCheck) {
vm.$showAlert("비밀번호 변경", "비밀번호 형식이 올바르지 않습니다.");
document.getElementById("pwChangeCheck").focus();
return false;
}
return true;
},
//유저 비밀번호 변경
passwordChange: function () {
const vm = this;
if (!vm.passwordChangeValidation()) {
return;
}
axios({
url: "/member",
method: "patch",
headers: {
"Content-Type": "application/json",
},
data: {
userId: vm.memberData.userId,
userPassword: vm.pwChange,
},
})
.then(function (response) {
if (response.data.resultData.result) {
vm.$showAlert("비밀번호 변경", "비밀번호 변경에 성공하였습니다.");
vm.modalOpen = false;
} else {
vm.$showAlert(
"비밀번호 변경",
"비밀번호 변경에 실패하였습니다. 다시 시도해주세요."
);
}
})
.catch(function (error) {
vm.$showAlert(
"비밀번호 변경",
"비밀번호 변경에 실패하였습니다. 다시 시도해주세요."
);
});
},
//이메일 중복검사
mailDuplicateCheck: function () {
const vm = this;
if (!vm.mailValidation()) {
return;
}
axios({
url: "/member/email",
method: "post",
headers: {
"Content-Type": "application/json;",
},
data: {
userEmail: vm.memberData.userEmail,
},
})
.then((response) => {
if (response.data.resultData.result) {
vm.$showAlert("이메일 중복확인", "사용중인 이메일입니다.");
vm.emailDuplicateChecked = false;
} else {
vm.$showAlert("이메일 중복확인", "사용할 수 있는 이메일입니다.");
vm.emailDuplicateChecked = true;
}
})
.catch((error) => {
this.$showAlert(
"에러 발생",
"에러가 발생했습니다. 관리자에게 문의해 주세요."
);
});
},
//이메일 유효성 검사
mailValidation: function () {
const vm = this;
//1.null검사
if (!vm.memberData.userEmail) {
vm.$showAlert("사용자 등록", "이메일을 입력하세요.");
document.getElementById("email").focus();
return false;
}
//2.정규식 검사
if (!vm.$email(vm.memberData.userEmail)) {
vm.$showAlert("사용자 등록", "이메일 형식이 올바르지 않습니다.");
document.getElementById("email").focus();
return false;
}
return true;
},
// 권한 변경 시 부서 선택
changeAuthor() {
const vm = this;
this.deptSearch.searchObjectList[0].key = 'role_chk';
if (vm.memberData.author == 'ROLE_ADMIN') {
this.deptSearch.searchObjectList[0].value = 1;
} else {
this.deptSearch.searchObjectList[0].value = 0;
}
axios({
url: "/department/departments",
method: "post",
data: vm.deptSearch,
})
.then(function (response) {
vm.departmentList = response.data.resultData.selectDeptList;
vm.memberData.deptNm = vm.departmentList[0].dept_nm;
vm.memberData.dept_code = vm.departmentList[0].dept_code;
})
.catch(function (error) {
vm.$showAlert(
"부서 조회",
"목록 불러오기 오류, 관리자에게 문의바랍니다."
);
});
}
},
watch: {
//아이디 값 변경 시 중복체크여부 false로 변경
"memberData.userId": function (newVal, oldVal) {
this.isDuplicateChecked = false;
},
//이메일 값 변경 시 중복체크여부 false로 변경
"memberData.userEmail": function (newVal, oldVal) {
this.emailDuplicateChecked = false;
},
},
components: {
PageNavigation: PageNavigation,
PaginationButton: PaginationButton,
SvgIcon: SvgIcon,
},
mounted() {
this.fetchMemberList();
this.deptSearchInit();
this.getAuthorList();
this.searchInit();
this.userId = store.state.loginUser.user_id;
this.authList = store.state.loginUser.user_auth;
this.author = store.state.loginUser.user_auth[0];
this.dept_code = store.state.loginUser.dept_code;
},
};
</script>