
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="col-lg-12">
<div class="card">
<div class="card-body">
<h2 class="card-title">휴가 현황</h2>
<div class="form-group">
<div class="form-conts">
<div class="form-conts datepicker-conts">
<div class="datepicker-input">
<input type="date" class="form-control datepicker cal" v-model="request.bgnde" style="max-width: 200px;" @change="changeDate" />
<mark>~</mark>
<input type="date" class="form-control datepicker cal" v-model="request.endde" style="max-width: 200px;" @change="changeDate" />
</div>
</div>
</div>
</div>
<div class="boxs">
<div class="color-boxs">
<div v-for="(item, idx) of useSummary" :key="idx" :class="getBoxClass(idx)" @click="fnFindUseList(item)">
<h3>{{ item.name }}</h3> {{ item.value }}
</div>
<div v-for="(item, idx) of notUseSummary" :key="idx" :class="getBoxClass(useSummary.length + idx)" @click="fnFindNotUseList(item.code)">
<h3>{{ item.codeNm }}</h3> {{ item.value }}
</div>
</div>
</div>
<div class="tbl-wrap">
<table id="myTable" class="tbl data">
<colgroup>
<col style="width: 15%;">
<col style="width: 40%;">
<col style="width: 30%;">
<col style="width: 15%;">
</colgroup>
<thead>
<tr>
<th>구분</th>
<th>기간</th>
<th>신청일</th>
<th>상태</th>
</tr>
</thead>
<tbody>
<template v-if="formattedListData.length > 0">
<tr v-for="(item, idx) in formattedListData" :key="idx" @click="fnMoveTo('view', item.vcatnId)">
<td :class="getTypeColorClass(item.formattedVcatnKnd)">{{ item.formattedVcatnKnd }}</td>
<td>{{ item.formattedBgnde }} {{ item.formattedBeginHour }}:{{ item.formattedBeginMnt }} ~ {{ item.formattedEndde }} {{ item.formattedEndHour }}:{{ item.formattedEndMnt }}</td>
<td>{{ item.rgsde }}</td>
<td :class="getStatusClass(item.formattedStatus)">{{ item.formattedStatus }}</td>
</tr>
</template>
<tr v-else>
<td colspan="4">해당 기간 내 등록된 휴가가 없습니다.</td>
</tr>
</tbody>
</table>
</div>
<Pagenation :search="request" @onChange="fnChangeCurrentPage" />
</div>
</div>
</div>
</template>
<script>
import { SearchOutlined } from '@ant-design/icons-vue';
import Pagenation from '../../../component/Pagenation.vue';
// API
import { findVcatnsSummary, findMyVcatnsProc } from '../../../../resources/api/vcatn';
export default {
components: {
SearchOutlined,
Pagenation
},
data() {
return {
photoicon: "/client/resources/img/photo_icon.png",
color: ['blue', 'red', 'green', 'purple', 'orange'],
colorMap: [],
useSummary: [], // 연차 소모성 휴가
notUseSummary: [], // 연차 비 소모성 휴가
// 휴가 현황 목록 조회용
listData: [],
request: {
vcatnKnds: null, // 휴가 종류
bgnde: null, // 시작일
endde: null, // 종료일
},
// 공통코드(구분, 상태) 목록 조회용
vcatnKnds: [],
confmTypes: [],
serachRequest: {
searchType: "upperCd",
searchText: null,
},
};
},
computed: {
formattedListData() {
if (!this.listData || !Array.isArray(this.listData)) {
return [];
}
return this.listData.map(item => {
const vcatnKnd = this.vcatnKnds.find(v => v.code === item.vcatnKnd);
const confmAt = this.confmTypes.find(v => v.codeValue === item.confmAt);
return {
...item,
formattedVcatnKnd: vcatnKnd ? vcatnKnd.codeNm : item.vcatnKnd,
formattedBgnde: item.bgnde ? item.bgnde.split(' ')[0] : '',
formattedEndde: item.endde ? item.endde.split(' ')[0] : '',
formattedBeginHour: item.beginHour ? item.beginHour.toString().padStart(2, '0') : '00',
formattedEndHour: item.endHour ? item.endHour.toString().padStart(2, '0') : '00',
formattedBeginMnt: item.beginMnt ? item.beginMnt.toString().padStart(2, '0') : '00',
formattedEndMnt: item.endMnt ? item.endMnt.toString().padStart(2, '0') : '00',
formattedStatus: confmAt ? confmAt.codeNm : item.confmAt,
};
});
}
},
created() {
this.vcatnCodes(); // 휴가 종류 코드 조회
this.confmTypeCodes(); // 상태 코드 조회
},
mounted() {
this.findSummary(); // 현황 조회
this.findList(); // 목록 조회
},
methods: {
// 휴가 종류 코드 조회
async confmTypeCodes() {
this.vcatnKnds = []; // 초기화
this.serachRequest.searchText = "sanctn_mby_vcatn";
const codes = await this.$findCodeList(this.serachRequest);
if (codes && Array.isArray(codes)) {
for (const code of codes) {
this.serachRequest.searchText = code.code;
const result = await this.$findCodeList(this.serachRequest);
if (result && Array.isArray(result)) {
this.vcatnKnds.push(...result);
}
}
}
},
// 상태 코드 조회
async vcatnCodes() {
this.confmTypes = []; // 초기화
this.serachRequest.searchText = "confm_code";
const codes = await this.$findCodeList(this.serachRequest);
if (codes && Array.isArray(codes)) {
this.confmTypes = codes;
}
},
// 현황 조회
async findSummary() {
const vm = this;
try {
const response = await findVcatnsSummary(vm.request);
const result = response.data.data;
this.request.bgnde = new Date(result.data.bgnde).toISOString().split('T')[0];
this.request.endde = new Date(result.data.endde).toISOString().split('T')[0];
if (result.data.yryc < 1) {
this.request.endde = new Date().toISOString().split('T')[0];
}
let yrycCyfdCo = result.data.yrycCyfdCo;
let totalCo = result.data.yrycCo + yrycCyfdCo;
let useCo = result.useSummary.useCo;
let notUseCo = totalCo - useCo;
this.useSummary = []; // 초기화
this.useSummary.push({ key: 'totalCo', name: '전체', value: totalCo + '(' + yrycCyfdCo + ')' });
this.useSummary.push({ key: 'useCo', name: '사용', value: useCo, codeList: result.useSummary.codeList });
this.useSummary.push({ key: 'notUseCo', name: '미사용', value: notUseCo });
this.notUseSummary = []; // 초기화
this.notUseSummary = result.notUseSummary;
this.colorMap = []; // 초기화
const keys = Object.keys(this.notUseSummary);
for (let i = 0; i < Object.keys(this.notUseSummary).length; i++) {
this.colorMap.push({
code: keys[i].code,
class: this.color[this.useSummary.length + i],
})
}
} catch (error) {
if (error.response) {
alert(error.response.data.message);
} else {
alert("에러가 발생했습니다.");
}
console.error(error.message);
};
},
// 현황에 클래스 부여
getBoxClass(idx) {
if (idx === 0) return 'box';
return `box ${this.color[(idx - 1) % this.color.length]}`;
},
// 날짜 선택
changeDate() {
if (!this.request.bgnde || !this.request.endde) {
return;
}
const startDate = new Date(this.request.bgnde);
const endDate = new Date(this.request.endde);
if (endDate < startDate) {
alert('종료일은 시작일보다 이전일 수 없습니다.');
this.request.endde = this.request.bgnde;
return;
}
this.findList(); // 목록 조회
},
// 목록 조회
async findList() {
const vm = this;
try {
delete vm.request.vcatnKndList;
const response = await findMyVcatnsProc(vm.request);
const result = response.data.data;
vm.listData = result.lists;
vm.request = result.search;
} catch (error) {
if (error.response) {
alert(error.response.data.message);
} else {
alert("에러가 발생했습니다.");
}
console.error(error.message);
};
},
// 목록 필터 조회
fnFindUseList(item) {
if (item.key === 'totalCo') {
this.request.vcatnKnds = null;
} else if (item.key === 'useCo') {
this.request.vcatnKnds = item.codeList.map(code => code.code).join(", ");
} else {
return;
}
this.findList(); // 목록 조회
},
fnFindNotUseList(vcatnKnd) {
this.request.vcatnKnds = vcatnKnd;
this.findList(); // 목록 조회
},
// 구분에 클래스 부여
getTypeColorClass(code) {
for (let color of this.colorMap) {
if (color.code === code) {
return 'vcatnKnd ' + color.class;
}
}
return 'vcatnKnd blue';
},
// 상태에 따른 클래스 반환 메소드
getStatusClass(status) {
if (status === '승인') return 'status-approved';
if (status === '대기') return 'status-pending';
return '';
},
// 페이지 이동
fnChangeCurrentPage(currentPage) {
this.request.currentPage = Number(currentPage);
this.$nextTick(() => {
this.findList();
});
},
// 페이지 이동
fnMoveTo(type, id) {
const routes = {
'list': { name: 'hyugaStatue' },
'view': { name: 'HyugaDetail', query: { id } },
'edit': { name: 'hyugaInsert', query: this.$isEmpty(id) ? {} : { id } },
};
if (routes[type]) {
if (!this.$isEmpty(this.pageId) && type === 'list') {
this.$router.push({ name: 'HyugaDetail', query: { id: this.pageId } });
}
this.$router.push(routes[type]);
} else {
alert("올바르지 않은 경로를 요청하여 목록으로 이동합니다.");
this.$router.push(routes['list']);
}
},
},
};
</script>
<style scoped>
tr {
cursor: pointer;
}
.box {
cursor: pointer;
}
.vcatnKnd.red {
color: #E92727 !important;
}
.vcatnKnd.green {
color: #3C97AB !important;
}
.vcatnKnd.blue {
color: #1D75E1 !important;
}
.vcatnKnd.purple {
color: #A36CD4 !important;
}
.vcatnKnd.orange {
color: #F7941C !important;
}
</style>