
File name
Commit message
Commit date
File name
Commit message
Commit date
File name
Commit message
Commit date
File name
Commit message
Commit date
04-04
File name
Commit message
Commit date
File name
Commit message
Commit date
<template>
<div class="content-zone full-page">
<div class="content">
<div class="setting-box h_100">
<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 ref="topBox" class="mb30">
<div class="form-box">
<div class="form-box-title">
<p>부서 정보</p>
<p><span>*</span>필수입력</p>
</div>
<div class="form-content">
<div class="layout">
<label class="form-title">상위부서</label>
<input
type="text"
class="form-control sm"
disabled
v-model="viewDept.upDeptNm"
/>
</div>
<div class="layout">
<label class="form-title"><span>*</span>부서명</label>
<input
type="text"
class="form-control sm"
:disabled="isFormDisabled"
v-model="viewDept.deptNm"
placeholder="부서명을 입력해주세요"
/>
</div>
<div class="grid-column layout">
<label class="form-title"><span>*</span>부서권한</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 layout">
<label class="form-title">부서설명</label>
<textarea
class="form-control sm area"
style="min-height: 3rem"
:disabled="isFormDisabled"
v-model="viewDept.deptExpln"
placeholder="부서에 대한 설명을 입력해주세요"
></textarea>
</div>
</div>
</div>
<div class="btn-wrap">
<button
class="btn sm main"
: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 ref="bottomBox" :style="{ height: bottomBoxHeight }">
<div class="form-box" style="height: calc(100% - 60px);">
<div class="form-box-title">
<p>부서 사용자</p>
</div>
<div class="form-content" style="display: block;overflow-y: auto;">
<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 main"
: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="btn-close" @click="modalClose"></button>
</template>
<div class="tbl-wrap">
<ListTable
:className="'data cursor'"
:colgroup="mbrColgroup"
:thead="mbrThead"
:tbody="mbrTbody"
@listClick="selectMbr"
>
</ListTable>
</div>
</Modal>
</template>
<script>
import draggable from "vuedraggable";
import Hierachy from "../../../component/hierachy/HierachyDraggable.vue";
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";
import pageAuthMixin from "../../../common/pageAuthMixin.js";
export default {
components: {
draggable: draggable,
Hierachy: Hierachy,
ListTable: ListTable,
PaginationButton: PaginationButton,
Modal: Modal,
},
mixins: [pageAuthMixin],
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: 'ico_team',
userListModal: false,
deptList: [], // 부서 목록
authList: [], // 권한목록
deptMbr: [], // 부서에 등록된 사용자 목록
mbrList: [], // 부서에 등록되지 않은 사용자 목록 [ 부서 사용자 등록을 위한 사용자 목록 ]
selectedMbr: [], // 부서에 등록된 사용자 중 지정된 사용자 [삭제용도]
selectedDeptId: null, // 선택된 부서
selectedAuthrt: "", // 부서 권한
newDept: {}, // 신규 부서 등록
viewDept: {}, // 사용자에게 보여질 부서정보
searchText: "", // 사용자 정보 검색
submitStts: true,
topBoxHeight: 0,
};
},
created() {
this.findAll();
},
methods: {
// 목록 조회
async findAll() {
try {
const res = await findAll();
if (res.status == 200) {
this.deptList = res.data.data.hierachyList; // 부서 목록
if(this.deptList.length > 0 && this.selectedDeptId == null) {
this.fnViewDetail(this.deptList[0].id); // 부서 최상단 조회
}
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.mblTelnoSplit(res.data.data.deptMbr);
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.validation() == false) {
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);
}
},
// 유효성 검사
validation() {
if (!this.viewDept.deptNm || this.viewDept.deptNm.trim() === "") {
alert("부서명을 입력해주세요.");
return false;
}
// 부서권한 검사
if (!this.selectedAuthrt) {
alert("부서 권한을 지정해주세요.");
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() {
if (this.selectedDeptId != null) {
if (!confirm("작성 중인 부서정보는 저장되지 않습니다.\n계속 하시겠습니까?")) {
return;
}
}
this.fnReset(); // 초기화
this.submitStts = true;
},
// 하위 신규 객체 생성
subAdd() {
if (
// Object.keys(this.viewDept).length === 0 ||
this.selectedDeptId == null
) {
alert("상위 부서를 지정해주세요.");
return;
} else {
if (!confirm("작성 중인 부서정보는 저장되지 않습니다.\n계속 하시겠습니까?")) {
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.mblTelnoSplit(res.data.data.mbrList);
this.mblTelnoSplit(res.data.data.deptMbr);
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 {
if (!confirm("부서 목록을 저장하시겠습니까?\n 작성 중인 부서정보는 저장되지 않습니다.")) {
return;
}
const res = await updateListProc(this.deptList);
alert(res.data.message);
if (res.status == 200) {
this.findAll();
this.findByDept();
}
} catch (error) {
alert(error.res.data.message);
}
},
updateHeight() {
if (this.$refs.topBox) {
this.topBoxHeight = this.$refs.topBox.offsetHeight;
}
},
// 휴대폰번호 표기 변환
mblTelnoSplit(data) {
for (const item of data) {
const mblTelno = item["mblTelno"];
const start = mblTelno.substring(0, 3);
const middle = mblTelno.substring(3, mblTelno.length - 4);
const end = mblTelno.substring(mblTelno.length - 4, mblTelno.length);
item["mblTelno"] = start + "-" + middle + "-" + end;
}
},
},
watch: {
topBoxHeight() {
this.updateHeight(); // 높이 변경될 때 업데이트
},
},
computed: {
isFormDisabled() {
if (!this.viewDept) return true;
return Object.keys(this.viewDept).length === 0;
},
bottomBoxHeight() {
return `calc(100% - ${this.topBoxHeight}px - 30px)`;
},
},
mounted() {
this.updateHeight();
window.addEventListener("resize", this.updateHeight);
},
beforeUnmount() {
window.removeEventListener("resize", this.updateHeight);
},
};
</script>
<style scoped>
.ghost {
height: 15px;
color: transparent;
border: 1px dashed var(--blue);
}
.ghost * {
display: none;
}
</style>