
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="card">
<div class="card-body">
<h2 class="card-title">부서 관리</h2>
<!-- Multi Columns Form -->
<div class="flex align-top">
<div class="sch-form-wrap search ">
<div v-for="(menu, index) in menus" :key="index" class="sidemenu">
<details class="menu-box" open>
<summary class="topmenu">
<img :src="arrow" alt="" class="arrow">
<img :src="topmenuicon" alt="">
<p>{{ menu.title }} </p>
<button @click="addSubMenu(index)" class="btn sm xsm secondary">sub +</button>
</summary>
<ul>
<li class="submenu" v-for="(submenu, subIndex) in menu.submenus" :key="subIndex">
<router-link :to="submenu.link" exact-active-class="active-link" v-slot="{ isExactActive }">
<img :src="menuicon" alt="">
<p>{{ submenu.label }}</p>
</router-link>
</li>
</ul>
</details>
</div>
<div class="buttons">
<button @click="addTopMenu"><img :src="addtopmenu" alt=""></button>
</div>
</div>
<div style="width: 100%;">
<div class=" sch-form-wrap title-wrap">
<h3><img :src="h3icon" alt="">부서 정보</h3>
<div class="buttons" style="margin: 0;">
<button type="submit" class="btn sm sm tertiary">초기화</button>
<button type="reset" class="btn sm sm secondary">등록</button>
<button type="delete" class="btn sm sm btn-red">삭제</button>
</div>
</div>
<form class="row g-3 pt-3 needs-validation detail" @submit.prevent="handleSubmit"
style="margin-bottom: 3rem;">
<div class="col-12">
<label for="purpose" class="form-label">상위부서</label>
<input type="text" class="form-control" id="purpose" v-model="purpose" readonly />
</div>
<div class="col-12">
<label for="purpose" class="form-label">
<p>부서명
<p class="require"><img :src="require" alt=""></p>
</p>
</label>
<input type="text" class="form-control" id="purpose" v-model="purpose" />
</div>
<div class="col-12 chuljang border-x">
<label for="prvonsh" class="form-label">부서설명</label>
<input type="text" class="form-control textarea" id="reason" v-model="reason" />
</div>
</form>
<div class=" sch-form-wrap title-wrap">
<h3><img :src="h3icon" alt="">부서 사용자</h3>
<div class="buttons" style="margin: 0;">
<button type="reset" class="btn sm sm secondary" @click="showPopup = true">사용자 추가</button>
<button type="delete" class="btn sm sm btn-red" @click="removeMember(index)">사용자 삭제</button>
</div>
<HrPopup v-if="showPopup" @close="showPopup = false" @select="addMember"/>
</div>
<div class="tbl-wrap chk-area">
<table id="myTable" class="tbl data">
<thead>
<tr>
<th>선택</th>
<th>직급</th>
<th>이름</th>
<th>부서장</th>
</tr>
</thead>
<!-- 동적으로 <td> 생성 -->
<tbody>
<tr v-for="(member, index) in members" :key="index">
<td>
<div class="form-check">
<input type="checkbox" :id="`chk_${index}`" :value="member.name" v-model="member.checked" />
<label :for="`chk_${index}`"></label>
</div>
</td>
<td>{{ member.position }}</td>
<td>{{ member.name }}</td>
<td>
<div class="form-check">
<input type="radio" name="manager" :id="`rdo_${index}`" :value="member.name"
v-model="selectedManager" />
<label :for="`rdo_${index}`"></label>
</div>
</td>
</tr>
</tbody>
</table>
</div>
<div class="pagination">
<ul>
<!-- 왼쪽 화살표 (이전 페이지) -->
<li class="arrow" :class="{ disabled: currentPage === 1 }" @click="changePage(currentPage - 1)">
<
</li>
<!-- 페이지 번호 -->
<li v-for="page in totalPages" :key="page" :class="{ active: currentPage === page }"
@click="changePage(page)">
{{ page }}
</li>
<!-- 오른쪽 화살표 (다음 페이지) -->
<li class="arrow" :class="{ disabled: currentPage === totalPages }" @click="changePage(currentPage + 1)">
>
</li>
</ul>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import { ref } from 'vue';
import { PlusCircleFilled, CloseOutlined, DownOutlined } from '@ant-design/icons-vue';
import HrPopup from '../../../component/Popup/HrPopup.vue';
const isOpen = ref(false)
export default {
data() {
const today = new Date().toISOString().split('T')[0];
return {
selectedManager: '',
showPopup: false,
menus: [
{
title: '부서1',
submenus: [
{
label: '직원검색',
link: { name: 'hrSearch' },
},
],
},
],
currentPage: 1,
totalPages: 3,
members: [] ,
selectedManager: null,
h3icon: "/client/resources/img/h3icon.png",
require: "/client/resources/img/require.png",
menuicon: "/client/resources/img/arrow-rg.png",
topmenuicon: "/client/resources/img/topmenu.png",
arrow: "/client/resources/img/arrow.png",
addtopmenu: "/client/resources/img/addtopmenu.png",
addsubmenu: "/client/resources/img/addsubmenu.png",
fileName: '',
startDate: today,
startTime: '09:00',
endDate: today,
endTime: '18:00',
where: '',
purpose: '',
approvals: [
{
category: '결재',
name: '',
},
],
receipts: [
{
type: '개인결제',
category: '결재',
category1: '구분',
},
],
};
},
components: {
PlusCircleFilled, CloseOutlined, DownOutlined, HrPopup
},
computed: {
loginUser() {
const authStore = useAuthStore();
return authStore.getLoginUser;
},
},
methods: {
addMember(selectedUser) {
this.members.push({
position: selectedUser.position,
name: selectedUser.name, // or other fields if needed
});
this.showPopup = false; // 팝업 닫기
},
removeMember() {
this.members = this.members.filter(member => !member.checked);
},
addTopMenu() {
const newIndex = this.menus.length + 1;
this.menus.push({
title: `부서${newIndex}`,
submenus: [],
});
},
addSubMenu(menuIndex) {
this.menus[menuIndex].submenus.push({
label: `신규메뉴${this.menus[menuIndex].submenus.length + 1}`,
link: { name: 'hrSearch' },
});
},
goToPage(type) {
if (type === '회의록 등록') {
this.$router.push({ name: 'meetingInsert' });
} else if (type === '출장') {
this.$router.push({ name: 'ChuljangDetail' });
}
},
handleFileUpload(event) {
const file = event.target.files[0];
if (file) {
this.fileName = file.name;
}
},
addApproval() {
this.approvals.push({
category: '결재',
name: '',
});
},
addReceipt() {
this.receipts.push({
type: '개인결제',
category: '결재',
category1: '',
name: '',
file: null,
});
},
// 승인자 삭제
removeApproval(index) {
this.approvals.splice(index, 1);
},
removeReceipt(index) {
this.receipts.splice(index, 1);
},
validateForm() {
// 필수 입력 필드 체크
if (
this.startDate &&
this.startTime &&
this.endDate &&
this.endTime &&
this.where &&
this.purpose.trim() !== ""
) {
this.isFormValid = true;
} else {
this.isFormValid = false;
}
},
calculateDayCount() {
const start = new Date(`${this.startDate}T${this.startTime}:00`);
const end = new Date(`${this.endDate}T${this.endTime}:00`);
let totalHours = (end - start) / (1000 * 60 * 60); // 밀리초를 시간 단위로 변환
if (this.startDate !== this.endDate) {
// 시작일과 종료일이 다른경우
const startDateObj = new Date(this.startDate);
const endDateObj = new Date(this.endDate);
const daysDifference = (endDateObj - startDateObj) / (1000 * 60 * 60 * 24); // 두 날짜 사이의 차이를 일수로 계산
if (this.startTime !== "09:00" || this.endTime !== "18:00") {
this.dayCount = daysDifference + 0.5; // 시간 조건이 기준에서 벗어날 경우
} else {
this.dayCount = Math.ceil(daysDifference + 1); // 시간 조건이 기준에 맞을 경우
}
} else {
// 시작일과 종료일이 같은 경우
if (this.startTime !== "09:00" || this.endTime !== "18:00") {
this.dayCount = 0.5; // 시작 시간 또는 종료 시간이 기준과 다를 경우 0.5
} else {
this.dayCount = 1; // 기준 시간(09:00~18:00)이 맞으면 1일로 간주
}
}
this.validateForm(); // dayCount 변경 후 폼 재검증
},
handleSubmit() {
this.validateForm(); // 제출 시 유효성 확인
if (this.isFormValid) {
localStorage.setItem('ChuljangFormData', JSON.stringify(this.$data));
alert("승인 요청이 완료되었습니다.");
// 추가 처리 로직 (API 요청 등)
} else {
alert("모든 필드를 올바르게 작성해주세요.");
}
},
loadFormData() {
const savedData = localStorage.getItem('ChuljangFormData');
if (savedData) {
this.$data = JSON.parse(savedData);
}
},
},
mounted() {
// Load the saved form data when the page is loaded
this.loadFormData();
},
watch: {
startDate: 'calculateDayCount',
startTime: 'calculateDayCount',
endDate: 'calculateDayCount',
endTime: 'calculateDayCount',
where: 'validateForm',
purpose: "validateForm",
},
};
</script>
<style scoped>
/* 필요한 스타일 추가 */
</style>