Files
sk_fems_ui/components/common/DatepickerTimeSelectBox.vue
2025-07-12 15:13:46 +09:00

526 lines
14 KiB
Vue

<template>
<v-row class="search-box" align="center" no-gutters>
<v-col v-if="label" :cols="labelCols">
<label for="" class="search-box-label">
<v-icon x-small :color="required ? '#fb8200' : 'primary'" class="mr-1"
>mdi-record-circle</v-icon
>
{{ label }}
</label>
</v-col>
<v-col :cols="label ? textCols : ''">
<div class="datepicker-container">
<v-text-field
id="startpicker"
ref="startpicker"
v-model="fromDtValue"
:class="(isRange && !selectBoxTimeItemList.selectTimeValue1) ? 'v-input__custom half' : 'v-input__custom'"
:hide-details="true"
readonly
outlined
>
<template #append>
<v-icon size="20">$icoCalendar</v-icon>
</template>
<template #append-outer>
<div ref="startpicker-container" id="startpicker-container"></div>
</template>
</v-text-field>
<component
v-if="selectBoxTimeItemList.selectTimeValue1"
:parentPrgmId="parentPrgmId"
:is="'SelectBoxTime'"
ref="SelectBox1"
:propsValue="selectTimeValue1"
:itemList="selectTimeValueList1"
:minInterval="selectBoxTimeItemList.minInterval ? selectBoxTimeItemList.minInterval : 1"
@update:propsValue="selectTimeValue1 = $event"
/>
<div v-show="isRange" class="mx-3" :style="{ lineHeight: 0 }">~</div>
<v-text-field
v-show="isRange"
id="endpicker"
ref="endpicker"
v-model="toDtValue"
:class="(isRange && !selectBoxTimeItemList.selectTimeValue2) ? 'v-input__custom half' : 'v-input__custom'"
:hide-details="true"
readonly
outlined
>
<template #append>
<v-icon size="20">$icoCalendar</v-icon>
</template>
<template #append-outer>
<div ref="endpicker-container" id="endpicker-container"></div>
</template>
</v-text-field>
<component
v-if="selectBoxTimeItemList.selectTimeValue2"
:parentPrgmId="parentPrgmId"
:is="'SelectBoxTime'"
ref="SelectBox2"
:propsValue="selectTimeValue2"
:itemList="selectTimeValueList2"
:minInterval="selectBoxTimeItemList.minInterval ? selectBoxTimeItemList.minInterval : 1"
@update:propsValue="selectTimeValue2 = $event"
/>
</div>
</v-col>
</v-row>
</template>
<script>
import { mapState, mapMutations } from 'vuex';
import TuiDatepicker from 'tui-date-picker';
import Utility from '~/plugins/utility';
import SelectBoxTime from '@/components/common/select/SelectBoxTime';
import DateUtility from '~/plugins/dateUtility'
export default {
props: {
parentPrgmId: {
type: String,
require: true,
},
label: {
type: String,
require: false,
},
timePicker: {
type: Boolean,
require: false,
default: false,
},
labelCols: {
type: Number,
require: false,
default: 4,
},
textCols: {
type: Number,
require: false,
default: 8,
},
required: {
type: Boolean,
require: false,
default: false,
},
isRangeOption:{
type:Boolean,
require:false,
default: true
},
selectBoxTimeItemList: {
type: Object,
require: false,
default: () => {
return {};
}
},
selectFromDtUntilTodayFg: {
type:Boolean,
require:false,
default: false
},
selectToDtUntilTodayFg: {
type:Boolean,
require:false,
default: false
},
},
components: {
SelectBoxTime
},
data() {
return {
today: new Date(),
startDatepickerInstance: null,
endDatepickerInstance: null,
startDtValue: null,
endDtValue: null,
fromDtOldVal: null,
toDtOldVal: null,
cmCycleFlag: false,
selectTimeValue1: this.selectBoxTimeItemList.selectTimeValue1 != undefined ? this.selectBoxTimeItemList.selectTimeValue1 : null, // selectBoxTime에 필요한 prop
selectTimeValueList1: this.selectBoxTimeItemList.selectTimeValueList1 != undefined ? this.selectBoxTimeItemList.selectTimeValueList1 : [], // selectBoxTime에 필요한 prop
selectTimeValue2: this.selectBoxTimeItemList.selectTimeValue2 != undefined ? this.selectBoxTimeItemList.selectTimeValue2 : null, // selectBoxTime에 필요한 prop
selectTimeValueList2: this.selectBoxTimeItemList.selectTimeValueList2 != undefined ? this.selectBoxTimeItemList.selectTimeValueList2 : [], // selectBoxTime에 필요한 prop
};
},
computed: {
...mapState({
searchParam(state) {
return state.pageData[this.parentPrgmId];
},
}),
myCmCycle() {
return this.searchParam.cmCycle;
},
myOptions() {
let returnObj = {};
switch (this.myCmCycle) {
case 'CYC_YEAR':
returnObj = {
type: 'year',
viewFormat: 'YYYY',
pickerFormat: 'YYYY',
sendFormat: 'YYYY',
};
break;
case 'CYC_MONTH':
returnObj = {
type: 'month',
viewFormat: 'YYYY-MM',
pickerFormat: 'YYYY-MM',
sendFormat: 'YYYYMM',
};
break;
case 'CYC_DAY':
returnObj = {
type: 'date',
viewFormat: 'YYYY-MM-DD',
pickerFormat: 'yyyy-MM-dd',
sendFormat: 'YYYYMMDD',
};
break;
case 'CYC_HOUR':
returnObj = {
type: 'date',
viewFormat: 'YYYY-MM-DD' + (this.timePicker ? ' HH:mm:ss' : ''),
pickerFormat: 'yyyy-MM-dd' + (this.timePicker ? ' HH:mm A' : ''),
sendFormat: this.timePicker ? 'YYYY-MM-DD HH:mm:ss' : 'YYYYMMDD',
};
// returnObj = { type: "day", format: "YYYY-MM-DD HH:mm:ss" };
break;
default:
break;
}
return returnObj;
},
// maxDate() {
// return Utility.setFormatDate("today", this.myOptions.format);
// },
fromDtValue(val) {
let selectVal = Utility.setFormatDate(
this.searchParam.fromDt,
this.myOptions.viewFormat,
);
if(this.selectFromDtUntilTodayFg){
let today = Utility.setFormatDate(new Date(), "YYYY-MM-DD");
let dayDiff = DateUtility.diff(selectVal,today,'days');
if(dayDiff < 0){
alert('오늘 날짜까지 검색이 가능합니다.');
selectVal = today;
if(this.fromDtOldVal == today){
this.toDtValueChkRang(selectVal);
this.startDatepickerInstance.setDate(new Date(selectVal));
}
}
}
if(this.fromDtOldVal == null){
this.fromDtOldVal = selectVal;
}
return selectVal;
// console.log('fromDtValue!!!',);
// return Utility.setFormatDate(
// this.searchParam.fromDt,
// this.myOptions.viewFormat,
// );
},
toDtValue() {
let selectVal = Utility.setFormatDate(
this.searchParam.toDt,
this.myOptions.viewFormat,
);
if(this.selectToDtUntilTodayFg){
let today = Utility.setFormatDate(new Date(), "YYYY-MM-DD");
let dayDiff = DateUtility.diff(selectVal,today,'days');
if(dayDiff < 0){
alert('오늘 날짜까지 검색이 가능합니다.');
selectVal = today;
if(this.toDtOldVal == today){
this.fromDtValueChkRang(selectVal);
this.endDatepickerInstance.setDate(new Date(selectVal));
}
}
}
if(this.toDtOldVal == null){
this.toDtOldVal = selectVal;
}
return selectVal;
// return Utility.setFormatDate(
// this.searchParam.toDt,
// this.myOptions.viewFormat,
// );
},
defaultRange() {
return this.searchParam.defaultRange
? this.searchParam.defaultRange[this.myCmCycle]
: null;
},
isRange() {
return (
(this.defaultRange !== null && this.defaultRange > 0 && this.isRangeOption) ||
this.defaultRange === 'no limite'
);
},
},
watch: {
selectTimeValue1(val){
if(this.selectBoxTimeItemList.selectTimeValue2 != undefined){
this.setSelectTimeValue2(val);
}else{
this.setPageData({ isFind: true });
}
},
selectTimeValue2(val){
this.setSelectTimeValue1(val);
// this.setPageData({ isFind: true });
},
myCmCycle() {
this.cmCycleFlag = false;
this.startDatepickerInstance.setDate(new Date(this.fromDtValue));
this.startDatepickerInstance.setType(this.myOptions.type);
this.endDatepickerInstance.setType(this.myOptions.type);
},
fromDtValue(newVal, oldVal) {
if (
this.isRange &&
this.defaultRange !== 'no limite' &&
newVal !== 'Invalid Date' &&
newVal !== oldVal
) {
this.toDtValueChkRang(newVal);
this.startDatepickerInstance.setDate(new Date(newVal));
this.fromDtOldVal = newVal;
this.setSelectTimeValue1(this.selectTimeValue2, 'check');
this.setSelectTimeValue2(this.selectTimeValue1, 'check');
} else {
this.setPageData({ isFind: true });
}
},
toDtValue(newVal, oldVal) {
if (
this.isRange &&
this.defaultRange !== 'no limite' &&
newVal !== 'Invalid Date' &&
newVal !== oldVal
) {
this.fromDtValueChkRang(newVal);
this.endDatepickerInstance.setDate(new Date(newVal));
this.toDtOldVal = newVal;
this.setSelectTimeValue1(this.selectTimeValue2, 'check');
this.setSelectTimeValue2(this.selectTimeValue1, 'check');
}
},
},
created() {
if (this.timePicker) {
this.setPageData({
fromDt: Utility.setFormatDate(this.today, 'YYYY-MM-DD') + ' 00:00:00',
toDt: Utility.setFormatDate(this.today, 'YYYY-MM-DD') + ' 23:59:59',
});
}
},
mounted() {
const startContainer = document.getElementById('startpicker-container');
const startTarget = document.getElementById('startpicker');
const endContainer = document.getElementById('endpicker-container');
const endTarget = document.getElementById('endpicker');
// datepicker 생성
this.startDatepickerInstance = new TuiDatepicker(startContainer, {
date: this.today,
language: 'ko',
type: this.myOptions.type, // "date", // type: date || month || year
input: {
element: startTarget,
format: this.myOptions.pickerFormat, //"YYYY-MM-DD" //this.format
},
timePicker: this.timePicker,
calendar: {
showToday: false,
},
});
// datepicker 생성
this.endDatepickerInstance = new TuiDatepicker(endContainer, {
date: this.today,
language: 'ko',
type: this.myOptions.type, // "date", // type: date || month || year
input: {
element: endTarget,
format: this.myOptions.pickerFormat, //"YYYY-MM-DD" //this.format
},
timePicker: this.timePicker,
calendar: {
showToday: false,
},
});
// datepicker 생성 끝
// datepicker 초기값 생성
this.startDatepickerInstance.setDate(new Date(this.fromDtValue));
// datepicker 초기값 생성 끝
// datepicker 변경시 이벤트 추가
this.startDatepickerInstance.on('change', () => this.getStartDt());
this.endDatepickerInstance.on('change', () => this.getEndDt());
// datepicker 이벤트는 mount 될때 추가 해주어야 한다.
},
methods: {
...mapMutations({ setPageData: 'setPageData' }),
getStartDt() {
const dt = this.startDatepickerInstance.getDate();
this.setPageData({
fromDt: Utility.setFormatDate(dt, this.myOptions.sendFormat),
});
},
getEndDt() {
const dt = this.endDatepickerInstance.getDate();
this.setPageData({
toDt: Utility.setFormatDate(dt, this.myOptions.sendFormat),
});
},
fromDtValueChkRang(newDt) {
const defaultDt = this.$dayjs(this.fromDtValue);
const compareDt = this.$dayjs(newDt);
const newDefault = Utility.setNewDefaultRange(
this.myCmCycle,
this.defaultRange,
);
const myRange = newDefault.range;
const rangeKey = newDefault.key;
const rangeGap = compareDt.diff(defaultDt, rangeKey);
if (
(myRange > rangeGap && compareDt.isAfter(defaultDt)) ||
defaultDt.format(this.myOptions.sendFormat) ===
compareDt.format(this.myOptions.sendFormat)
) {
// if(this.cmCycleFlag){
this.setPageData({ isFind: true });
// }
// this.cmCycleFlag = true;
} else {
this.setPageData({
fromDt: Utility.setBeforetDate(
this.searchParam,
compareDt,
this.myOptions.sendFormat,
),
});
}
},
toDtValueChkRang(newDt) {
const defaultDt = this.$dayjs(this.toDtValue);
const compareDt = this.$dayjs(newDt);
const newDefault = Utility.setNewDefaultRange(
this.myCmCycle,
this.defaultRange,
);
const myRange = newDefault.range;
const rangeKey = newDefault.key;
const rangeGap = defaultDt.diff(compareDt, rangeKey);
if (
(myRange > rangeGap && defaultDt.isAfter(compareDt)) ||
defaultDt.format(this.myOptions.sendFormat) ===
compareDt.format(this.myOptions.sendFormat)
) {
this.setPageData({ isFind: true });
} else {
this.setPageData({
toDt: Utility.setAftertDate(
this.searchParam,
compareDt,
this.myOptions.sendFormat,
),
});
}
},
setSelectTimeValue2(val, type='default'){
this.setPageData({selectTimeValue1:val});
let toDt = this.toDtOldVal;
let fromDt = this.fromDtOldVal;
let dayDiff = DateUtility.diff(fromDt,toDt,'days');
let selectTimeValueList2 = this.selectTimeValueList2.map(item => {
return item.value;
});
if(dayDiff <= 0 && selectTimeValueList2.indexOf(this.selectTimeValue2) < selectTimeValueList2.indexOf(val)){
// this.selectTimeValue2 = selectTimeValueList2[selectTimeValueList2.indexOf(val)];
this.selectTimeValue2 = val;
this.setPageData({selectTimeValue2:val});
}else{
if(type=='default'){
this.setPageData({ isFind: true });
}
}
},
setSelectTimeValue1(val, type='default'){
this.setPageData({selectTimeValue2:val});
let toDt = this.toDtOldVal;
let fromDt = this.fromDtOldVal;
let dayDiff = DateUtility.diff(fromDt,toDt,'days');
let selectTimeValueList2 = this.selectTimeValueList2.map(item => {
return item.value;
});
if(dayDiff <= 0 && selectTimeValueList2.indexOf(val) < selectTimeValueList2.indexOf(this.selectTimeValue1)){
// this.selectTimeValue1 = selectTimeValueList2[selectTimeValueList2.indexOf(val)];
this.selectTimeValue1 = val;
// this.selectTimeValue1 = this.selectTimeValueList2[selectTimeValueList2.indexOf(val) + 1]
this.setPageData({selectTimeValue1:val});
}else{
if(type=='default'){
this.setPageData({ isFind: true });
}
}
}
},
};
</script>
<style lang="scss" scoped>
.datepicker-container {
display: flex;
align-items: center;
justify-content: space-between;
position: relative;
.v-input {
.v-input__append-outer {
margin-top: 0;
margin-left: 0;
#startpicker-container,
#endpicker-container {
width: 100%;
position: absolute;
top: 36px;
left: 0;
}
}
}
}
.v-input__custom {
flex: 0 0 auto;
&.half {
width: calc(50% - 20px);
}
}
::v-deep {
.tui-timepicker-row {
display: flex;
justify-content: space-around;
background-color: #edf4fc;
.tui-timepicker-column.tui-timepicker-colon {
color: #000 !important;
}
}
}
</style>