
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>
<div class="flex align-top">
<div class="sch-form-wrap search">
<div class="input-group" style="display: flex;">
<select v-model="searchReqDTO.searchType" id="searchType" class="form-select">
<option value="all">전체</option>
<option value="cm">카드명</option>
<option value="nm">신청자</option>
</select>
<div class="sch-input">
<input type="text" class="form-control" v-model="searchReqDTO.searchText" @keyup.enter="searchCards">
<button class="ico-sch" @click="searchCards">
<SearchOutlined />
</button>
</div>
</div>
<div class="tbl-wrap table-scroll">
<table id="myTable" class="tbl data">
<!-- 동적으로 <th> 생성 -->
<thead>
<tr>
<th>카드목록 </th>
</tr>
</thead>
<!-- 동적으로 <td> 생성 -->
<tbody>
<tr v-if="selectedCards.length === 0">
<td style="text-align: center;">등록된 카드정보가 없습니다.</td>
</tr>
<tr v-for="(item, index) in selectedCards" :key="index" @click="selectCard(item)">
<td>
{{ item.cardNm }}
</td>
</tr>
</tbody>
</table>
</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" @click="resetCard">신규</button>
<button type="reset" class="btn sm sm secondary" @click="insertByUpdateCard">
{{ buttonText }}
</button>
<button type="delete" class="btn sm sm btn-red" @click="deleteByUseAtCard">삭제</button>
</div>
</div>
<form class="row g-3 pt-3 needs-validation " @submit.prevent="handleSubmit" style="margin-bottom: 3rem;">
<div class="col-12 ">
<label for="cardNm" class="form-label">
<p>카드명
<p class="require"><img :src="require" alt=""></p>
</p>
</label>
<input type="text" class="form-control " id="reason" v-model="selectedCard.cardNm" />
</div>
<div class="col-12 ">
<label for="chargerId" class="form-label">
<p>담당자
<p class="require"><img :src="require" alt=""></p>
</p>
</label>
<input type="text" class="form-control " id="reason" v-model="selectedCard.chargerId" readonly />
<input type="button" class="form-control " value="검색" @click="showPopup = true" />
<!-- 팝업 -->
<HrPopup v-if="showPopup" @close="showPopup = false" @select="addApproval" />
</div>
<div class="col-12 chuljang ">
<label for="prvonsh" class="form-label">비고</label>
<input type="text" class="form-control textarea" id="reason" v-model="selectedCard.rm" />
</div>
<div class="col-12 border-x input-radio">
<label for="prvonsh" class="form-label">
<p>상태
<p class="require"><img :src="require" alt=""></p>
</p>
</label>
<select class="form-select" id="sttus" v-model="selectedCard.sttus">
<option value="N">정상</option>
<option value="R">재발급</option>
<option value="D">폐기</option>
</select>
</div>
</form>
<div class=" sch-form-wrap title-wrap">
<h3><img :src="h3icon" alt="">예약현황</h3>
</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="(item, index) in processedCards" :key="index">
<td>{{ item.deptId }}</td>
<td>{{ item.applcntId }}</td>
<td>{{ item.formattedPeriod }}</td>
<td :class="getStatusClass(item.status)">
{{ item.status }}
</td>
</tr>
</tbody>
</table>
</div>
<Pagenation :search="searchReqHisDTO" @onChange="fnChangeCurrentPage" />
</div>
</div>
</div>
</div>
</template>
<script>
import GoogleCalendar from "../../../component/GoogleCalendar.vue"
import HrPopup from "../../../component/Popup/HrPopup.vue";
import { SearchOutlined, CloseCircleFilled } from '@ant-design/icons-vue';
import { saveAsSetCard, findAllAsSetCard, updateAsSetCard, findAllAsSetCardHis } from "../../../../resources/api/asset"; //카드 정보 API
import Pagenation from "../../../component/Pagenation.vue";
export default {
data() {
return {
showPopup: false,
approvals: [],
require: "/client/resources/img/require.png",
h3icon: "/client/resources/img/h3icon.png",
photoicon: "/client/resources/img/photo_icon.png",
img1: "/client/resources/img/img.png",
icon1: "/client/resources/img/icon.png",
dateicon: "/client/resources/img/date.png",
startbtn: "/client/resources/img/start.png",
stopbtn: "/client/resources/img/stop.png",
moreicon: "/client/resources/img/more.png",
checkCard: false,
cardId: null,
selectedCards: [],
selectedCardsHis: [],
searchReqDTO: {
searchType: "all",
searchText: null,
useAt: null,
useAll: true,
},
searchReqHisDTO: {
searchType: "all",
searchText: null,
useAt: null,
useAll: false,
listType:"all",
currentPage: null,
recordSize: 4,
pageSize: null,
totalRecordCount: null,
totalPageCount: null,
startPage: null,
endPage: null,
limitStart: null,
existPrevPage: null,
existNextPage: null,
},
selectedCard: {
cardNm: null,
chargerId: null,
rm: null,
sttus: "N",
useAt: "Y"
},
}
},
components: {
SearchOutlined, CloseCircleFilled, HrPopup, Pagenation
},
methods: {
// 페이지 이동
fnChangeCurrentPage(currentPage) {
this.searchReqHisDTO.currentPage = Number(currentPage);
console.log(this.searchReqHisDTO);
this.$nextTick(() => {
this.searchCardsHis();
});
},
//카드 정보 전체 조회
async searchCards() {
try {
const response = await findAllAsSetCard(this.searchReqDTO);
if (response.status === 200) {
this.selectedCards = response.data.data.card; // API 응답에서 카테고리 목록을 가져옴
}
} catch (error) {
console.error("검색 중 오류 발생:", error);
}
},
//카드 정보 사용 현황 전체 조회
async searchCardsHis() {
try {
const response = await findAllAsSetCardHis(this.searchReqHisDTO);
if (response.status === 200) {
this.selectedCardsHis = response.data.data.cardHis; // API 응답에서 카테고리 목록을 가져옴
this.searchReqHisDTO = response.data.data.search;
}
} catch (error) {
console.error("검색 중 오류 발생:", error);
}
},
// 카드 정보 등록 수정
async insertByUpdateCard() {
if (!this.validateCheck()) {
return; // 유효성 검사 실패 시 함수 종료
}
if (this.cardId == null && this.cardId == "") {
try {
const response = await saveAsSetCard(this.selectedCard);
if (response.status === 200) { // 성공 여부 체크
alert("등록되었습니다.");
window.location.reload();
}
} catch (error) {
// HTTP 오류가 발생한 경우
const errorMessage = error.response?.data?.message || "등록이 실패하였습니다.";
alert(errorMessage); // 오류 메시지 표시
this.searchCards();
}
} else {
try {
const response = await updateAsSetCard(this.cardId, this.selectedCard);
if (response.status === 200) {
alert("수정되었습니다.");
window.location.reload();
}
} catch (error) {// HTTP 오류가 발생한 경우
const errorMessage = error.response?.data?.message || "수정이 실패하였습니다.";
alert(errorMessage); // 오류 메시지 표시
this.searchCards();
}
}
},
// 등록 유효성 체크 함수
validateCheck() {
// 1. 카드명 (cardNm) 필수 체크
if (!this.selectedCard.cardNm || this.selectedCard.cardNm.trim() === "") {
alert("카드명은 필수 입력 항목입니다.");
return false;
}
// 2. 담당자 (chargerId) 필수 체크
if (!this.selectedCard.chargerId || this.selectedCard.chargerId.trim() === "") {
alert("담당자는 필수 입력 항목입니다.");
return false;
}
return true; // 모든 유효성 검사 통과
},
// 삭제 버튼을 눌렀을 시 삭제
async deleteByUseAtCard() {
try {
this.selectedCard.useAt = "N";
const response = await updateAsSetCard(this.cardId, this.selectedCard);
if (response.status === 200) {
alert("삭제되었습니다.");
window.location.reload();
}
} catch (error) {
alert("삭제가 실패하였습니다.");
}
},
//선택한 카드의 정보를 오른쪽에 표시
selectCard(item) {
this.checkCard = true;
this.cardId = item.cardId;
this.selectedCard = {
cardNm: item.cardNm,
chargerId: item.chargerId,
rm: item.rm,
sttus: item.sttus,
useAt: item.useAt
};
},
// 신규 버튼을 눌렀을 시
resetCard() {
this.checkCard = false;
this.selectedCard = {
cardNm: null,
chargerId: null,
rm: null,
sttus: "N",
useAt: "Y"
};
},
addApproval(selectedUser) {
this.approvals.push({
name: selectedUser.name
});
this.selectedCard.chargerId = selectedUser.name; // 입력창에 표시
this.showPopup = false;
},
getStatusClass(status) {
if (status === '예약') return 'status-pending';
if (status === '사용 중') return 'status-pending';
if (status === '반납') return 'status-approved';
return ''; // 기본값
},
},
watch: {
},
computed: {
buttonText() {
return this.checkCard ? "수정" : "등록";
},
// selectedCardsHis 데이터를 가공하여 화면에 표시할 데이터를 만듭니다.
processedCards() {
const now = new Date(); // 현재 시간
// 날짜와 시간 문자열을 조합하여 Date 객체를 생성하는 헬퍼 함수
const createDateTime = (dateStr, hourStr, minStr) => {
// dateStr이 "YYYY-MM-DD HH:MM:SS.ms" 형태라고 가정하고 "YYYY-MM-DD" 부분만 추출
const datePart = dateStr.split(' ')[0];
const year = parseInt(datePart.substring(0, 4), 10);
const month = parseInt(datePart.substring(5, 7), 10) - 1; // 월은 0부터 시작 (0=1월)
const day = parseInt(datePart.substring(8, 10), 10);
const hour = parseInt(hourStr, 10);
const minute = parseInt(minStr, 10);
return new Date(year, month, day, hour, minute, 0);
};
// Date 객체를 'YYYY-MM-DD HH:MI' 형식으로 포맷하는 헬퍼 함수
const formatDateTime = (dateObj) => {
const year = dateObj.getFullYear();
const month = String(dateObj.getMonth() + 1).padStart(2, '0');
const day = String(dateObj.getDate()).padStart(2, '0');
const hour = String(dateObj.getHours()).padStart(2, '0');
const minute = String(dateObj.getMinutes()).padStart(2, '0');
return `${year}-${month}-${day} ${hour}:${minute}`;
};
return this.selectedCardsHis.map(item => {
const startDateTime = createDateTime(item.bgnde, item.beginHour, item.beginMnt);
const endDateTime = createDateTime(item.endde, item.endHour, item.endMnt);
let status = '';
if (now >= startDateTime && now <= endDateTime) {
status = '사용 중'; // 현재 시간이 기간 안에 포함
} else if (now < startDateTime) {
status = '예약'; // 현재 시간이 시작일시보다 이전
} else { // now > endDateTime
status = '반납'; // 현재 시간이 종료일시보다 이후
}
return {
...item, // 원본 아이템의 모든 속성 유지
formattedPeriod: `${formatDateTime(startDateTime)} ~ ${formatDateTime(endDateTime)}`, // 포맷된 기간 문자열
status: status // 계산된 상태
};
});
}
},
mounted() {
console.log('main mounted');
this.searchCards();
this.searchCardsHis();
}
}
</script>
<style scoped>
tr {
cursor: pointer;
}
</style>