
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
File name
Commit message
Commit date
<template>
<div class="content-zone full-page">
<div class="content">
<div class="title-zone">
<div class="page-title">
<p>부서관리</p>
</div>
</div>
<div class="setting-box">
<div class="node-zone">
<div class="tree">
<div>
<draggable
tag="ul"
class="tree-node"
:list="deptList"
:group="{ name: 'menu' }"
item-key="id"
handle=".handle"
ghost-class="ghost"
>
<template #item="{ element }">
<Hierachy
:tasks="element"
:icon="iconPath"
:selectedNode="selectedDeptId"
@changeSelected="fnViewDetail"
/>
</template>
</draggable>
</div>
</div>
<div class="btn-zone">
<template v-if="pageAuth.mdfcnAuthrt == 'Y'">
<button class="btn top sm secondary" @click="topAdd">TOP+</button>
<button class="btn top sm secondary" @click="subAdd">SUB+</button>
<button class="btn save sm" @click="fnListUpdate">메뉴 저장</button>
</template>
</div>
</div>
<div class="setting-zone">
<div>
<div class="form-box">
<div class="form-box-title">
<p>부서 정보</p>
</div>
<div class="form-content">
<div>
<label class="form-title">상위부서</label>
<input
type="text"
class="form-control sm"
disabled
v-model="viewDept.upDeptNm"
/>
</div>
<div>
<label class="form-title">부서명</label>
<input
type="text"
class="form-control sm"
:disabled="isFormDisabled"
v-model="viewDept.deptNm"
/>
</div>
<div class="grid-column">
<label class="form-title">부서권한</label>
<select
class="form-select sm"
:disabled="isFormDisabled"
v-model="selectedAuthrt"
>
<option value="">선택</option>
<option
v-for="(item, idx) in authList"
:key="idx"
:value="item.authrtCd"
>
{{ item.authrtNm }}
</option>
</select>
</div>
<div class="grid-column">
<label class="form-title">부서설명</label>
<textarea
class="form-control lg area"
style="min-height: 3rem"
:disabled="isFormDisabled"
v-model="viewDept.deptExpln"
></textarea>
</div>
</div>
</div>
<div class="btn-wrap">
<button
class="btn sm primary"
:disabled="isFormDisabled"
@click="fnSave"
>
<span v-if="submitStts"> 등록 </span>
<span v-else>수정</span>
</button>
<button
class="btn sm red"
:disabled="isFormDisabled"
@click="fnDel"
>
삭제
</button>
</div>
</div>
<div>
<div class="form-box">
<div class="form-box-title">
<p>부서 사용자</p>
</div>
<div class="form-content">
<div class="tbl-wrap">
<ListTable
:className="'data'"
:colgroup="colgroup"
:thead="thead"
:tbody="tbody"
@listClick="clickEvent"
>
<template v-slot:checkbox="{ row, idx }">
<div class="form-check">
<input
type="checkbox"
:id="'check_' + idx"
class="checkbox md"
:checked="selectedMbr.includes(row.loginId)"
@change="() => checkboxChange(row, idx)"
/>
<label for="'check_' + idx"></label>
</div>
</template>
</ListTable>
</div>
</div>
</div>
<div class="btn-wrap">
<button
class="btn sm primary"
:disabled="isFormDisabled"
@click="modalOpen"
v-if="pageAuth.regAuthrt == 'Y'"
>
사용자 추가
</button>
<button
class="btn sm red"
:disabled="isFormDisabled"
@click="deptMbrDel"
v-if="pageAuth.delAuthrt == 'Y'"
>
선택 사용자 삭제
</button>
</div>
</div>
</div>
</div>
</div>
</div>
<Modal :showModal="userListModal">
<template v-slot:header>
<div class="modal-title">
<p>사용자 목록</p>
</div>
<button class="close-btn" @click="modalClose">X</button>
</template>
<ListTable
:className="'admin-list'"
:colgroup="mbrColgroup"
:thead="mbrThead"
:tbody="mbrTbody"
@listClick="selectMbr"
>
</ListTable>
</Modal>
</template>
<script>
import draggable from "vuedraggable";
import Hierachy from "../../../component/hierachy/HierachyDraggable.vue";
import { mdiAccountCheck, mdiAccountGroup } from "@mdi/js";
import ListTable from "../../../component/table/ListTable.vue";
import PaginationButton from "../../../component/pagination/PaginationButton.vue";
import {
findAll,
save,
findByDept,
update,
del,
deptMbrDelete,
findByMbr,
deptMbrSaveProc,
updateListProc,
} from "../../../../resources/api/dept";
import Modal from "../../../component/modal/Modal.vue";
export default {
components: {
draggable: draggable,
Hierachy: Hierachy,
ListTable: ListTable,
PaginationButton: PaginationButton,
Modal: Modal,
},
data() {
return {
// 페이지 권한 객체
pageAuth: JSON.parse(localStorage.getItem("vuex")).pageAuth,
colgroup: ["5%", "15%", "20%", "20%", "20%"], // 부서관련 등록된 사용자 테이블 생성
thead: ["선택", "아이디", "이름", "연락처", "이메일"], // 부서관련 등록된 사용자 테이블 생성
tbody: [],
mbrColgroup: ["20%", "20%", "20%", "20%"], // 부서관련 등록할 사용자 테이블 생성
mbrThead: ["아이디", "이름", "연락처", "이메일"], // 부서관련 등록할 사용자 테이블 생성
mbrTbody: [],
iconPath: mdiAccountGroup,
userListModal: false,
deptList: [], // 부서 목록
authList: [], // 권한목록
deptMbr: [], // 부서에 등록된 사용자 목록
mbrList: [], // 부서에 등록되지 않은 사용자 목록 [ 부서 사용자 등록을 위한 사용자 목록 ]
selectedMbr: [], // 부서에 등록된 사용자 중 지정된 사용자 [삭제용도]
selectedDeptId: null, // 선택된 부서
selectedAuthrt: "", // 부서 권한
newDept: {}, // 신규 부서 등록
viewDept: {}, // 사용자에게 보여질 부서정보
searchText: "", // 사용자 정보 검색
submitStts: true,
};
},
created() {
this.findAll();
},
methods: {
// 목록 조회
async findAll() {
try {
const res = await findAll();
if (res.status == 200) {
this.deptList = res.data.data.hierachyList; // 부서 목록
this.authList = res.data.data.authList; // 권한 목록
this.newDept = res.data.data.newDept; // 부서 빈 객체
this.newDept.useYn = "Y";
}
} catch (error) {
alert(error.response.data.message);
}
},
// 상세 조회
async findByDept() {
if (this.selectedDeptId == null) return;
try {
const params = { deptId: this.selectedDeptId };
const res = await findByDept(params);
if (res.status == 200) {
this.fnReset(); // 초기화
this.viewDept = res.data.data.dept; // 부서 정보
this.deptMbr = res.data.data.deptMbr; // 부서에 등록된 사용자 목록
this.selectedDeptId = this.viewDept.deptId;
if (this.viewDept.authrtList.length > 0) {
this.selectedAuthrt = this.viewDept.authrtList[0].authrtCd; // 부서 권한
}
this.makeTbody();
this.submitStts = false;
}
} catch (error) {
alert(error.response.data.message);
}
},
// 부서 선택
fnViewDetail(deptId) {
this.selectedDeptId = deptId;
this.findByDept();
},
// 저장
async fnSave() {
// 부서 권한 설정
if (!this.fnDeptAuthrt()) {
alert("부서 권한을 지정해주세요.");
return false;
}
// 신규 등록 및 수정 설정
const action = this.selectedDeptId ? update : save;
try {
const res = await action(this.viewDept);
alert(res.data.message);
if (res.status == 200) {
this.findAll();
this.selectedDeptId = res.data.data.deptId;
}
} catch (error) {
alert(error.response.data.message);
}
},
// 부서권한 설정
fnDeptAuthrt() {
if (
this.selectedAuthrt == null ||
this.selectedAuthrt == "" ||
this.selectedAuthrt == undefined
) {
return false;
}
let authrtList = [];
const params = { authrtCd: this.selectedAuthrt };
authrtList.push(params);
this.viewDept.authrtList = authrtList;
return true;
},
// 삭제
async fnDel() {
if (Object.keys(this.viewDept).length === 0) {
alert("삭제 대상을 지정해주세요.");
return false;
}
if (
!confirm(
"부서정보를 삭제하시겠습니까?\n삭제 시 하위부서 및 부서사용자 항목도 제거됩니다."
)
)
return;
try {
const res = await del(this.viewDept);
alert(res.data.message);
if (res.status == 200) {
this.fnReset(); // 초기화
this.viewDept = {};
this.findAll(); // 목록 재조회
}
} catch (error) {
alert(error.response.data.message);
}
},
// 최상위 신규 객체 생성
topAdd() {
this.fnReset(); // 초기화
this.submitStts = true;
},
// 하위 신규 객체 생성
subAdd() {
if (
Object.keys(this.viewDept).length === 0 ||
this.selectedDeptId == null
) {
alert("상위 부서를 지정해주세요.");
return;
}
const upDeptId = this.viewDept.deptId; // 상위 부서 아이디
const upDeptNm = this.viewDept.deptNm; // 상위 부서명
this.fnReset(); // 초기화
this.viewDept.upDeptId = upDeptId;
this.viewDept.upDeptNm = upDeptNm;
this.submitStts = true;
},
// 초기화
fnReset() {
this.viewDept = JSON.parse(JSON.stringify(this.newDept)); // 신규 객체 생성
this.selectedDeptId = null; // 선택된 부서 객체 아이디 초기화
this.selectedAuthrt = "";
this.mbrList = []; // 부서에 등록되지 않은 사용자 정보 초기화
this.deptMbr = []; // 부서에 등록된 사용자 정보 초기화
this.makeTbody();
this.makeMbrTobdy();
},
// 삭제할 사용자 정보 체크
checkboxChange(row, idx) {
const selectIdx = this.selectedMbr.indexOf(row.loginId);
if (selectIdx === -1) {
this.selectedMbr.push(row.loginId);
} else {
this.selectedMbr.splice(selectIdx, 1);
}
},
// 선택 사용자 해당 부서에서 삭제
async deptMbrDel() {
if (this.selectedMbr.length <= 0) {
alert("삭제할 사용자를 지정해주세요.");
return;
}
if (!confirm("선택한 사용자를 부서에서 제거하시겠습니까?")) return;
// 회원 아이디 추출
const delMbr = this.deptMbr.filter((mbr) =>
this.selectedMbr.includes(mbr.lgnId)
);
try {
const res = await deptMbrDelete(delMbr);
alert(res.data.message);
if (res.status == 200) {
this.findByDept();
}
} catch (error) {
alert(error.response.data.message);
}
},
// 사용자 정보 검색
async fnFindByMbr() {
try {
const params = {
deptId: this.selectedDeptId,
searchText: this.searchText,
};
const res = await findByMbr(params);
// alert(res.data.message);
if (res.status == 200) {
this.mbrList = res.data.data.mbrList; // 부서에 등록되지 않은 사용자 목록
this.deptMbr = res.data.data.deptMbr; // 부서에 등록된 사용자 목록
this.makeTbody();
this.makeMbrTobdy();
}
} catch (error) {
alert(error.response.data.message);
}
},
// 사용자 부서 등록
async selectMbr(idx) {
if (!confirm("해당 사용자를 등록하시겠습니까?")) return false;
try {
const params = {
deptId: this.selectedDeptId,
mbrId: this.mbrList[idx].mbrId,
};
const res = await deptMbrSaveProc(params);
alert(res.data.message);
if (res.status == 200) {
this.fnFindByMbr();
}
} catch (error) {}
},
// tbody 생성
makeTbody() {
this.tbody = [];
this.tbody = this.deptMbr.map((mbr) => ({
loginId: mbr.lgnId, // 로그인 아이디
mbrNm: mbr.mbrNm, // 이름
mblTelno: mbr.mblTelno, // 연락처
eml: mbr.eml, // 이메일
}));
},
// 사용자 목록 tbody 생성
makeMbrTobdy() {
this.mbrTbody = [];
this.mbrTbody = this.mbrList.map((mbr) => ({
loginId: mbr.lgnId, // 로그인 아이디
mbrNm: mbr.mbrNm, // 이름
mblTelno: mbr.mblTelno, // 연락처
eml: mbr.eml, // 이메일
}));
},
// 사용자추가 버튼 클릭
modalOpen() {
// 사용자 검색
if (
this.selectedDeptId == null ||
this.selectedDeptId == undefined ||
this.selectedDeptId == ""
) {
alert("부서등록 후 사용자 등록이 가능합니다.");
return;
} else {
this.fnFindByMbr();
this.userListModal = true;
}
},
modalClose() {
this.userListModal = false;
},
clickEvent() {},
// 드래그앤드롭
// axios: 목록 수정
async fnListUpdate() {
try {
const res = await updateListProc(this.deptList);
alert(res.data.message);
if (res.status == 200) {
this.findAll();
}
} catch (error) {
alert(error.res.data.message);
}
},
},
watch: {},
computed: {
isFormDisabled() {
if (!this.viewDept) return true;
return Object.keys(this.viewDept).length === 0;
},
},
mounted() {},
};
</script>
<style scoped>
.ghost {
height: 15px;
color: transparent;
border: 1px dashed var(--blue);
}
.ghost * {
display: none;
}
</style>