evui 3.4.207 → 3.4.209
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +18 -33
- package/dist/404.html +44 -0
- package/dist/favicon.ico +0 -0
- package/dist/index.js +22738 -0
- package/dist/index.umd.cjs +28 -0
- package/dist/style.css +1 -0
- package/package.json +46 -43
- package/dist/evui.common.js +0 -63681
- package/dist/evui.common.js.map +0 -1
- package/dist/evui.umd.js +0 -63691
- package/dist/evui.umd.js.map +0 -1
- package/dist/evui.umd.min.js +0 -2
- package/dist/evui.umd.min.js.map +0 -1
- package/dist/img/EVUI.b82ee81a.svg +0 -293
- package/src/assets/logo.png +0 -0
- package/src/common/emitter.js +0 -20
- package/src/common/utils.bignumber.js +0 -67
- package/src/common/utils.debounce.js +0 -223
- package/src/common/utils.js +0 -151
- package/src/common/utils.table.js +0 -78
- package/src/common/utils.throttle.js +0 -83
- package/src/common/utils.tree.js +0 -18
- package/src/components/button/Button.vue +0 -195
- package/src/components/button/index.js +0 -7
- package/src/components/buttonGroup/ButtonGroup.vue +0 -11
- package/src/components/buttonGroup/index.js +0 -7
- package/src/components/calendar/Calendar.vue +0 -725
- package/src/components/calendar/index.js +0 -7
- package/src/components/calendar/uses.js +0 -1410
- package/src/components/chart/Chart.vue +0 -363
- package/src/components/chart/ChartToolbar.vue +0 -52
- package/src/components/chart/chart.core.js +0 -1170
- package/src/components/chart/chartZoom.core.js +0 -540
- package/src/components/chart/element/element.bar.js +0 -672
- package/src/components/chart/element/element.bar.time.js +0 -166
- package/src/components/chart/element/element.heatmap.js +0 -743
- package/src/components/chart/element/element.line.js +0 -611
- package/src/components/chart/element/element.pie.js +0 -197
- package/src/components/chart/element/element.scatter.js +0 -320
- package/src/components/chart/element/element.tip.js +0 -717
- package/src/components/chart/helpers/helpers.canvas.js +0 -265
- package/src/components/chart/helpers/helpers.constant.js +0 -235
- package/src/components/chart/helpers/helpers.util.js +0 -400
- package/src/components/chart/index.js +0 -9
- package/src/components/chart/model/index.js +0 -50
- package/src/components/chart/model/model.series.js +0 -125
- package/src/components/chart/model/model.store.js +0 -1427
- package/src/components/chart/plugins/plugins.interaction.js +0 -1659
- package/src/components/chart/plugins/plugins.legend.gradient.js +0 -606
- package/src/components/chart/plugins/plugins.legend.js +0 -1543
- package/src/components/chart/plugins/plugins.pie.js +0 -254
- package/src/components/chart/plugins/plugins.scrollbar.js +0 -732
- package/src/components/chart/plugins/plugins.title.js +0 -61
- package/src/components/chart/plugins/plugins.tooltip.js +0 -1041
- package/src/components/chart/scale/scale.js +0 -951
- package/src/components/chart/scale/scale.linear.js +0 -268
- package/src/components/chart/scale/scale.logarithmic.js +0 -135
- package/src/components/chart/scale/scale.step.js +0 -430
- package/src/components/chart/scale/scale.time.category.js +0 -338
- package/src/components/chart/scale/scale.time.js +0 -49
- package/src/components/chart/style/chart.scss +0 -405
- package/src/components/chart/uses.js +0 -721
- package/src/components/chartBrush/ChartBrush.vue +0 -323
- package/src/components/chartBrush/chartBrush.core.js +0 -691
- package/src/components/chartBrush/index.js +0 -9
- package/src/components/chartBrush/uses.js +0 -23
- package/src/components/chartGroup/ChartGroup.vue +0 -144
- package/src/components/chartGroup/index.js +0 -9
- package/src/components/chartGroup/style/chartGroup.scss +0 -5
- package/src/components/chartGroup/uses.js +0 -53
- package/src/components/checkbox/Checkbox.vue +0 -229
- package/src/components/checkbox/index.js +0 -7
- package/src/components/checkboxGroup/CheckboxGroup.vue +0 -44
- package/src/components/checkboxGroup/index.js +0 -7
- package/src/components/contextMenu/ContextMenu.vue +0 -95
- package/src/components/contextMenu/MenuList.vue +0 -182
- package/src/components/contextMenu/index.js +0 -7
- package/src/components/contextMenu/uses.js +0 -223
- package/src/components/datePicker/DatePicker.vue +0 -504
- package/src/components/datePicker/index.js +0 -7
- package/src/components/datePicker/uses.js +0 -460
- package/src/components/grid/Grid.vue +0 -1535
- package/src/components/grid/GridColumnSetting.vue +0 -358
- package/src/components/grid/GridFilterSetting.vue +0 -323
- package/src/components/grid/GridPagination.vue +0 -75
- package/src/components/grid/GridSummary.vue +0 -314
- package/src/components/grid/GridToolbar.vue +0 -35
- package/src/components/grid/icon/icon-option-button.vue +0 -17
- package/src/components/grid/icon/icon-sort-button.vue +0 -67
- package/src/components/grid/index.js +0 -11
- package/src/components/grid/style/grid.scss +0 -417
- package/src/components/grid/uses.js +0 -1629
- package/src/components/icon/Icon.vue +0 -53
- package/src/components/icon/index.js +0 -8
- package/src/components/inputNumber/InputNumber.vue +0 -212
- package/src/components/inputNumber/index.js +0 -7
- package/src/components/inputNumber/uses.js +0 -217
- package/src/components/loading/Loading.vue +0 -125
- package/src/components/loading/index.js +0 -7
- package/src/components/menu/Menu.vue +0 -79
- package/src/components/menu/MenuItem.vue +0 -201
- package/src/components/menu/index.js +0 -7
- package/src/components/message/Message.vue +0 -229
- package/src/components/message/index.js +0 -34
- package/src/components/messageBox/MessageBox.vue +0 -358
- package/src/components/messageBox/index.js +0 -22
- package/src/components/notification/Notification.vue +0 -316
- package/src/components/notification/index.js +0 -49
- package/src/components/pagination/Pagination.vue +0 -317
- package/src/components/pagination/index.js +0 -7
- package/src/components/pagination/pageButton.vue +0 -31
- package/src/components/progress/Progress.vue +0 -139
- package/src/components/progress/index.js +0 -7
- package/src/components/radio/Radio.vue +0 -159
- package/src/components/radio/index.js +0 -7
- package/src/components/radioGroup/RadioGroup.vue +0 -41
- package/src/components/radioGroup/index.js +0 -7
- package/src/components/scheduler/Scheduler.vue +0 -149
- package/src/components/scheduler/index.js +0 -7
- package/src/components/scheduler/uses.js +0 -183
- package/src/components/select/Select.vue +0 -556
- package/src/components/select/index.js +0 -7
- package/src/components/select/uses.js +0 -379
- package/src/components/slider/Slider.vue +0 -505
- package/src/components/slider/index.js +0 -7
- package/src/components/slider/uses.js +0 -391
- package/src/components/tabPanel/TabPanel.vue +0 -74
- package/src/components/tabPanel/index.js +0 -7
- package/src/components/tabs/Tabs.vue +0 -517
- package/src/components/tabs/index.js +0 -7
- package/src/components/textField/TextField.vue +0 -399
- package/src/components/textField/index.js +0 -7
- package/src/components/timePicker/TimePicker.vue +0 -364
- package/src/components/timePicker/index.js +0 -7
- package/src/components/toggle/Toggle.vue +0 -115
- package/src/components/toggle/index.js +0 -7
- package/src/components/tree/Tree.vue +0 -338
- package/src/components/tree/TreeNode.vue +0 -293
- package/src/components/tree/index.js +0 -7
- package/src/components/treeGrid/TreeGrid.vue +0 -1074
- package/src/components/treeGrid/TreeGridNode.vue +0 -349
- package/src/components/treeGrid/TreeGridToolbar.vue +0 -35
- package/src/components/treeGrid/icon/icon-tree.png +0 -0
- package/src/components/treeGrid/index.js +0 -9
- package/src/components/treeGrid/style/treeGrid.scss +0 -277
- package/src/components/treeGrid/uses.js +0 -1178
- package/src/components/window/Window.vue +0 -329
- package/src/components/window/index.js +0 -7
- package/src/components/window/uses.js +0 -908
- package/src/directives/clickoutside.js +0 -90
- package/src/main.js +0 -120
- package/src/style/components/input.scss +0 -108
- package/src/style/functions.scss +0 -3
- package/src/style/index.scss +0 -6
- package/src/style/lib/fonts/EVUI.eot +0 -0
- package/src/style/lib/fonts/EVUI.svg +0 -293
- package/src/style/lib/fonts/EVUI.ttf +0 -0
- package/src/style/lib/fonts/EVUI.woff +0 -0
- package/src/style/lib/icon.css +0 -888
- package/src/style/mixins.scss +0 -94
- package/src/style/themes.scss +0 -69
- package/src/style/variables.scss +0 -22
|
@@ -1,1410 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
ref, reactive, computed, getCurrentInstance, unref, onBeforeMount, watch,
|
|
3
|
-
} from 'vue';
|
|
4
|
-
import { throttle } from 'lodash-es';
|
|
5
|
-
|
|
6
|
-
const CALENDAR_ROWS = 6;
|
|
7
|
-
const CALENDAR_COLS = 7;
|
|
8
|
-
const CALENDAR_MONTH_ROWS = 4;
|
|
9
|
-
const CALENDAR_MONTH_COLS = 3;
|
|
10
|
-
const CALENDAR_YEAR_ROWS = 5;
|
|
11
|
-
const CALENDAR_YEAR_COLS = 4;
|
|
12
|
-
const MONTH_CNT = 12;
|
|
13
|
-
const HOUR_CNT = 24;
|
|
14
|
-
const MIN_CNT = 60;
|
|
15
|
-
const SEC_CNT = 60;
|
|
16
|
-
const CELL_CNT_IN_ONE_PAGE = 12;
|
|
17
|
-
const CELL_CNT_IN_ONE_ROW = 4;
|
|
18
|
-
const YEAR_CNT_IN_ONE_PAGE = 20;
|
|
19
|
-
const MONTH_NAME_LIST = {
|
|
20
|
-
fullName: ['January', 'February', 'March', 'April', 'May', 'June',
|
|
21
|
-
'July', 'August', 'September', 'October', 'November', 'December'],
|
|
22
|
-
numberName: ['1', '2', '3', '4', '5', '6',
|
|
23
|
-
'7', '8', '9', '10', '11', '12'],
|
|
24
|
-
abbrName: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
|
|
25
|
-
'Jul', 'Aug', 'Sept', 'Oct', 'Nov', 'Dec'],
|
|
26
|
-
korName: ['1월', '2월', '3월', '4월', '5월', '6월',
|
|
27
|
-
'7월', '8월', '9월', '10월', '11월', '12월'],
|
|
28
|
-
};
|
|
29
|
-
const DAY_OF_THE_WEEK_NAME_LIST = {
|
|
30
|
-
abbrUpperName: ['SUN', 'MON', 'TUE', 'WED', 'THU', 'FRI', 'SAT'],
|
|
31
|
-
abbrLowerName: ['sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat'],
|
|
32
|
-
abbrPascalName: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
|
|
33
|
-
abbrKorName: ['일', '월', '화', '수', '목', '금', '토'],
|
|
34
|
-
};
|
|
35
|
-
|
|
36
|
-
const LIST_TYPE = {
|
|
37
|
-
DATE: 'date',
|
|
38
|
-
MONTH: 'month',
|
|
39
|
-
YEAR: 'year',
|
|
40
|
-
};
|
|
41
|
-
|
|
42
|
-
const ONE_DAY_MS = 86400000;
|
|
43
|
-
const MIN_DATE_MS = +new Date('1970-01-01 00:00:00'); // javascript 객체 최소 시간
|
|
44
|
-
const dateReg = new RegExp(/[0-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])/);
|
|
45
|
-
const dateTimeReg = new RegExp(/[0-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1]) (2[0-3]|[01][0-9]):[0-5][0-9]:[0-5][0-9]/);
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* 배열 내 여러 날짜(eg. 'YYYY-MM-DD' || 'YYYY-MM-DD HH:MI:SS') 중 가장 끝의 날짜 텍스트 구하기
|
|
49
|
-
* @param arr
|
|
50
|
-
* @param sideDirection - 끝의 방향 (first: 가장 멀리 오래된 날짜, last: 가장 최근의 날짜)
|
|
51
|
-
* @returns {String} - 날짜 텍스트
|
|
52
|
-
*/
|
|
53
|
-
const getSideDateStr = (arr, sideDirection) => {
|
|
54
|
-
if (!arr.length) return '';
|
|
55
|
-
if (sideDirection === 'last') {
|
|
56
|
-
return arr
|
|
57
|
-
.reduce((prev, cur) => (new Date(prev).getTime() > new Date(cur).getTime() ? prev : cur));
|
|
58
|
-
}
|
|
59
|
-
return arr
|
|
60
|
-
.reduce((prev, cur) => (new Date(prev).getTime() < new Date(cur).getTime() ? prev : cur));
|
|
61
|
-
};
|
|
62
|
-
|
|
63
|
-
/**
|
|
64
|
-
* 월, 일을 두자리 숫자로 보정
|
|
65
|
-
* @param num
|
|
66
|
-
* @returns {string|*}
|
|
67
|
-
*/
|
|
68
|
-
export const lpadToTwoDigits = (num) => {
|
|
69
|
-
if (num === null) {
|
|
70
|
-
return '00';
|
|
71
|
-
} else if (+num < 10) {
|
|
72
|
-
return `0${num}`;
|
|
73
|
-
}
|
|
74
|
-
return num;
|
|
75
|
-
};
|
|
76
|
-
|
|
77
|
-
/**
|
|
78
|
-
* 이차원 배열 만들기
|
|
79
|
-
* @param row
|
|
80
|
-
* @param col
|
|
81
|
-
* @returns {Array} - [row][col]
|
|
82
|
-
*/
|
|
83
|
-
const getMatrixArr = (row, col) => Array.from(Array(row), () => Array(col).fill(false));
|
|
84
|
-
|
|
85
|
-
/**
|
|
86
|
-
* y년 m월 1일의 요일 구하기
|
|
87
|
-
* @param y - 년
|
|
88
|
-
* @param m - 월
|
|
89
|
-
* @returns {number} - 해당 y년 m월 1일의 요일 (e.g. 0: SUN, ..., 6: SAT)
|
|
90
|
-
* - 1주차에서 일요일부터 1일까지의 공백 개수
|
|
91
|
-
*/
|
|
92
|
-
const getDayOfWeekOnThe1stOfMonth = (y, m) => new Date(`${y}-${m}-1`).getDay();
|
|
93
|
-
|
|
94
|
-
/**
|
|
95
|
-
* y년 m월 마지막 일자 구하기
|
|
96
|
-
* @param y
|
|
97
|
-
* @param m
|
|
98
|
-
* @returns {number} - 해당 년, 월의 마지막 일자
|
|
99
|
-
*/
|
|
100
|
-
export const getLastDateOfMonth = (y, m) => {
|
|
101
|
-
let day;
|
|
102
|
-
switch (m) {
|
|
103
|
-
case 4:
|
|
104
|
-
case 6:
|
|
105
|
-
case 9:
|
|
106
|
-
case 11:
|
|
107
|
-
day = 30;
|
|
108
|
-
break;
|
|
109
|
-
case 2:
|
|
110
|
-
if (((y % 4 === 0) && (y % 100 !== 0)) || (y % 400 === 0)) {
|
|
111
|
-
day = 29;
|
|
112
|
-
} else {
|
|
113
|
-
day = 28;
|
|
114
|
-
}
|
|
115
|
-
break;
|
|
116
|
-
default:
|
|
117
|
-
day = 31;
|
|
118
|
-
break;
|
|
119
|
-
}
|
|
120
|
-
return day;
|
|
121
|
-
};
|
|
122
|
-
|
|
123
|
-
/**
|
|
124
|
-
* date또는 time 형태로 format string으로 조합
|
|
125
|
-
* @param year
|
|
126
|
-
* @param month
|
|
127
|
-
* @param date
|
|
128
|
-
* @param hour
|
|
129
|
-
* @param min
|
|
130
|
-
* @param sec
|
|
131
|
-
* @returns {string}
|
|
132
|
-
*/
|
|
133
|
-
const formatDateTime = ({ year, month, date, hour, min, sec }) => {
|
|
134
|
-
if (hour !== undefined && min !== undefined && sec !== undefined) {
|
|
135
|
-
return `${year}-${lpadToTwoDigits(month)}-${lpadToTwoDigits(date)} ${lpadToTwoDigits(hour)}:${lpadToTwoDigits(min)}:${lpadToTwoDigits(sec)}`;
|
|
136
|
-
}
|
|
137
|
-
return `${year}-${lpadToTwoDigits(month)}-${lpadToTwoDigits(date)}`;
|
|
138
|
-
};
|
|
139
|
-
|
|
140
|
-
/**
|
|
141
|
-
* 첫번째 인자로 받은 날짜 형식 String ('YYYY-MM-DD' || 'YYYY-MM-DD HH:MI:SS')이나
|
|
142
|
-
* 해당 날짜형식이 들어있는 Array를 받아서 최신날짜의 정보를 추출하는 함수
|
|
143
|
-
* typeToImport가 존재하는 경우 해당 timeType의 값을
|
|
144
|
-
* typeToImport가 존재하지 않는 경우 최신날짜 텍스트를 timeType별로 분할한 Object를 리턴
|
|
145
|
-
* @param param {String | Array} - 변경하려는 날짜
|
|
146
|
-
* @param typeToImport
|
|
147
|
-
* @returns {object|number}
|
|
148
|
-
*/
|
|
149
|
-
const getDateTimeInfoByType = (param, typeToImport) => {
|
|
150
|
-
let str = unref(param);
|
|
151
|
-
if (Array.isArray(str)) {
|
|
152
|
-
str = getSideDateStr(param, 'last');
|
|
153
|
-
}
|
|
154
|
-
const result = {
|
|
155
|
-
year: +(str?.split(' ')[0]?.split('-')[0]) || null,
|
|
156
|
-
month: +(str?.split(' ')[0]?.split('-')[1]) || null,
|
|
157
|
-
date: +(str?.split(' ')[0]?.split('-')[2]) || null,
|
|
158
|
-
hour: +(str?.split(' ')[1]?.split(':')[0]) || 0,
|
|
159
|
-
min: +(str?.split(' ')[1]?.split(':')[1]) || 0,
|
|
160
|
-
sec: +(str?.split(' ')[1]?.split(':')[2]) || 0,
|
|
161
|
-
};
|
|
162
|
-
if (typeToImport === 'year') return result.year;
|
|
163
|
-
if (typeToImport === 'month') return result.month;
|
|
164
|
-
if (typeToImport === 'date') return result.date;
|
|
165
|
-
if (typeToImport === 'hour') return result.hour;
|
|
166
|
-
if (typeToImport === 'min') return result.min;
|
|
167
|
-
if (typeToImport === 'sec') return result.sec;
|
|
168
|
-
return result;
|
|
169
|
-
};
|
|
170
|
-
/**
|
|
171
|
-
* 이전달, 다음달의 달력 상 연도, 월 정보 구하기
|
|
172
|
-
* @param prevNext - 이전, 다음 여부 ('prev'|'next')
|
|
173
|
-
* @param year
|
|
174
|
-
* @param month
|
|
175
|
-
* @returns {{month: number, year: *}}
|
|
176
|
-
*/
|
|
177
|
-
const getSideMonthCalendarInfo = (prevNext, year, month) => {
|
|
178
|
-
if (prevNext === 'next') {
|
|
179
|
-
return {
|
|
180
|
-
year: month === 12 ? year + 1 : year,
|
|
181
|
-
month: ((month + 1) % 12) || 12,
|
|
182
|
-
};
|
|
183
|
-
}
|
|
184
|
-
return {
|
|
185
|
-
year: month === 1 ? year - 1 : year,
|
|
186
|
-
month: ((month - 1) % 12) || 12,
|
|
187
|
-
};
|
|
188
|
-
};
|
|
189
|
-
|
|
190
|
-
/**
|
|
191
|
-
* timeFormat을 체크하여 timeFormat이 있으면 format에 맞는 형식으로 반환
|
|
192
|
-
* @param timeFormat -- props.option?.timeFormat
|
|
193
|
-
* @param dateTimeValue
|
|
194
|
-
* @param typeToImport
|
|
195
|
-
* @returns {Object|number}
|
|
196
|
-
*/
|
|
197
|
-
const getTimeInfoByTimeFormat = (timeFormat, dateTimeValue, typeToImport) => {
|
|
198
|
-
const value = getDateTimeInfoByType(dateTimeValue, typeToImport);
|
|
199
|
-
if (timeFormat) {
|
|
200
|
-
const hour = timeFormat?.split(':')[0];
|
|
201
|
-
const min = timeFormat?.split(':')[1];
|
|
202
|
-
const sec = timeFormat?.split(':')[2];
|
|
203
|
-
if (typeToImport === 'hour') {
|
|
204
|
-
return hour === 'HH' ? value : +hour;
|
|
205
|
-
} else if (typeToImport === 'min') {
|
|
206
|
-
return min === 'mm' ? value : +min;
|
|
207
|
-
} else if (typeToImport === 'sec') {
|
|
208
|
-
return sec === 'ss' ? value : +sec;
|
|
209
|
-
}
|
|
210
|
-
}
|
|
211
|
-
return value;
|
|
212
|
-
};
|
|
213
|
-
|
|
214
|
-
/**
|
|
215
|
-
* 초기 timeFormat에 따른 modelValue update 함수
|
|
216
|
-
* @param timeFormat - props.options.timeFormat
|
|
217
|
-
* @param modelValue
|
|
218
|
-
* @returns string
|
|
219
|
-
*/
|
|
220
|
-
export const getChangedValueByTimeFormat = (timeFormat, modelValue) => {
|
|
221
|
-
if (!modelValue) {
|
|
222
|
-
return '';
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
const hourByTimeFormat = lpadToTwoDigits(getTimeInfoByTimeFormat(timeFormat, modelValue, 'hour'));
|
|
226
|
-
const minByTimeFormat = lpadToTwoDigits(getTimeInfoByTimeFormat(timeFormat, modelValue, 'min'));
|
|
227
|
-
const secByTimeFormat = lpadToTwoDigits(getTimeInfoByTimeFormat(timeFormat, modelValue, 'sec'));
|
|
228
|
-
|
|
229
|
-
return `${modelValue.split(' ')[0]} ${hourByTimeFormat}:${minByTimeFormat}:${secByTimeFormat}`;
|
|
230
|
-
};
|
|
231
|
-
|
|
232
|
-
/**
|
|
233
|
-
* 현재 달력의 날짜와 다음 달력의 날짜 비교 (disabledDate 옵션이 없는 경우만 적용)
|
|
234
|
-
* @param mode - calendar mode
|
|
235
|
-
* @param calendarType - 달력 종류 {main | expanded}
|
|
236
|
-
* @param targetDate - 기준 날짜
|
|
237
|
-
* @param modelValue - model value
|
|
238
|
-
* @returns {*|boolean}
|
|
239
|
-
*/
|
|
240
|
-
const compareFromAndToDateTime = (mode, calendarType, targetDate, modelValue) => {
|
|
241
|
-
if (!modelValue.length) {
|
|
242
|
-
return false;
|
|
243
|
-
}
|
|
244
|
-
let fromDate = calendarType === 'main' ? targetDate : modelValue[0];
|
|
245
|
-
let toDate = calendarType === 'expanded' ? targetDate : modelValue[1];
|
|
246
|
-
|
|
247
|
-
let fromDateTime = fromDate;
|
|
248
|
-
let toDateTime = toDate;
|
|
249
|
-
if (!targetDate.split(' ')[1]) {
|
|
250
|
-
if (mode === 'dateTimeRange') {
|
|
251
|
-
fromDate = fromDate.split(' ')[0];
|
|
252
|
-
toDate = toDate.split(' ')[0];
|
|
253
|
-
const fromTime = modelValue[0].split(' ')[1];
|
|
254
|
-
const toTime = modelValue[1].split(' ')[1];
|
|
255
|
-
fromDateTime = `${fromDate} ${fromTime}`;
|
|
256
|
-
toDateTime = `${toDate} ${toTime}`;
|
|
257
|
-
} else {
|
|
258
|
-
fromDateTime = `${fromDate} 00:00:00`;
|
|
259
|
-
toDateTime = `${toDate} 23:59:59`;
|
|
260
|
-
}
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
return (fromDateTime && toDateTime)
|
|
264
|
-
&& new Date(fromDateTime).getTime() > +new Date(toDateTime).getTime();
|
|
265
|
-
};
|
|
266
|
-
|
|
267
|
-
/**
|
|
268
|
-
* date string 값의 MS 값 구하기
|
|
269
|
-
* @param dateStr
|
|
270
|
-
* @returns {number}
|
|
271
|
-
*/
|
|
272
|
-
const getDateMs = dateStr => new Date(`${dateStr}`).getTime();
|
|
273
|
-
|
|
274
|
-
/**
|
|
275
|
-
* Calendar 년도 범위 구하기
|
|
276
|
-
* @param currentYear - 현재 Calendar 페이지 정보의 년도
|
|
277
|
-
* @returns {{start: number, end: number}} - start: 시작년도, end: 마지막 년도
|
|
278
|
-
*/
|
|
279
|
-
const getYearRange = (currentYear) => {
|
|
280
|
-
const multipleOf10 = 10 ** (currentYear.toString().length - 1);
|
|
281
|
-
const quotient = Math.floor(currentYear / multipleOf10);
|
|
282
|
-
const remainder = Math.floor(currentYear % (multipleOf10 * quotient));
|
|
283
|
-
const startYear = (quotient * multipleOf10)
|
|
284
|
-
+ (Math.floor(remainder / YEAR_CNT_IN_ONE_PAGE) * YEAR_CNT_IN_ONE_PAGE);
|
|
285
|
-
const endYear = startYear + YEAR_CNT_IN_ONE_PAGE - 1;
|
|
286
|
-
return {
|
|
287
|
-
start: startYear,
|
|
288
|
-
end: endYear,
|
|
289
|
-
};
|
|
290
|
-
};
|
|
291
|
-
|
|
292
|
-
export const useModel = () => {
|
|
293
|
-
const { props } = getCurrentInstance();
|
|
294
|
-
const timeFormat = props.options?.timeFormat;
|
|
295
|
-
|
|
296
|
-
// 달력 list - 'dateRange | dateTimeRange' 모드인 경우 확장 달력 추가
|
|
297
|
-
const calendarList = computed(() =>
|
|
298
|
-
(['dateRange', 'dateTimeRange'].includes(props.mode) ? ['main', 'expanded'] : ['main']),
|
|
299
|
-
);
|
|
300
|
-
|
|
301
|
-
/**
|
|
302
|
-
* 현재 선택된 값, 배열인 경우 반응형을 끊기위해 rest 사용
|
|
303
|
-
* selectValue ref로 변환하기 전 modelValue timeFormat에 따라 fetch
|
|
304
|
-
* 1) props.mode: 'date' or 'dateTime' > String
|
|
305
|
-
* 2) props.mode: 'dateMulti' or 'dateRange' > [...Array]
|
|
306
|
-
*/
|
|
307
|
-
let selectedValue;
|
|
308
|
-
if (props.mode !== 'dateMulti' && props.mode !== 'dateRange' && props.mode !== 'dateTimeRange') {
|
|
309
|
-
if (props.modelValue
|
|
310
|
-
&& ((props.modelValue.length === 10 && dateReg.exec(props.modelValue?.toString()))
|
|
311
|
-
|| (props.modelValue.length === 19 && dateTimeReg.exec(props.modelValue?.toString())))
|
|
312
|
-
) {
|
|
313
|
-
if (props.mode === 'dateTime' && timeFormat) {
|
|
314
|
-
const modelValue = getChangedValueByTimeFormat(timeFormat, props.modelValue);
|
|
315
|
-
selectedValue = ref(modelValue);
|
|
316
|
-
} else {
|
|
317
|
-
selectedValue = ref(props.modelValue);
|
|
318
|
-
}
|
|
319
|
-
} else {
|
|
320
|
-
selectedValue = ref('');
|
|
321
|
-
}
|
|
322
|
-
} else if (Array.isArray(props.modelValue)
|
|
323
|
-
&& props.modelValue.every(v => (
|
|
324
|
-
!v
|
|
325
|
-
|| (v.length === 10 && dateReg.exec(v))
|
|
326
|
-
|| (v.length === 19 && dateTimeReg.exec(v))
|
|
327
|
-
))
|
|
328
|
-
) {
|
|
329
|
-
if (props.mode === 'dateTimeRange' && props.modelValue.length === 2 && timeFormat) {
|
|
330
|
-
const modelValue = [];
|
|
331
|
-
modelValue.push(getChangedValueByTimeFormat(timeFormat[0], props.modelValue[0]));
|
|
332
|
-
modelValue.push(getChangedValueByTimeFormat(timeFormat[1], props.modelValue[1]));
|
|
333
|
-
selectedValue = ref([...modelValue]);
|
|
334
|
-
} else {
|
|
335
|
-
selectedValue = ref([...props.modelValue]);
|
|
336
|
-
}
|
|
337
|
-
} else {
|
|
338
|
-
selectedValue = ref([]);
|
|
339
|
-
}
|
|
340
|
-
|
|
341
|
-
/**
|
|
342
|
-
* validate v-model's value
|
|
343
|
-
*/
|
|
344
|
-
const validateModelValue = () => {
|
|
345
|
-
if (props.mode === 'date' && props.modelValue && typeof props.modelValue !== 'string') {
|
|
346
|
-
console.warn('[EVUI][Calendar] When mode is \'date\', v-model must be \'String\' type.');
|
|
347
|
-
} else if (props.mode === 'dateTime' && props.modelValue && typeof props.modelValue !== 'string') {
|
|
348
|
-
console.warn('[EVUI][Calendar] When mode is \'dateTime\', v-model must be \'String\' type.');
|
|
349
|
-
} else if (props.mode === 'dateMulti' && props.modelValue && !Array.isArray(props.modelValue)) {
|
|
350
|
-
console.warn('[EVUI][Calendar] When mode is \'dateMulti\', v-model must be \'Array\' type.');
|
|
351
|
-
} else if (props.mode === 'dateRange' && props.modelValue) {
|
|
352
|
-
if (!Array.isArray(props.modelValue)) {
|
|
353
|
-
console.warn('[EVUI][Calendar] When mode is \'dateRange\', v-model must be \'Array\' type.');
|
|
354
|
-
} else if (getDateMs(`${props.modelValue[0]} 00:00:00`) > getDateMs(`${props.modelValue[1]} 00:00:00`)) {
|
|
355
|
-
console.warn('[EVUI][Calendar] When mode is \'dateRange\', fromDate must be less than toDate.');
|
|
356
|
-
}
|
|
357
|
-
} else if (props.mode === 'dateTimeRange' && props.modelValue) {
|
|
358
|
-
if (!Array.isArray(props.modelValue)) {
|
|
359
|
-
console.warn('[EVUI][Calendar] When mode is \'dateTimeRange\', v-model must be \'Array\' type.');
|
|
360
|
-
} else if (getDateMs(props.modelValue[0]) > getDateMs(props.modelValue[1])) {
|
|
361
|
-
console.warn('[EVUI][Calendar] When mode is \'dateRange\', fromDate must be less than toDate.');
|
|
362
|
-
}
|
|
363
|
-
}
|
|
364
|
-
};
|
|
365
|
-
|
|
366
|
-
// 메인(좌측) 달력(연, 월, 시, 분, 초) 페이징 정보
|
|
367
|
-
let mainCalendarPageInfo;
|
|
368
|
-
const mainValue = !['dateRange', 'dateTimeRange'].includes(props.mode) ? selectedValue.value : selectedValue.value[0];
|
|
369
|
-
if (mainValue?.length) {
|
|
370
|
-
mainCalendarPageInfo = {
|
|
371
|
-
year: getDateTimeInfoByType(mainValue, 'year'),
|
|
372
|
-
month: getDateTimeInfoByType(mainValue, 'month'),
|
|
373
|
-
hour: Math.floor(getDateTimeInfoByType(mainValue, 'hour') / CELL_CNT_IN_ONE_PAGE) + 1 || 1,
|
|
374
|
-
min: Math.floor(getDateTimeInfoByType(mainValue, 'min') / CELL_CNT_IN_ONE_PAGE) + 1 || 1,
|
|
375
|
-
sec: Math.floor(getDateTimeInfoByType(mainValue, 'sec') / CELL_CNT_IN_ONE_PAGE) + 1 || 1,
|
|
376
|
-
};
|
|
377
|
-
} else {
|
|
378
|
-
mainCalendarPageInfo = {
|
|
379
|
-
year: new Date().getFullYear(),
|
|
380
|
-
month: new Date().getMonth() + 1,
|
|
381
|
-
hour: 1,
|
|
382
|
-
min: 1,
|
|
383
|
-
sec: 1,
|
|
384
|
-
};
|
|
385
|
-
}
|
|
386
|
-
|
|
387
|
-
// 'mode: dateRange || dateTimeRange', 인 경우 확장된 달력(연, 월) 페이징 정보
|
|
388
|
-
let expandedCalendarPageInfo;
|
|
389
|
-
if ((['dateRange', 'dateTimeRange'].includes(props.mode))
|
|
390
|
-
&& Array.isArray(selectedValue.value)
|
|
391
|
-
&& selectedValue.value[1]
|
|
392
|
-
) {
|
|
393
|
-
const expandedValue = selectedValue.value[1];
|
|
394
|
-
expandedCalendarPageInfo = {
|
|
395
|
-
year: getDateTimeInfoByType(expandedValue, 'year'),
|
|
396
|
-
month: getDateTimeInfoByType(expandedValue, 'month'),
|
|
397
|
-
};
|
|
398
|
-
|
|
399
|
-
if (props.mode === 'dateTimeRange') {
|
|
400
|
-
expandedCalendarPageInfo.hour = Math.floor(getDateTimeInfoByType(expandedValue, 'hour') / CELL_CNT_IN_ONE_PAGE) + 1 || 1;
|
|
401
|
-
expandedCalendarPageInfo.min = Math.floor(getDateTimeInfoByType(expandedValue, 'min') / CELL_CNT_IN_ONE_PAGE) + 1 || 1;
|
|
402
|
-
expandedCalendarPageInfo.sec = Math.floor(getDateTimeInfoByType(expandedValue, 'sec') / CELL_CNT_IN_ONE_PAGE) + 1 || 1;
|
|
403
|
-
}
|
|
404
|
-
} else {
|
|
405
|
-
expandedCalendarPageInfo = {
|
|
406
|
-
year: new Date().getFullYear(),
|
|
407
|
-
month: new Date().getMonth() + 1,
|
|
408
|
-
hour: 1,
|
|
409
|
-
min: 1,
|
|
410
|
-
sec: 1,
|
|
411
|
-
};
|
|
412
|
-
}
|
|
413
|
-
|
|
414
|
-
// 현재, 다음 달력(연, 월, 시, 분, 초) 페이징 정보
|
|
415
|
-
const calendarPageInfo = reactive({
|
|
416
|
-
main: mainCalendarPageInfo,
|
|
417
|
-
expanded: expandedCalendarPageInfo,
|
|
418
|
-
});
|
|
419
|
-
|
|
420
|
-
// 현재, 다음 달력 년도 목록 정보
|
|
421
|
-
const calendarYearRangeInfo = reactive({
|
|
422
|
-
main: computed(() => getYearRange(calendarPageInfo.main.year)),
|
|
423
|
-
expanded: computed(() => getYearRange(calendarPageInfo.expanded.year)),
|
|
424
|
-
});
|
|
425
|
-
|
|
426
|
-
// 현재 달력이 표현되는 월
|
|
427
|
-
const mainCalendarMonth = computed(() =>
|
|
428
|
-
MONTH_NAME_LIST[props.monthNotation][calendarPageInfo.main.month - 1]);
|
|
429
|
-
// 다음페이지 달력이 표현되는 월
|
|
430
|
-
const expandedCalendarMonth = computed(() =>
|
|
431
|
-
MONTH_NAME_LIST[props.monthNotation][calendarPageInfo.expanded.month - 1]);
|
|
432
|
-
|
|
433
|
-
// 현재, 다음 달력에 표현되는 월 정보
|
|
434
|
-
const calendarMonth = reactive({
|
|
435
|
-
main: mainCalendarMonth,
|
|
436
|
-
expanded: expandedCalendarMonth,
|
|
437
|
-
});
|
|
438
|
-
|
|
439
|
-
// 현재 달력에 표현되는 타입별 요일
|
|
440
|
-
const dayOfTheWeekList = computed(() =>
|
|
441
|
-
DAY_OF_THE_WEEK_NAME_LIST[props.dayOfTheWeekNotation]);
|
|
442
|
-
// mode: dateRange에 두 달력이 연속적인 경우
|
|
443
|
-
// const isContinuousMonths = computed(
|
|
444
|
-
// () => ['dateRange', 'dateTimeRange'].includes(props.mode)
|
|
445
|
-
// && (mainCalendarPageInfo.year === expandedCalendarPageInfo.year
|
|
446
|
-
// && mainCalendarPageInfo.month === expandedCalendarPageInfo.month),
|
|
447
|
-
// );
|
|
448
|
-
|
|
449
|
-
// Calendar 선택 type ('date' | 'month' | 'year')
|
|
450
|
-
const selectedListType = reactive({
|
|
451
|
-
main: LIST_TYPE.DATE,
|
|
452
|
-
expanded: LIST_TYPE.DATE,
|
|
453
|
-
});
|
|
454
|
-
|
|
455
|
-
onBeforeMount(() => {
|
|
456
|
-
validateModelValue();
|
|
457
|
-
});
|
|
458
|
-
|
|
459
|
-
return {
|
|
460
|
-
calendarList,
|
|
461
|
-
selectedValue,
|
|
462
|
-
calendarPageInfo,
|
|
463
|
-
calendarYearRangeInfo,
|
|
464
|
-
calendarMonth,
|
|
465
|
-
dayOfTheWeekList,
|
|
466
|
-
selectedListType,
|
|
467
|
-
// isContinuousMonths,
|
|
468
|
-
};
|
|
469
|
-
};
|
|
470
|
-
|
|
471
|
-
export const useCalendarDate = (param) => {
|
|
472
|
-
const { props } = getCurrentInstance();
|
|
473
|
-
const { selectedValue, calendarPageInfo, calendarYearRangeInfo } = param;
|
|
474
|
-
|
|
475
|
-
// 달력 테이블의 년도 정보 (5X4, 2차원 배열)
|
|
476
|
-
const calendarYearTableInfo = reactive({
|
|
477
|
-
main: getMatrixArr(CALENDAR_YEAR_ROWS, CALENDAR_YEAR_COLS),
|
|
478
|
-
expanded: getMatrixArr(CALENDAR_YEAR_ROWS, CALENDAR_YEAR_COLS),
|
|
479
|
-
});
|
|
480
|
-
|
|
481
|
-
// 달력 테이블의 월 정보 (4X3, 2차원 배열)
|
|
482
|
-
const calendarMonthTableInfo = reactive({
|
|
483
|
-
main: getMatrixArr(CALENDAR_MONTH_ROWS, CALENDAR_MONTH_COLS),
|
|
484
|
-
expanded: getMatrixArr(CALENDAR_MONTH_ROWS, CALENDAR_MONTH_COLS),
|
|
485
|
-
});
|
|
486
|
-
|
|
487
|
-
// 달력 테이블의 날짜 정보 (6X7, 2차원배열)
|
|
488
|
-
const calendarTableInfo = reactive({
|
|
489
|
-
main: getMatrixArr(CALENDAR_ROWS, CALENDAR_COLS),
|
|
490
|
-
expanded: getMatrixArr(CALENDAR_ROWS, CALENDAR_COLS),
|
|
491
|
-
});
|
|
492
|
-
// 시간박스 정보
|
|
493
|
-
const calendarTimeTableInfo = reactive({
|
|
494
|
-
main: {
|
|
495
|
-
hour: [],
|
|
496
|
-
min: [],
|
|
497
|
-
sec: [],
|
|
498
|
-
},
|
|
499
|
-
expanded: {
|
|
500
|
-
hour: [],
|
|
501
|
-
min: [],
|
|
502
|
-
sec: [],
|
|
503
|
-
},
|
|
504
|
-
});
|
|
505
|
-
|
|
506
|
-
/**
|
|
507
|
-
* Calendar 년도 정보 세팅하기
|
|
508
|
-
* @param calendarType - 달력 종류 ('main'|'expanded')
|
|
509
|
-
*/
|
|
510
|
-
const setCalendarYear = (calendarType) => {
|
|
511
|
-
let yearValue = calendarYearRangeInfo[calendarType].start;
|
|
512
|
-
const thisYear = new Date().getFullYear();
|
|
513
|
-
const minYear = new Date(MIN_DATE_MS).getFullYear();
|
|
514
|
-
for (let i = 0; i < CALENDAR_YEAR_ROWS; i++) {
|
|
515
|
-
for (let j = 0; j < CALENDAR_YEAR_COLS; j++) {
|
|
516
|
-
calendarYearTableInfo[calendarType][i][j] = {
|
|
517
|
-
label: yearValue,
|
|
518
|
-
value: yearValue,
|
|
519
|
-
today: yearValue === thisYear,
|
|
520
|
-
isSelected: yearValue === calendarPageInfo[calendarType].year,
|
|
521
|
-
disabled: (yearValue < minYear),
|
|
522
|
-
};
|
|
523
|
-
yearValue++;
|
|
524
|
-
}
|
|
525
|
-
}
|
|
526
|
-
};
|
|
527
|
-
|
|
528
|
-
/**
|
|
529
|
-
* Calendar 월 정보 세팅하기
|
|
530
|
-
* @param calendarType - 달력 종류 ('main'|'expanded')
|
|
531
|
-
*/
|
|
532
|
-
const setCalendarMonth = (calendarType) => {
|
|
533
|
-
let monthValue = 0;
|
|
534
|
-
const todayYear = new Date().getFullYear();
|
|
535
|
-
const todayMonth = new Date().getMonth() + 1;
|
|
536
|
-
const { year: currentYear, month: currentMonth } = calendarPageInfo[calendarType];
|
|
537
|
-
for (let i = 0; i < CALENDAR_MONTH_ROWS; i++) {
|
|
538
|
-
for (let j = 0; j < CALENDAR_MONTH_COLS; j++) {
|
|
539
|
-
calendarMonthTableInfo[calendarType][i][j] = {
|
|
540
|
-
label: MONTH_NAME_LIST.abbrName[monthValue++],
|
|
541
|
-
value: monthValue,
|
|
542
|
-
today: currentYear === todayYear
|
|
543
|
-
&& monthValue === todayMonth,
|
|
544
|
-
isSelected: monthValue === currentMonth,
|
|
545
|
-
};
|
|
546
|
-
}
|
|
547
|
-
}
|
|
548
|
-
};
|
|
549
|
-
|
|
550
|
-
/**
|
|
551
|
-
* Dropdown Calendar 날짜 정보 세팅하기
|
|
552
|
-
* @param calendarType - 달력 종류 ('main'|'expanded')
|
|
553
|
-
*/
|
|
554
|
-
const setCalendarDate = (calendarType) => {
|
|
555
|
-
const pageInfo = calendarPageInfo[calendarType];
|
|
556
|
-
let disabledDate = props.options.disabledDate;
|
|
557
|
-
if (disabledDate && Array.isArray(disabledDate)) {
|
|
558
|
-
disabledDate = calendarType === 'main' ? disabledDate[0] : disabledDate[1];
|
|
559
|
-
}
|
|
560
|
-
const isRangeMode = ['dateRange', 'dateTimeRange'].includes(props.mode);
|
|
561
|
-
|
|
562
|
-
const TODAY_YMD = formatDateTime({
|
|
563
|
-
year: new Date().getFullYear(),
|
|
564
|
-
month: new Date().getMonth() + 1,
|
|
565
|
-
date: new Date().getDate(),
|
|
566
|
-
});
|
|
567
|
-
const PREV_MONTH = ((MONTH_CNT + pageInfo.month - 1) % MONTH_CNT) || MONTH_CNT;
|
|
568
|
-
const NEXT_MONTH = ((pageInfo.month + 1) % MONTH_CNT) || MONTH_CNT;
|
|
569
|
-
const YEAR_OF_PREV_MONTH = (pageInfo.month === 1
|
|
570
|
-
? pageInfo.year - 1 : pageInfo.year);
|
|
571
|
-
const YEAR_OF_NEXT_MONTH = pageInfo.month === 12
|
|
572
|
-
? pageInfo.year + 1 : pageInfo.year;
|
|
573
|
-
// 이번달 1일의 요일
|
|
574
|
-
const dayOfWeekOnThe1stOfThisMonth = getDayOfWeekOnThe1stOfMonth(
|
|
575
|
-
pageInfo.year,
|
|
576
|
-
pageInfo.month,
|
|
577
|
-
);
|
|
578
|
-
// 저번달 마지막 날짜
|
|
579
|
-
const lastDateOfPrevMonth = getLastDateOfMonth(
|
|
580
|
-
pageInfo.month === 1
|
|
581
|
-
? pageInfo.year - 1 : pageInfo.year,
|
|
582
|
-
(MONTH_CNT + pageInfo.month - 1) % MONTH_CNT || MONTH_CNT,
|
|
583
|
-
);
|
|
584
|
-
// 이번달 마지막 날짜
|
|
585
|
-
const lastDateOfThisMonth = getLastDateOfMonth(
|
|
586
|
-
pageInfo.year,
|
|
587
|
-
pageInfo.month,
|
|
588
|
-
);
|
|
589
|
-
|
|
590
|
-
let modelValue = '';
|
|
591
|
-
if (props.mode.includes('Time')) {
|
|
592
|
-
if (props.mode === 'dateTime') {
|
|
593
|
-
modelValue = selectedValue.value;
|
|
594
|
-
} else {
|
|
595
|
-
modelValue = calendarType === 'main' ? selectedValue.value[0] : selectedValue.value[1];
|
|
596
|
-
}
|
|
597
|
-
}
|
|
598
|
-
|
|
599
|
-
let monthDate = 0;
|
|
600
|
-
let year = 0;
|
|
601
|
-
let month = 0;
|
|
602
|
-
let date = 0;
|
|
603
|
-
let currDate = '';
|
|
604
|
-
// date 숫자 및 속성 세팅
|
|
605
|
-
const setDateInfo = (monthType, i, j) => {
|
|
606
|
-
currDate = formatDateTime({ year, month, date });
|
|
607
|
-
|
|
608
|
-
// time 모드인 경우 현재 값의 시간을 가지고 테스트
|
|
609
|
-
const timeValue = modelValue?.split(' ')[1] ?? '';
|
|
610
|
-
|
|
611
|
-
// range 모드인 경우 from 날짜가 to 날짜를 넘는지 확인 || 최소 날짜보다 이전 날짜인지 확인
|
|
612
|
-
const isInvalidDate = (isRangeMode && !disabledDate
|
|
613
|
-
&& compareFromAndToDateTime(props.mode, calendarType, currDate, selectedValue.value))
|
|
614
|
-
|| (+new Date(`${currDate} ${timeValue}`) < MIN_DATE_MS);
|
|
615
|
-
|
|
616
|
-
const isDisabled = (disabledDate && disabledDate(new Date(`${currDate} ${timeValue}`)))
|
|
617
|
-
|| isInvalidDate;
|
|
618
|
-
|
|
619
|
-
const index = +(calendarType !== 'main');
|
|
620
|
-
const isRangeSelected = isRangeMode && selectedValue.value.length > index
|
|
621
|
-
&& selectedValue.value?.[index]?.includes(currDate);
|
|
622
|
-
const isSelected = !isDisabled
|
|
623
|
-
&& (isRangeMode ? isRangeSelected : selectedValue.value?.includes(currDate));
|
|
624
|
-
|
|
625
|
-
// mode가 dateRange일 때는 이전, 다음달에 selected 를 하지 않는다.
|
|
626
|
-
calendarTableInfo[calendarType][i][j] = {
|
|
627
|
-
monthType: `${monthType}${isDisabled ? ' disabled' : ''}`,
|
|
628
|
-
isToday: TODAY_YMD === currDate,
|
|
629
|
-
isSelected,
|
|
630
|
-
year,
|
|
631
|
-
month,
|
|
632
|
-
date,
|
|
633
|
-
};
|
|
634
|
-
};
|
|
635
|
-
|
|
636
|
-
for (let i = 0; i < CALENDAR_ROWS; i++) {
|
|
637
|
-
for (let j = 0; j < CALENDAR_COLS; j++) {
|
|
638
|
-
if (i === 0) {
|
|
639
|
-
// 첫번째 주
|
|
640
|
-
if (dayOfWeekOnThe1stOfThisMonth !== 0) {
|
|
641
|
-
if (j < dayOfWeekOnThe1stOfThisMonth) {
|
|
642
|
-
year = YEAR_OF_PREV_MONTH;
|
|
643
|
-
month = PREV_MONTH;
|
|
644
|
-
date = lastDateOfPrevMonth - dayOfWeekOnThe1stOfThisMonth + 1 + j;
|
|
645
|
-
setDateInfo('prev', i, j);
|
|
646
|
-
} else {
|
|
647
|
-
monthDate++;
|
|
648
|
-
year = pageInfo.year;
|
|
649
|
-
month = pageInfo.month;
|
|
650
|
-
date = monthDate;
|
|
651
|
-
setDateInfo('', i, j);
|
|
652
|
-
}
|
|
653
|
-
} else {
|
|
654
|
-
year = YEAR_OF_PREV_MONTH;
|
|
655
|
-
month = PREV_MONTH;
|
|
656
|
-
date = lastDateOfPrevMonth - 6 + j;
|
|
657
|
-
setDateInfo('prev', i, j);
|
|
658
|
-
}
|
|
659
|
-
} else if (lastDateOfThisMonth <= monthDate) {
|
|
660
|
-
// 마지막 -1, 마지막 주의 다음달 날짜
|
|
661
|
-
monthDate++;
|
|
662
|
-
year = YEAR_OF_NEXT_MONTH;
|
|
663
|
-
month = NEXT_MONTH;
|
|
664
|
-
date = monthDate - lastDateOfThisMonth;
|
|
665
|
-
setDateInfo('next', i, j);
|
|
666
|
-
} else {
|
|
667
|
-
// 첫번째 주를 제외한 이번달 날짜
|
|
668
|
-
monthDate++;
|
|
669
|
-
year = pageInfo.year;
|
|
670
|
-
month = pageInfo.month;
|
|
671
|
-
date = monthDate;
|
|
672
|
-
setDateInfo('', i, j);
|
|
673
|
-
}
|
|
674
|
-
}
|
|
675
|
-
}
|
|
676
|
-
};
|
|
677
|
-
|
|
678
|
-
/**
|
|
679
|
-
* Calendar 시간 정보 세팅하기
|
|
680
|
-
*/
|
|
681
|
-
const setHmsTime = () => {
|
|
682
|
-
const timeFormat = props.options?.timeFormat;
|
|
683
|
-
const disabledDate = props.options?.disabledDate;
|
|
684
|
-
const mainTimeFormat = Array.isArray(timeFormat) ? timeFormat[0] : timeFormat;
|
|
685
|
-
const expandedTimeFormat = Array.isArray(timeFormat) ? timeFormat[1] : '';
|
|
686
|
-
const mainDateTimeValue = props.mode === 'dateTimeRange' ? selectedValue.value[0] : selectedValue.value;
|
|
687
|
-
const expandedDateTimeValue = props.mode === 'dateTimeRange' ? selectedValue.value[1] : '';
|
|
688
|
-
const mainDisabledDate = Array.isArray(disabledDate) ? disabledDate[0] : disabledDate;
|
|
689
|
-
const expandedDisabledDate = Array.isArray(disabledDate) ? disabledDate[1] : disabledDate;
|
|
690
|
-
|
|
691
|
-
const compareDateTimeValue = (calendarType, timeType, value) => {
|
|
692
|
-
const dateTimeValue = calendarType === 'main' ? mainDateTimeValue : expandedDateTimeValue;
|
|
693
|
-
const disabledDateFunc = calendarType === 'main' ? mainDisabledDate : expandedDisabledDate;
|
|
694
|
-
if (!dateTimeValue) {
|
|
695
|
-
return false;
|
|
696
|
-
}
|
|
697
|
-
|
|
698
|
-
const date = dateTimeValue.split(' ')[0];
|
|
699
|
-
let hour = getDateTimeInfoByType(dateTimeValue, 'hour');
|
|
700
|
-
let min = getDateTimeInfoByType(dateTimeValue, 'min');
|
|
701
|
-
let sec = getDateTimeInfoByType(dateTimeValue, 'sec');
|
|
702
|
-
|
|
703
|
-
if (timeType === 'hour') {
|
|
704
|
-
hour = value;
|
|
705
|
-
} else if (timeType === 'min') {
|
|
706
|
-
min = value;
|
|
707
|
-
} else if (timeType === 'sec') {
|
|
708
|
-
sec = value;
|
|
709
|
-
}
|
|
710
|
-
|
|
711
|
-
const targetDateTimeValue = `${date} ${lpadToTwoDigits(hour)}:${lpadToTwoDigits(min)}:${lpadToTwoDigits(sec)}`;
|
|
712
|
-
if (disabledDateFunc && disabledDateFunc(new Date(targetDateTimeValue))) {
|
|
713
|
-
return true;
|
|
714
|
-
}
|
|
715
|
-
|
|
716
|
-
return !disabledDateFunc && compareFromAndToDateTime(
|
|
717
|
-
props.mode,
|
|
718
|
-
calendarType,
|
|
719
|
-
targetDateTimeValue,
|
|
720
|
-
selectedValue.value,
|
|
721
|
-
);
|
|
722
|
-
};
|
|
723
|
-
|
|
724
|
-
['hour', 'min', 'sec'].forEach((v) => {
|
|
725
|
-
let cnt = SEC_CNT;
|
|
726
|
-
if (v === 'hour') {
|
|
727
|
-
cnt = HOUR_CNT;
|
|
728
|
-
} else if (v === 'min') {
|
|
729
|
-
cnt = MIN_CNT;
|
|
730
|
-
}
|
|
731
|
-
const mainTimeValue = mainDateTimeValue && mainDateTimeValue.length > 0
|
|
732
|
-
? getTimeInfoByTimeFormat(mainTimeFormat, mainDateTimeValue, v) : -1;
|
|
733
|
-
const expandedTimeValue = expandedDateTimeValue && expandedDateTimeValue.length > 0
|
|
734
|
-
? getTimeInfoByTimeFormat(expandedTimeFormat, expandedDateTimeValue, v) : -1;
|
|
735
|
-
for (let i = 0; i < cnt; i++) {
|
|
736
|
-
let isDisabled = props.mode === 'dateTimeRange' && compareDateTimeValue('main', v, i);
|
|
737
|
-
calendarTimeTableInfo.main[v][i] = {
|
|
738
|
-
timeType: v,
|
|
739
|
-
num: i,
|
|
740
|
-
isSelected: !isDisabled && mainTimeValue === i,
|
|
741
|
-
isDisabled,
|
|
742
|
-
};
|
|
743
|
-
if (props.mode === 'dateTimeRange') {
|
|
744
|
-
isDisabled = compareDateTimeValue('expanded', v, i);
|
|
745
|
-
calendarTimeTableInfo.expanded[v][i] = {
|
|
746
|
-
timeType: v,
|
|
747
|
-
num: i,
|
|
748
|
-
isSelected: !isDisabled && expandedTimeValue === i,
|
|
749
|
-
isDisabled,
|
|
750
|
-
};
|
|
751
|
-
}
|
|
752
|
-
}
|
|
753
|
-
});
|
|
754
|
-
};
|
|
755
|
-
|
|
756
|
-
/**
|
|
757
|
-
* HMS 영역 내 tr, td, 페이지에 맞는 시간 정보 가져오기
|
|
758
|
-
* @param timeType - {'hour'|'min'|'sec'}
|
|
759
|
-
* @param i - rows
|
|
760
|
-
* @param j - cols
|
|
761
|
-
* @param calendarType - {'main'|'expanded'}
|
|
762
|
-
* @returns {object} - cellInfo
|
|
763
|
-
*/
|
|
764
|
-
const getTimeInfo = (timeType, i, j, calendarType) => {
|
|
765
|
-
const pageInfo = calendarPageInfo[calendarType];
|
|
766
|
-
const timeInfo = calendarTimeTableInfo[calendarType];
|
|
767
|
-
const currPage = pageInfo[timeType] - 1;
|
|
768
|
-
const currRowIdx = i - 1;
|
|
769
|
-
const currColIdx = j - 1;
|
|
770
|
-
const currIdx = (currPage * CELL_CNT_IN_ONE_PAGE)
|
|
771
|
-
+ (currRowIdx * CELL_CNT_IN_ONE_ROW) + currColIdx;
|
|
772
|
-
return timeInfo[timeType][currIdx];
|
|
773
|
-
};
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
return {
|
|
777
|
-
calendarTableInfo,
|
|
778
|
-
calendarMonthTableInfo,
|
|
779
|
-
calendarYearTableInfo,
|
|
780
|
-
calendarTimeTableInfo,
|
|
781
|
-
setCalendarDate,
|
|
782
|
-
setCalendarMonth,
|
|
783
|
-
setCalendarYear,
|
|
784
|
-
setHmsTime,
|
|
785
|
-
getTimeInfo,
|
|
786
|
-
};
|
|
787
|
-
};
|
|
788
|
-
|
|
789
|
-
export const useEvent = (param) => {
|
|
790
|
-
const { props, emit } = getCurrentInstance();
|
|
791
|
-
const timeFormat = props.options?.timeFormat;
|
|
792
|
-
const {
|
|
793
|
-
selectedValue,
|
|
794
|
-
calendarPageInfo,
|
|
795
|
-
calendarTimeTableInfo,
|
|
796
|
-
setCalendarDate,
|
|
797
|
-
setCalendarMonth,
|
|
798
|
-
setCalendarYear,
|
|
799
|
-
setHmsTime,
|
|
800
|
-
selectedListType,
|
|
801
|
-
} = param;
|
|
802
|
-
|
|
803
|
-
// dateRange mode에서 클릭하여 첫번째 선택된 날짜
|
|
804
|
-
const dateRangeClickedDate = ref('');
|
|
805
|
-
// dateRange mode에서 클릭한번 후 커서에 따라 날짜를 마우스오버하는 경우 dynamic argument로 이벤트명 설정
|
|
806
|
-
const calendarEventName = ref(null);
|
|
807
|
-
// dateTime 또는 dateTimeRange에서 timeFormat이 있는 경우 event 막음
|
|
808
|
-
const mainTimeFormat = Array.isArray(timeFormat) ? timeFormat[0] : timeFormat;
|
|
809
|
-
const expandedTimeFormat = Array.isArray(timeFormat) ? timeFormat[1] : '';
|
|
810
|
-
const preventTimeEventType = {
|
|
811
|
-
main: {
|
|
812
|
-
hour: mainTimeFormat && mainTimeFormat.split(':')[0] !== 'HH',
|
|
813
|
-
min: mainTimeFormat && mainTimeFormat.split(':')[1] !== 'mm',
|
|
814
|
-
sec: mainTimeFormat && mainTimeFormat.split(':')[2] !== 'ss',
|
|
815
|
-
},
|
|
816
|
-
expanded: {
|
|
817
|
-
hour: expandedTimeFormat && expandedTimeFormat.split(':')[0] !== 'HH',
|
|
818
|
-
min: expandedTimeFormat && expandedTimeFormat.split(':')[1] !== 'mm',
|
|
819
|
-
sec: expandedTimeFormat && expandedTimeFormat.split(':')[2] !== 'ss',
|
|
820
|
-
},
|
|
821
|
-
};
|
|
822
|
-
|
|
823
|
-
/**
|
|
824
|
-
* 입력받은 dateTime object에 calendar date, time 영역 페이지 세팅
|
|
825
|
-
* @param calendarType - 달력 종류 ('main'|'expanded')
|
|
826
|
-
* @param dateTime - 입력된 페이지 정보 ({ year, month, hour, min, sec })
|
|
827
|
-
*/
|
|
828
|
-
const setCalendarPageInfo = (calendarType, dateTime) => {
|
|
829
|
-
const pageInfo = calendarPageInfo[calendarType];
|
|
830
|
-
const { year, month, hour, min, sec } = dateTime;
|
|
831
|
-
if (year) {
|
|
832
|
-
pageInfo.year = year;
|
|
833
|
-
}
|
|
834
|
-
if (month) {
|
|
835
|
-
pageInfo.month = month;
|
|
836
|
-
}
|
|
837
|
-
if (hour) {
|
|
838
|
-
pageInfo.hour = hour;
|
|
839
|
-
}
|
|
840
|
-
if (min) {
|
|
841
|
-
pageInfo.min = min;
|
|
842
|
-
}
|
|
843
|
-
if (sec) {
|
|
844
|
-
pageInfo.sec = sec;
|
|
845
|
-
}
|
|
846
|
-
};
|
|
847
|
-
|
|
848
|
-
/**
|
|
849
|
-
* value를 Array로 담아 페이지 세팅
|
|
850
|
-
* @param valueList
|
|
851
|
-
*/
|
|
852
|
-
const updateCalendarPage = (valueList) => {
|
|
853
|
-
valueList?.forEach((currValue, index) => {
|
|
854
|
-
const changeCalendarType = index === 0 ? 'main' : 'expanded';
|
|
855
|
-
setCalendarPageInfo(changeCalendarType, {
|
|
856
|
-
year: getDateTimeInfoByType(currValue, 'year'),
|
|
857
|
-
month: getDateTimeInfoByType(currValue, 'month'),
|
|
858
|
-
hour: Math.floor(getDateTimeInfoByType(currValue, 'hour') / CELL_CNT_IN_ONE_PAGE) + 1,
|
|
859
|
-
min: Math.floor(getDateTimeInfoByType(currValue, 'min') / CELL_CNT_IN_ONE_PAGE) + 1,
|
|
860
|
-
sec: Math.floor(getDateTimeInfoByType(currValue, 'sec') / CELL_CNT_IN_ONE_PAGE) + 1,
|
|
861
|
-
});
|
|
862
|
-
setCalendarDate(changeCalendarType);
|
|
863
|
-
});
|
|
864
|
-
};
|
|
865
|
-
|
|
866
|
-
/**
|
|
867
|
-
* Calendar 의 year 이동시키기 (이전, 이후)
|
|
868
|
-
* @param calendarType
|
|
869
|
-
* @param type
|
|
870
|
-
*/
|
|
871
|
-
const moveYear = (calendarType, type) => {
|
|
872
|
-
const increaseValue = selectedListType[calendarType] === LIST_TYPE.MONTH ? 1 : 20;
|
|
873
|
-
const offset = type === 'prev' ? -increaseValue : increaseValue;
|
|
874
|
-
const minYear = new Date(MIN_DATE_MS).getFullYear();
|
|
875
|
-
const movedYear = calendarPageInfo[calendarType].year + offset;
|
|
876
|
-
calendarPageInfo[calendarType].year = (movedYear < minYear) ? minYear : movedYear;
|
|
877
|
-
};
|
|
878
|
-
|
|
879
|
-
/**
|
|
880
|
-
* Calendar 의 Month 이동시키기 (이전, 이후)
|
|
881
|
-
* @param calendarType - 달력 종류 ('main'|'expanded')
|
|
882
|
-
* @param type - {'prev'|'next'}
|
|
883
|
-
*/
|
|
884
|
-
const moveMonth = (calendarType, type) => {
|
|
885
|
-
const pageInfo = calendarPageInfo[calendarType];
|
|
886
|
-
|
|
887
|
-
if (type === 'prev') {
|
|
888
|
-
const minYear = new Date(MIN_DATE_MS).getFullYear();
|
|
889
|
-
if (pageInfo.year === minYear && pageInfo.month === 1) {
|
|
890
|
-
return;
|
|
891
|
-
}
|
|
892
|
-
if (pageInfo.month === 1) {
|
|
893
|
-
pageInfo.year -= 1;
|
|
894
|
-
pageInfo.month = 12;
|
|
895
|
-
} else {
|
|
896
|
-
pageInfo.month -= 1;
|
|
897
|
-
}
|
|
898
|
-
} else if (pageInfo.month === 12) {
|
|
899
|
-
pageInfo.year += 1;
|
|
900
|
-
pageInfo.month = 1;
|
|
901
|
-
} else {
|
|
902
|
-
pageInfo.month += 1;
|
|
903
|
-
}
|
|
904
|
-
};
|
|
905
|
-
|
|
906
|
-
/**
|
|
907
|
-
* Calendar Header의 prev, next 아이콘 클릭 이벤트
|
|
908
|
-
* @param calendarType - 달력 종류 ('main'|'expanded')
|
|
909
|
-
* @param type - 이전달, 다음달 ('prev'|'next')
|
|
910
|
-
*/
|
|
911
|
-
const clickPrevNextBtn = (calendarType, type) => {
|
|
912
|
-
const listType = selectedListType[calendarType];
|
|
913
|
-
switch (listType) {
|
|
914
|
-
case LIST_TYPE.DATE: {
|
|
915
|
-
moveMonth(calendarType, type);
|
|
916
|
-
setCalendarDate(calendarType);
|
|
917
|
-
break;
|
|
918
|
-
}
|
|
919
|
-
case LIST_TYPE.MONTH:
|
|
920
|
-
moveYear(calendarType, type);
|
|
921
|
-
setCalendarMonth(calendarType);
|
|
922
|
-
break;
|
|
923
|
-
case LIST_TYPE.YEAR:
|
|
924
|
-
moveYear(calendarType, type);
|
|
925
|
-
setCalendarYear(calendarType);
|
|
926
|
-
break;
|
|
927
|
-
default:
|
|
928
|
-
break;
|
|
929
|
-
}
|
|
930
|
-
};
|
|
931
|
-
|
|
932
|
-
/**
|
|
933
|
-
* Calendar Header 의 year, month 버튼 클릭 이벤트
|
|
934
|
-
* @param calendarType - 달력 종류 ('main'|'expanded')
|
|
935
|
-
* @param type - 클릭 정보 ('year' | 'month')
|
|
936
|
-
*/
|
|
937
|
-
const clickYearMonthBtn = (calendarType, type) => {
|
|
938
|
-
if (type === LIST_TYPE.DATE) {
|
|
939
|
-
setCalendarDate(calendarType);
|
|
940
|
-
} else if (type === LIST_TYPE.MONTH) {
|
|
941
|
-
setCalendarMonth(calendarType);
|
|
942
|
-
} else if (type === LIST_TYPE.YEAR) {
|
|
943
|
-
setCalendarYear(calendarType);
|
|
944
|
-
}
|
|
945
|
-
selectedListType[calendarType] = type;
|
|
946
|
-
};
|
|
947
|
-
|
|
948
|
-
/**
|
|
949
|
-
* Calendar year, month 클릭 이벤트
|
|
950
|
-
* @param calendarType - 달력 종류 ('main'|'expanded')
|
|
951
|
-
* @param clickedInfo - 클릭 정보
|
|
952
|
-
*/
|
|
953
|
-
const clickYearMonth = (calendarType, clickedInfo) => {
|
|
954
|
-
const { value } = clickedInfo;
|
|
955
|
-
|
|
956
|
-
if (clickedInfo.disabled) {
|
|
957
|
-
return;
|
|
958
|
-
}
|
|
959
|
-
|
|
960
|
-
if (selectedListType[calendarType] === LIST_TYPE.YEAR) {
|
|
961
|
-
calendarPageInfo[calendarType].year = value;
|
|
962
|
-
selectedListType[calendarType] = LIST_TYPE.MONTH;
|
|
963
|
-
setCalendarMonth(calendarType);
|
|
964
|
-
} else {
|
|
965
|
-
calendarPageInfo[calendarType].month = value;
|
|
966
|
-
selectedListType[calendarType] = LIST_TYPE.DATE;
|
|
967
|
-
setCalendarDate(calendarType);
|
|
968
|
-
}
|
|
969
|
-
};
|
|
970
|
-
|
|
971
|
-
/**
|
|
972
|
-
* Calendar Date 일자 클릭 이벤트
|
|
973
|
-
* @param calendarType - {main|expanded}
|
|
974
|
-
* @param dateInfo
|
|
975
|
-
*/
|
|
976
|
-
const clickDate = (calendarType, dateInfo) => {
|
|
977
|
-
const { year, month, date, monthType } = dateInfo;
|
|
978
|
-
const CURR_DATE_STR = formatDateTime({ year, month, date });
|
|
979
|
-
const isExistCurrDate = props.modelValue ? (Array.isArray(props.modelValue)
|
|
980
|
-
? props.modelValue?.map(v => v.split(' ')[0])
|
|
981
|
-
: props.modelValue.split(' ')[0])
|
|
982
|
-
.includes(CURR_DATE_STR) : false;
|
|
983
|
-
|
|
984
|
-
let disabledDate = props.options.disabledDate;
|
|
985
|
-
if (disabledDate && Array.isArray(disabledDate)) {
|
|
986
|
-
disabledDate = calendarType === 'main' ? disabledDate[0] : disabledDate[1];
|
|
987
|
-
}
|
|
988
|
-
// 제한된 날짜는 선택할 수 없다.
|
|
989
|
-
if (disabledDate && disabledDate(new Date(CURR_DATE_STR)) && !isExistCurrDate) {
|
|
990
|
-
return;
|
|
991
|
-
} else if (!disabledDate && ['dateRange', 'dateTimeRange'].includes(props.mode)
|
|
992
|
-
&& compareFromAndToDateTime(props.mode, calendarType, CURR_DATE_STR, selectedValue.value)) {
|
|
993
|
-
return;
|
|
994
|
-
}
|
|
995
|
-
|
|
996
|
-
const pageInfo = calendarPageInfo[calendarType];
|
|
997
|
-
const PREV_MONTH = ((MONTH_CNT + pageInfo.month - 1) % MONTH_CNT) || MONTH_CNT;
|
|
998
|
-
const YEAR_OF_PREV_MONTH = pageInfo.month === 1
|
|
999
|
-
? pageInfo.year - 1 : pageInfo.year;
|
|
1000
|
-
const NEXT_MONTH = ((pageInfo.month + 1) % MONTH_CNT) || MONTH_CNT;
|
|
1001
|
-
const YEAR_OF_NEXT_MONTH = pageInfo.month === 12
|
|
1002
|
-
? pageInfo.year + 1 : pageInfo.year;
|
|
1003
|
-
|
|
1004
|
-
const moveDispCalendarMonth = () => {
|
|
1005
|
-
if (monthType.includes('prev')) {
|
|
1006
|
-
pageInfo.year = YEAR_OF_PREV_MONTH;
|
|
1007
|
-
pageInfo.month = PREV_MONTH;
|
|
1008
|
-
} else if (monthType.includes('next')) {
|
|
1009
|
-
pageInfo.year = YEAR_OF_NEXT_MONTH;
|
|
1010
|
-
pageInfo.month = NEXT_MONTH;
|
|
1011
|
-
}
|
|
1012
|
-
};
|
|
1013
|
-
|
|
1014
|
-
switch (props.mode) {
|
|
1015
|
-
case 'date':
|
|
1016
|
-
// moveDispCalendarMonth();
|
|
1017
|
-
emit('update:modelValue', CURR_DATE_STR);
|
|
1018
|
-
break;
|
|
1019
|
-
case 'dateTime': {
|
|
1020
|
-
const isExistTime = !!(selectedValue.value?.split(' ')[1]);
|
|
1021
|
-
const CURR_TIME_HMS = isExistTime
|
|
1022
|
-
? selectedValue.value?.split(' ')[1] : '00:00:00';
|
|
1023
|
-
const changedValueByTimeFormat = getChangedValueByTimeFormat(
|
|
1024
|
-
timeFormat,
|
|
1025
|
-
`${CURR_DATE_STR} ${CURR_TIME_HMS}`,
|
|
1026
|
-
);
|
|
1027
|
-
// moveDispCalendarMonth();
|
|
1028
|
-
emit('update:modelValue', changedValueByTimeFormat);
|
|
1029
|
-
break;
|
|
1030
|
-
}
|
|
1031
|
-
case 'dateMulti': {
|
|
1032
|
-
const multiType = props.options.multiType;
|
|
1033
|
-
const multiDayLimit = props.options.multiDayLimit;
|
|
1034
|
-
if (multiType === 'date') {
|
|
1035
|
-
const selectedIdx = selectedValue.value.indexOf(CURR_DATE_STR);
|
|
1036
|
-
if (selectedIdx > -1) {
|
|
1037
|
-
selectedValue.value.splice(selectedIdx, 1);
|
|
1038
|
-
emit('update:modelValue', [...selectedValue.value]);
|
|
1039
|
-
} else if (selectedValue.value.length < multiDayLimit) {
|
|
1040
|
-
selectedValue.value.push(CURR_DATE_STR);
|
|
1041
|
-
moveDispCalendarMonth();
|
|
1042
|
-
emit('update:modelValue', [...selectedValue.value]);
|
|
1043
|
-
}
|
|
1044
|
-
} else if (multiType === 'week' || multiType === 'weekday') {
|
|
1045
|
-
const NUMBER_OF_DAYS_IN_RANGE = multiType === 'week' ? 7 : 5; // 범위 내 선택된 날짜 개수
|
|
1046
|
-
const DIFF_UNTIL_THE_LAST_DATE = multiType === 'week' ? 6 : 5; // 한 주의 마지막 날짜까지의 차이
|
|
1047
|
-
const exactSelectedDate = new Date(`${CURR_DATE_STR} 00:00:00`);
|
|
1048
|
-
const dayOfTheWeekOfTheSelectedDate = exactSelectedDate.getDay();
|
|
1049
|
-
const diffFromTheLastDay = DIFF_UNTIL_THE_LAST_DATE - dayOfTheWeekOfTheSelectedDate;
|
|
1050
|
-
const theLastDayTime = exactSelectedDate.getTime() + (ONE_DAY_MS * diffFromTheLastDay);
|
|
1051
|
-
|
|
1052
|
-
for (let i = 0; i < NUMBER_OF_DAYS_IN_RANGE; i++) {
|
|
1053
|
-
const loopYear = new Date(theLastDayTime - (i * ONE_DAY_MS)).getFullYear();
|
|
1054
|
-
const loopMonth = new Date(theLastDayTime - (i * ONE_DAY_MS)).getMonth() + 1;
|
|
1055
|
-
const loopDate = new Date(theLastDayTime - (i * ONE_DAY_MS)).getDate();
|
|
1056
|
-
const dateStr = `${loopYear}-${lpadToTwoDigits(loopMonth)}-${lpadToTwoDigits(loopDate)}`;
|
|
1057
|
-
if (i === 0) {
|
|
1058
|
-
if (selectedValue.value.includes(dateStr)) {
|
|
1059
|
-
selectedValue.value.splice(0);
|
|
1060
|
-
break;
|
|
1061
|
-
} else {
|
|
1062
|
-
selectedValue.value.splice(0);
|
|
1063
|
-
moveDispCalendarMonth();
|
|
1064
|
-
}
|
|
1065
|
-
}
|
|
1066
|
-
if (!disabledDate || !disabledDate(new Date(dateStr))) {
|
|
1067
|
-
selectedValue.value.unshift(dateStr);
|
|
1068
|
-
}
|
|
1069
|
-
}
|
|
1070
|
-
emit('update:modelValue', [...selectedValue.value]);
|
|
1071
|
-
}
|
|
1072
|
-
setCalendarDate('main');
|
|
1073
|
-
break;
|
|
1074
|
-
}
|
|
1075
|
-
case 'dateRange': {
|
|
1076
|
-
let changedValue = [...selectedValue.value];
|
|
1077
|
-
if (!selectedValue.value.length) {
|
|
1078
|
-
changedValue = [CURR_DATE_STR, CURR_DATE_STR];
|
|
1079
|
-
} else {
|
|
1080
|
-
const currIndex = +(calendarType === 'expanded');
|
|
1081
|
-
changedValue[currIndex] = CURR_DATE_STR;
|
|
1082
|
-
}
|
|
1083
|
-
emit('update:modelValue', changedValue);
|
|
1084
|
-
break;
|
|
1085
|
-
}
|
|
1086
|
-
case 'dateTimeRange': {
|
|
1087
|
-
let changedValue = [...selectedValue.value];
|
|
1088
|
-
if (!changedValue.length) {
|
|
1089
|
-
let fromDate = `${CURR_DATE_STR} 00:00:00`;
|
|
1090
|
-
let toDate = `${CURR_DATE_STR} 00:00:00`;
|
|
1091
|
-
if (timeFormat && timeFormat.length) {
|
|
1092
|
-
fromDate = getChangedValueByTimeFormat(
|
|
1093
|
-
timeFormat[0],
|
|
1094
|
-
fromDate,
|
|
1095
|
-
);
|
|
1096
|
-
toDate = getChangedValueByTimeFormat(
|
|
1097
|
-
timeFormat[1],
|
|
1098
|
-
toDate,
|
|
1099
|
-
);
|
|
1100
|
-
}
|
|
1101
|
-
changedValue = [fromDate, toDate];
|
|
1102
|
-
} else {
|
|
1103
|
-
const currIndex = +(calendarType === 'expanded');
|
|
1104
|
-
const CURR_TIME_HMS = changedValue[currIndex]?.split(' ')[1] || '00:00:00';
|
|
1105
|
-
let currDate = `${CURR_DATE_STR} ${CURR_TIME_HMS}`;
|
|
1106
|
-
if (timeFormat && timeFormat.length) {
|
|
1107
|
-
currDate = getChangedValueByTimeFormat(
|
|
1108
|
-
timeFormat[currIndex],
|
|
1109
|
-
currDate,
|
|
1110
|
-
);
|
|
1111
|
-
}
|
|
1112
|
-
changedValue[currIndex] = currDate;
|
|
1113
|
-
}
|
|
1114
|
-
emit('update:modelValue', changedValue);
|
|
1115
|
-
break;
|
|
1116
|
-
}
|
|
1117
|
-
default:
|
|
1118
|
-
break;
|
|
1119
|
-
}
|
|
1120
|
-
};
|
|
1121
|
-
|
|
1122
|
-
/**
|
|
1123
|
-
* Calendar mode: dateTime인 경우 HMS 이동 화살표 클릭 이벤트
|
|
1124
|
-
* @param calendarType - {main|expanded}
|
|
1125
|
-
* @param timeType - {hour|min|sec}
|
|
1126
|
-
* @param arrow - {up|down}
|
|
1127
|
-
*/
|
|
1128
|
-
const clickHmsBtn = (calendarType, timeType, arrow) => {
|
|
1129
|
-
if (preventTimeEventType[calendarType][timeType]) {
|
|
1130
|
-
return;
|
|
1131
|
-
}
|
|
1132
|
-
|
|
1133
|
-
const pageInfo = calendarPageInfo[calendarType];
|
|
1134
|
-
const FIRST_PAGE = 1;
|
|
1135
|
-
const HOUR_MAX_PAGE = 2;
|
|
1136
|
-
const MINUTE_MAX_PAGE = 5;
|
|
1137
|
-
const SECOND_MAX_PAGE = 5;
|
|
1138
|
-
if (timeType === 'hour') {
|
|
1139
|
-
if (arrow === 'down' && pageInfo.hour < HOUR_MAX_PAGE) {
|
|
1140
|
-
pageInfo.hour++;
|
|
1141
|
-
} else if (arrow === 'up' && pageInfo.hour > FIRST_PAGE) {
|
|
1142
|
-
pageInfo.hour--;
|
|
1143
|
-
}
|
|
1144
|
-
} else if (timeType === 'min') {
|
|
1145
|
-
if (arrow === 'down' && pageInfo.min < MINUTE_MAX_PAGE) {
|
|
1146
|
-
pageInfo.min++;
|
|
1147
|
-
} else if (arrow === 'up' && pageInfo.min > FIRST_PAGE) {
|
|
1148
|
-
pageInfo.min--;
|
|
1149
|
-
}
|
|
1150
|
-
} else if (timeType === 'sec') {
|
|
1151
|
-
if (arrow === 'down' && pageInfo.sec < SECOND_MAX_PAGE) {
|
|
1152
|
-
pageInfo.sec++;
|
|
1153
|
-
} else if (arrow === 'up' && pageInfo.sec > FIRST_PAGE) {
|
|
1154
|
-
pageInfo.sec--;
|
|
1155
|
-
}
|
|
1156
|
-
}
|
|
1157
|
-
};
|
|
1158
|
-
|
|
1159
|
-
/**
|
|
1160
|
-
* Click cell In HMS area
|
|
1161
|
-
* @param calendarType - {main|expanded}
|
|
1162
|
-
* @param timeType - {hour|min|sec}
|
|
1163
|
-
* @param i - row
|
|
1164
|
-
* @param j - col
|
|
1165
|
-
*/
|
|
1166
|
-
const clickTime = (calendarType, timeType, i, j) => {
|
|
1167
|
-
if (preventTimeEventType[calendarType][timeType]) {
|
|
1168
|
-
return;
|
|
1169
|
-
}
|
|
1170
|
-
|
|
1171
|
-
const pageInfo = calendarPageInfo[calendarType];
|
|
1172
|
-
const timeInfo = calendarTimeTableInfo[calendarType];
|
|
1173
|
-
const currPage = pageInfo[timeType] - 1;
|
|
1174
|
-
const currRowIdx = i - 1;
|
|
1175
|
-
const currColIdx = j - 1;
|
|
1176
|
-
const clickedNum = (currPage * CELL_CNT_IN_ONE_PAGE)
|
|
1177
|
-
+ (currRowIdx * CELL_CNT_IN_ONE_ROW) + currColIdx;
|
|
1178
|
-
|
|
1179
|
-
if (timeInfo[timeType][clickedNum]?.isDisabled) {
|
|
1180
|
-
return;
|
|
1181
|
-
}
|
|
1182
|
-
|
|
1183
|
-
const TODAY = new Date();
|
|
1184
|
-
const TODAY_INFO = {
|
|
1185
|
-
year: TODAY.getFullYear(),
|
|
1186
|
-
month: TODAY.getMonth() + 1,
|
|
1187
|
-
date: TODAY.getDate(),
|
|
1188
|
-
};
|
|
1189
|
-
let EXIST_MODEL = true;
|
|
1190
|
-
let valueListByUpdatePage = [];
|
|
1191
|
-
|
|
1192
|
-
const getTimeValueByType = () => {
|
|
1193
|
-
let targetTimeValue;
|
|
1194
|
-
if (timeType === 'hour') {
|
|
1195
|
-
targetTimeValue = `${lpadToTwoDigits(clickedNum)}:00:00'`;
|
|
1196
|
-
} else if (timeType === 'min') {
|
|
1197
|
-
targetTimeValue = `00:${lpadToTwoDigits(clickedNum)}:00`;
|
|
1198
|
-
} else if (timeType === 'sec') {
|
|
1199
|
-
targetTimeValue = `00:00:${lpadToTwoDigits(clickedNum)}`;
|
|
1200
|
-
}
|
|
1201
|
-
return `${formatDateTime(TODAY_INFO)} ${targetTimeValue}`;
|
|
1202
|
-
};
|
|
1203
|
-
|
|
1204
|
-
const getChangedValue = (targetValue) => {
|
|
1205
|
-
const HOUR_START_IDX = 11;
|
|
1206
|
-
const MIN_START_IDX = 14;
|
|
1207
|
-
const SEC_START_IDX = 17;
|
|
1208
|
-
const REPLACE_TEXT_SIZE = 2;
|
|
1209
|
-
let START_IDX = HOUR_START_IDX;
|
|
1210
|
-
if (timeType === 'min') {
|
|
1211
|
-
START_IDX = MIN_START_IDX;
|
|
1212
|
-
} else if (timeType === 'sec') {
|
|
1213
|
-
START_IDX = SEC_START_IDX;
|
|
1214
|
-
}
|
|
1215
|
-
return `${targetValue?.substr(0, START_IDX)}`
|
|
1216
|
-
+ `${lpadToTwoDigits(clickedNum)}${targetValue?.substr(START_IDX + REPLACE_TEXT_SIZE)}`;
|
|
1217
|
-
};
|
|
1218
|
-
|
|
1219
|
-
if (props.mode === 'dateTime') {
|
|
1220
|
-
let changedValue;
|
|
1221
|
-
if (!props.modelValue) {
|
|
1222
|
-
EXIST_MODEL = false;
|
|
1223
|
-
changedValue = getChangedValueByTimeFormat(
|
|
1224
|
-
timeFormat,
|
|
1225
|
-
getTimeValueByType(),
|
|
1226
|
-
);
|
|
1227
|
-
} else {
|
|
1228
|
-
changedValue = getChangedValueByTimeFormat(
|
|
1229
|
-
timeFormat,
|
|
1230
|
-
getChangedValue(props.modelValue),
|
|
1231
|
-
);
|
|
1232
|
-
}
|
|
1233
|
-
emit('update:modelValue', changedValue);
|
|
1234
|
-
valueListByUpdatePage.push(changedValue);
|
|
1235
|
-
} else {
|
|
1236
|
-
const index = calendarType !== 'main' | 0;
|
|
1237
|
-
let changedValue = [...selectedValue.value];
|
|
1238
|
-
if (!props.modelValue.length) {
|
|
1239
|
-
const timeValue = getTimeValueByType();
|
|
1240
|
-
changedValue = [timeValue, timeValue];
|
|
1241
|
-
|
|
1242
|
-
if (timeFormat && timeFormat.length) {
|
|
1243
|
-
changedValue = [...changedValue
|
|
1244
|
-
.map((v, idx) => getChangedValueByTimeFormat(timeFormat[idx], v))];
|
|
1245
|
-
}
|
|
1246
|
-
|
|
1247
|
-
EXIST_MODEL = false;
|
|
1248
|
-
valueListByUpdatePage = changedValue;
|
|
1249
|
-
} else {
|
|
1250
|
-
let currDateTime = getChangedValue(props.modelValue[index]);
|
|
1251
|
-
if (timeFormat && timeFormat.length) {
|
|
1252
|
-
currDateTime = getChangedValueByTimeFormat(
|
|
1253
|
-
timeFormat[index],
|
|
1254
|
-
currDateTime,
|
|
1255
|
-
);
|
|
1256
|
-
}
|
|
1257
|
-
|
|
1258
|
-
changedValue[index] = currDateTime;
|
|
1259
|
-
}
|
|
1260
|
-
emit('update:modelValue', changedValue);
|
|
1261
|
-
}
|
|
1262
|
-
setHmsTime();
|
|
1263
|
-
// dateTime의 v-model값이 없는 경우 time area를 클릭하였을 때 date의 값은 today로 세팅
|
|
1264
|
-
if (!EXIST_MODEL) {
|
|
1265
|
-
updateCalendarPage(valueListByUpdatePage);
|
|
1266
|
-
}
|
|
1267
|
-
};
|
|
1268
|
-
|
|
1269
|
-
/**
|
|
1270
|
-
* Wheel up or wheel down In Calendar Month(tbody) area
|
|
1271
|
-
* @param calendarType - {main|expanded}
|
|
1272
|
-
* @param e
|
|
1273
|
-
*/
|
|
1274
|
-
const wheelMonth = (calendarType, e) => {
|
|
1275
|
-
clickPrevNextBtn(calendarType, e.deltaY > 0 ? 'next' : 'prev');
|
|
1276
|
-
};
|
|
1277
|
-
|
|
1278
|
-
/**
|
|
1279
|
-
* Wheel up or wheel down In Calendar Time(HMS) area
|
|
1280
|
-
* @param calendarType - {main|expanded}
|
|
1281
|
-
* @param timeType - {hour|min|sec}
|
|
1282
|
-
* @param e
|
|
1283
|
-
*/
|
|
1284
|
-
const wheelTime = (calendarType, timeType, e) => {
|
|
1285
|
-
if (preventTimeEventType[calendarType][timeType]) {
|
|
1286
|
-
return;
|
|
1287
|
-
}
|
|
1288
|
-
|
|
1289
|
-
clickHmsBtn(calendarType, timeType, e.deltaY > 0 ? 'down' : 'up');
|
|
1290
|
-
};
|
|
1291
|
-
|
|
1292
|
-
/**
|
|
1293
|
-
* dateRange 모드에서 한번 클릭 후 날짜에 마우스무브하는 경우
|
|
1294
|
-
* 커서 위에 있는 날짜까지의 selectedValue의 영역 선택한 selection 로직
|
|
1295
|
-
* 일반적인 마우스무브 로직에 성능향상을 위한 throttle 10ms를 설정
|
|
1296
|
-
* @param calendarType - 캘린더 종류 ('main'|'expanded')
|
|
1297
|
-
* @param e - 마우스이벤트
|
|
1298
|
-
* @type {function(): (*)}
|
|
1299
|
-
*/
|
|
1300
|
-
const onMousemoveDate = throttle((calendarType, e) => {
|
|
1301
|
-
const target = e.target.tagName === 'TD' ? e.target : e.target.parentElement;
|
|
1302
|
-
const isDisabled = target.classList.contains('disabled');
|
|
1303
|
-
const isPrev = target.classList.contains('prev');
|
|
1304
|
-
const isNext = target.classList.contains('next');
|
|
1305
|
-
if (target.classList.length > 0 && !isDisabled) {
|
|
1306
|
-
const pageInfo = calendarPageInfo[calendarType];
|
|
1307
|
-
let yearMonth = {
|
|
1308
|
-
year: +pageInfo.year,
|
|
1309
|
-
month: +pageInfo.month,
|
|
1310
|
-
date: e.target.innerText,
|
|
1311
|
-
};
|
|
1312
|
-
// 달력 내 이전달, 다음달 일자의 경우 연, 월 보정
|
|
1313
|
-
if (isPrev) {
|
|
1314
|
-
yearMonth = { ...yearMonth, ...getSideMonthCalendarInfo('prev', yearMonth.year, yearMonth.month) };
|
|
1315
|
-
} else if (isNext) {
|
|
1316
|
-
yearMonth = { ...yearMonth, ...getSideMonthCalendarInfo('next', yearMonth.year, yearMonth.month) };
|
|
1317
|
-
}
|
|
1318
|
-
const STANDARD_DATE_STR = dateRangeClickedDate.value;
|
|
1319
|
-
const MOUSEMOVE_DATE_STR = formatDateTime({
|
|
1320
|
-
year: yearMonth.year,
|
|
1321
|
-
month: yearMonth.month,
|
|
1322
|
-
date: yearMonth.date,
|
|
1323
|
-
});
|
|
1324
|
-
|
|
1325
|
-
// fromDate ~ toDate selection 순서 세팅
|
|
1326
|
-
if (getDateMs(MOUSEMOVE_DATE_STR) < getDateMs(STANDARD_DATE_STR)) {
|
|
1327
|
-
selectedValue.value[0] = MOUSEMOVE_DATE_STR;
|
|
1328
|
-
selectedValue.value[1] = STANDARD_DATE_STR;
|
|
1329
|
-
} else {
|
|
1330
|
-
selectedValue.value[0] = STANDARD_DATE_STR;
|
|
1331
|
-
selectedValue.value[1] = MOUSEMOVE_DATE_STR;
|
|
1332
|
-
}
|
|
1333
|
-
setCalendarDate('main');
|
|
1334
|
-
setCalendarDate('expanded');
|
|
1335
|
-
}
|
|
1336
|
-
}, 10);
|
|
1337
|
-
|
|
1338
|
-
/**
|
|
1339
|
-
* calendar setting 하기 전 선택된 날짜가 disabledDate에 포함되는지 체크
|
|
1340
|
-
* @param currValue
|
|
1341
|
-
*/
|
|
1342
|
-
const checkDisabledDate = (currValue) => {
|
|
1343
|
-
const isRangeMode = ['dateRange', 'dateMulti', 'dateTimeRange'].includes(props.mode);
|
|
1344
|
-
const disabledDate = props.options.disabledDate;
|
|
1345
|
-
if (isRangeMode) {
|
|
1346
|
-
const [fromDate, toDate] = selectedValue.value;
|
|
1347
|
-
let [disabledFromDate, disabledToDate] = [disabledDate, disabledDate];
|
|
1348
|
-
if (disabledDate && Array.isArray(disabledDate)) {
|
|
1349
|
-
[disabledFromDate, disabledToDate] = disabledDate;
|
|
1350
|
-
}
|
|
1351
|
-
|
|
1352
|
-
if (currValue[0] && currValue[0] !== fromDate
|
|
1353
|
-
&& disabledFromDate && disabledFromDate(new Date(currValue[0]))) {
|
|
1354
|
-
return true;
|
|
1355
|
-
} else if (currValue[1] && currValue[1] !== toDate
|
|
1356
|
-
&& disabledToDate && disabledToDate(new Date(currValue[1]))) {
|
|
1357
|
-
return true;
|
|
1358
|
-
} else if (!disabledDate
|
|
1359
|
-
&& compareFromAndToDateTime(props.mode, 'main', currValue[0], currValue)) {
|
|
1360
|
-
return true;
|
|
1361
|
-
}
|
|
1362
|
-
} else if (props.mode === 'dateMulti') {
|
|
1363
|
-
return currValue.some(value => disabledDate && disabledDate(new Date(value)));
|
|
1364
|
-
} else if (disabledDate && disabledDate(new Date(currValue))) {
|
|
1365
|
-
return true;
|
|
1366
|
-
}
|
|
1367
|
-
return false;
|
|
1368
|
-
};
|
|
1369
|
-
|
|
1370
|
-
watch(
|
|
1371
|
-
() => props.modelValue,
|
|
1372
|
-
(curr) => {
|
|
1373
|
-
if (checkDisabledDate(curr)) {
|
|
1374
|
-
emit('update:modelValue', selectedValue.value);
|
|
1375
|
-
return;
|
|
1376
|
-
}
|
|
1377
|
-
|
|
1378
|
-
const isRangeMode = ['dateRange', 'dateMulti', 'dateTimeRange'].includes(props.mode);
|
|
1379
|
-
selectedValue.value = isRangeMode ? [...curr] : curr;
|
|
1380
|
-
|
|
1381
|
-
if (props.mode === 'dateRange') {
|
|
1382
|
-
updateCalendarPage(curr);
|
|
1383
|
-
} else if (props.mode.includes('Time')) {
|
|
1384
|
-
let updateValue = [];
|
|
1385
|
-
if (props.mode === 'dateTime') {
|
|
1386
|
-
updateValue = [curr];
|
|
1387
|
-
} else if (props.mode === 'dateTimeRange') {
|
|
1388
|
-
updateValue = curr;
|
|
1389
|
-
}
|
|
1390
|
-
updateCalendarPage(updateValue);
|
|
1391
|
-
setHmsTime();
|
|
1392
|
-
} else if (props.mode === 'date') {
|
|
1393
|
-
updateCalendarPage([curr]);
|
|
1394
|
-
}
|
|
1395
|
-
});
|
|
1396
|
-
|
|
1397
|
-
return {
|
|
1398
|
-
clickYearMonthBtn,
|
|
1399
|
-
clickPrevNextBtn,
|
|
1400
|
-
clickDate,
|
|
1401
|
-
clickYearMonth,
|
|
1402
|
-
clickHmsBtn,
|
|
1403
|
-
clickTime,
|
|
1404
|
-
wheelMonth,
|
|
1405
|
-
wheelTime,
|
|
1406
|
-
calendarEventName,
|
|
1407
|
-
onMousemoveDate,
|
|
1408
|
-
preventTimeEventType,
|
|
1409
|
-
};
|
|
1410
|
-
};
|