@neatui/vue 3.1.0 → 4.0.0
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 +1 -10
- package/package.json +5 -2
- package/rollup.config.js +42 -2
- package/src/components/basic/IDraggable@b.vue +1 -1
- package/src/components/basic/IFollowView.vue +2 -2
- package/src/components/basic/LayerView/Layer.vue +193 -42
- package/src/components/display/Calendar.vue +6 -6
- package/src/components/display/CalendarReg.vue +6 -6
- package/src/components/display/PhotoEditor.vue +2 -2
- package/src/components/display/TreeView.vue +4 -3
- package/src/components/form/Cascader.vue +3 -3
- package/src/components/form/DatePicker.vue +2 -2
- package/src/components/form/{DateRangePicker@v3.vue → DateRangePicker.vue} +2 -1
- package/src/components/form/{DateRangeView@v3.vue → DateRangeView.vue} +11 -11
- package/src/components/form/DateView.vue +461 -82
- package/src/components/form/ImgUpload.vue +3 -3
- package/src/components/form/{MoreSelect@v3.vue → MoreSelect.vue} +1 -1
- package/src/components/form/MoreSelectList.vue +1 -1
- package/src/components/form/{MoreSelectPanel@v3.vue → MoreSelectPanel.vue} +1 -1
- package/src/components/form/MoreSelectPicker.vue +3 -3
- package/src/components/form/MoreSelectTags.vue +1 -1
- package/src/components/form/PageMoreSelect.vue +1 -1
- package/src/components/form/PageSelect.vue +1 -1
- package/src/components/form/SearchMoreSelect.vue +1 -1
- package/src/components/form/{SearchSelect@v3.vue → SearchSelect.vue} +1 -1
- package/src/components/form/{Select@v3.vue → Select.vue} +1 -1
- package/src/components/form/SelectList.vue +1 -1
- package/src/components/form/SelectPicker.vue +3 -3
- package/src/components/form/SelectTree/{SelectTree@v1.vue → SelectTree.vue} +1 -1
- package/src/components/form/Switch.vue +2 -1
- package/src/components/form/TimeView.vue +6 -6
- package/src/components/form/Upload.vue +22 -11
- package/src/components/form/index.ts +8 -8
- package/src/components/loader/FormLoader/FormLoader.vue +124 -103
- package/src/components/loader/LayerLoader/LayerLoader.vue +6 -7
- package/src/components/loader/LimitLoader/{LimitLoader@v3.vue → LimitLoader.vue} +4 -4
- package/src/components/loader/LimitLoader/index.ts +1 -1
- package/src/components/loader/TableLoader/TableLoader.vue +7 -7
- package/src/components/loader/TableLoader/TableRender.vue +0 -1
- package/src/components/loader/ViewLoader/{ViewLoader@v1.vue → ViewLoader.vue} +124 -103
- package/src/components/loader/ViewLoader/index.ts +1 -1
- package/src/components/tools/FormDraftsView.vue +4 -4
- package/src/components/tools/FormVerifyView.vue +2 -2
- package/src/components/tools/MoreTools.vue +5 -5
- package/src/components/tools/Pagination@a.vue +4 -4
- package/src/components/tools/Pagination@b.vue +4 -4
- package/tsconfig.json +1 -2
- package/src/components/form/DateView@v2.vue +0 -386
- package/src/components/form/DateView@v3.vue +0 -608
- package/src/components/tools/MoreTools@v2.vue +0 -74
- /package/src/components/form/{Input@v3.vue → Input.vue} +0 -0
- /package/src/components/form/{TextArea.vue → Textarea.vue} +0 -0
|
@@ -1,34 +1,83 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div ui-date="@a" class="
|
|
3
|
-
<div ui-date-head="" class="nx-
|
|
2
|
+
<div ui-date="@a" class="fekit-date-view pr" :class="`${frame ? 'b-solid b-line b-xs r-sm' : ''}`" ui-flex="col xy" style="width: 22em">
|
|
3
|
+
<div ui-date-head="" class="flex-fixed nx-ms mt-ss ny-sm b-solid b-line" ui-flex="row xm">
|
|
4
4
|
<div ui-flex="row lm" class="o-lm">
|
|
5
|
-
<div ui-btn="@a s none :square" @click="prev(
|
|
6
|
-
<Icon name="double-arrow-left" />
|
|
7
|
-
</div>
|
|
8
|
-
<div ui-btn="@a s none :square" @click="prev('m')">
|
|
5
|
+
<div ui-btn="@a s none :square" @click="prev()">
|
|
9
6
|
<Icon name="arrow-left" />
|
|
10
7
|
</div>
|
|
11
8
|
</div>
|
|
12
|
-
<div ui-
|
|
13
|
-
<
|
|
14
|
-
<
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
9
|
+
<div ui-btns="@a none s" @click="setPanelType()">
|
|
10
|
+
<p v-if="state.type === 2" class="nowrap" ui-flex="row cm">
|
|
11
|
+
<b class="nx-ss">{{ panel.sta }}年</b>
|
|
12
|
+
<span class="nx-xs">-</span>
|
|
13
|
+
<b class="nx-ss">{{ panel.end }}年</b>
|
|
14
|
+
</p>
|
|
15
|
+
<p v-else-if="state.type === 1" class="nowrap" ui-flex="row cm">
|
|
16
|
+
<b class="nx-ss">{{ state.curr.y }}年</b>
|
|
17
|
+
</p>
|
|
18
|
+
<p v-else class="nowrap" ui-flex="row cm">
|
|
19
|
+
<b class="nx-xs">{{ state.curr.y }}年</b>
|
|
20
|
+
<b class="nx-xs">{{ state.curr.M }}月</b>
|
|
21
|
+
</p>
|
|
19
22
|
</div>
|
|
20
23
|
<div ui-flex="row rm" class="o-lm">
|
|
21
|
-
<div ui-btn="@a s none :square" @click="next(
|
|
24
|
+
<div ui-btn="@a s none :square" @click="next()">
|
|
22
25
|
<Icon name="arrow-right" />
|
|
23
26
|
</div>
|
|
24
|
-
<div ui-btn="@a s none :square" @click="next('y')">
|
|
25
|
-
<Icon name="double-arrow-right" />
|
|
26
|
-
</div>
|
|
27
27
|
</div>
|
|
28
28
|
</div>
|
|
29
|
-
<div ui-date-body="">
|
|
30
|
-
<div class="
|
|
31
|
-
<ul ui-
|
|
29
|
+
<div ui-date-body="" :class="['flex-block pr', bodyClass]">
|
|
30
|
+
<div v-if="state.type === 2" class="full">
|
|
31
|
+
<ul ui-grid="mob:4" class="n-ms ny-sm-sub">
|
|
32
|
+
<li v-for="(year, idx) in panel.years" :key="idx" ui-flex="col cm" @click="setDateValue('y', year)">
|
|
33
|
+
<div ui-flex="col cm" class="w-ls h-sl ac ux-none r-sm" :class="isSelectedYear(year) ? 'active bg-main-o-lm co-w' : 'co-main:hover'">
|
|
34
|
+
{{ year }}
|
|
35
|
+
</div>
|
|
36
|
+
</li>
|
|
37
|
+
</ul>
|
|
38
|
+
</div>
|
|
39
|
+
<div v-else-if="state.type === 1" class="full">
|
|
40
|
+
<ul ui-grid="mob:4" class="n-ms ny-sm-sub">
|
|
41
|
+
<li ui-flex="col cm" @click="setDateValue('m', 1)">
|
|
42
|
+
<div ui-flex="col cm" class="w-ls h-sl ac ux-none r-sm" :class="isSelectedMonth(1) ? 'active bg-main-o-lm co-w' : 'co-main:hover'">1月</div>
|
|
43
|
+
</li>
|
|
44
|
+
<li ui-flex="col cm" @click="setDateValue('m', 2)">
|
|
45
|
+
<div ui-flex="col cm" class="w-ls h-sl ac ux-none r-sm" :class="isSelectedMonth(2) ? 'active bg-main-o-lm co-w' : 'co-main:hover'">2月</div>
|
|
46
|
+
</li>
|
|
47
|
+
<li ui-flex="col cm" @click="setDateValue('m', 3)">
|
|
48
|
+
<div ui-flex="col cm" class="w-ls h-sl ac ux-none r-sm" :class="isSelectedMonth(3) ? 'active bg-main-o-lm co-w' : 'co-main:hover'">3月</div>
|
|
49
|
+
</li>
|
|
50
|
+
<li ui-flex="col cm" @click="setDateValue('m', 4)">
|
|
51
|
+
<div ui-flex="col cm" class="w-ls h-sl ac ux-none r-sm" :class="isSelectedMonth(4) ? 'active bg-main-o-lm co-w' : 'co-main:hover'">4月</div>
|
|
52
|
+
</li>
|
|
53
|
+
<li ui-flex="col cm" @click="setDateValue('m', 5)">
|
|
54
|
+
<div ui-flex="col cm" class="w-ls h-sl ac ux-none r-sm" :class="isSelectedMonth(5) ? 'active bg-main-o-lm co-w' : 'co-main:hover'">5月</div>
|
|
55
|
+
</li>
|
|
56
|
+
<li ui-flex="col cm" @click="setDateValue('m', 6)">
|
|
57
|
+
<div ui-flex="col cm" class="w-ls h-sl ac ux-none r-sm" :class="isSelectedMonth(6) ? 'active bg-main-o-lm co-w' : 'co-main:hover'">6月</div>
|
|
58
|
+
</li>
|
|
59
|
+
<li ui-flex="col cm" @click="setDateValue('m', 7)">
|
|
60
|
+
<div ui-flex="col cm" class="w-ls h-sl ac ux-none r-sm" :class="isSelectedMonth(7) ? 'active bg-main-o-lm co-w' : 'co-main:hover'">7月</div>
|
|
61
|
+
</li>
|
|
62
|
+
<li ui-flex="col cm" @click="setDateValue('m', 8)">
|
|
63
|
+
<div ui-flex="col cm" class="w-ls h-sl ac ux-none r-sm" :class="isSelectedMonth(8) ? 'active bg-main-o-lm co-w' : 'co-main:hover'">8月</div>
|
|
64
|
+
</li>
|
|
65
|
+
<li ui-flex="col cm" @click="setDateValue('m', 9)">
|
|
66
|
+
<div ui-flex="col cm" class="w-ls h-sl ac ux-none r-sm" :class="isSelectedMonth(9) ? 'active bg-main-o-lm co-w' : 'co-main:hover'">9月</div>
|
|
67
|
+
</li>
|
|
68
|
+
<li ui-flex="col cm" @click="setDateValue('m', 10)">
|
|
69
|
+
<div ui-flex="col cm" class="w-ls h-sl ac ux-none r-sm" :class="isSelectedMonth(10) ? 'active bg-main-o-lm co-w' : 'co-main:hover'">10月</div>
|
|
70
|
+
</li>
|
|
71
|
+
<li ui-flex="col cm" @click="setDateValue('m', 11)">
|
|
72
|
+
<div ui-flex="col cm" class="w-ls h-sl ac ux-none r-sm" :class="isSelectedMonth(11) ? 'active bg-main-o-lm co-w' : 'co-main:hover'">11月</div>
|
|
73
|
+
</li>
|
|
74
|
+
<li ui-flex="col cm" @click="setDateValue('m', 12)">
|
|
75
|
+
<div ui-flex="col cm" class="w-ls h-sl ac ux-none r-sm" :class="isSelectedMonth(12) ? 'active bg-main-o-lm co-w' : 'co-main:hover'">12月</div>
|
|
76
|
+
</li>
|
|
77
|
+
</ul>
|
|
78
|
+
</div>
|
|
79
|
+
<div v-else class="full">
|
|
80
|
+
<ul ui-flex="row am" class="fs-ss nx-sm nt-ss">
|
|
32
81
|
<li class="flex-block ac"><span>日</span></li>
|
|
33
82
|
<li class="flex-block ac"><span>一</span></li>
|
|
34
83
|
<li class="flex-block ac"><span>二</span></li>
|
|
@@ -47,52 +96,129 @@
|
|
|
47
96
|
:class="`${item.range ? 'bg-main-o-xs' : ''} ${item.sta ? 'r-lt-sl r-lb-sl' : ''} ${item.end ? 'r-rt-sl r-rb-sl' : ''}`"
|
|
48
97
|
ui-flex="col cm"
|
|
49
98
|
@click="change(item)"
|
|
50
|
-
@mouseenter="setRangeValue(item)"
|
|
51
99
|
>
|
|
52
100
|
<div
|
|
53
101
|
ui-flex="col cm"
|
|
54
|
-
class="r-sm b-solid
|
|
102
|
+
class="r-sm b-solid b-none b-xs my-ss ux-scale"
|
|
55
103
|
style="width: 1.8em; height: 1.8em"
|
|
56
|
-
:class="`${item.isLastMonth || item.isNextMonth ? 'co-idle' : item.isHoliday ? 'co-risk' : ''} ${item.selected ? 'active bg-main-o-lm co-
|
|
104
|
+
:class="`${item.isLastMonth || item.isNextMonth ? 'co-idle' : item.isHoliday ? 'co-risk' : ''} ${item.selected ? 'active bg-main-o-lm co-w' : 'bg-weak:hover co-main:hover'}`"
|
|
57
105
|
>
|
|
58
106
|
<span>{{ item.day }}</span>
|
|
59
107
|
</div>
|
|
60
108
|
</div>
|
|
61
|
-
<div class="pa w-full lh-xs ny-ss ob-no ol-no nowrap s-ml bold" style="transform-origin: 50%
|
|
109
|
+
<div class="pa w-full lh-xs ny-ss ob-no ol-no nowrap s-ml bold" style="transform-origin: 50% 100%" ui-flex="row ct" v-html="extras(item)"></div>
|
|
62
110
|
</div>
|
|
63
111
|
</li>
|
|
64
112
|
</ul>
|
|
65
113
|
</div>
|
|
66
114
|
</div>
|
|
67
|
-
<
|
|
115
|
+
<template v-if="!state.isNoTime">
|
|
116
|
+
<div v-if="state.type === 0" class="h-ls ny-sm nx-ms">
|
|
117
|
+
<div class="full ac b-solid b-line b-xs r-sm" ui-row="mob-8" style="width: 100%; height: 3em; padding: 0.5em">
|
|
118
|
+
<ul
|
|
119
|
+
:style="`${state.panel ? '' : 'pointer-events: none; opacity:.35'}`"
|
|
120
|
+
class="fekit-date-view-time-scroll"
|
|
121
|
+
ref="ths"
|
|
122
|
+
ui-scroll=":y xs"
|
|
123
|
+
ui-btns="@a none s :block"
|
|
124
|
+
data-type="h"
|
|
125
|
+
@scroll="timeScroll"
|
|
126
|
+
>
|
|
127
|
+
<li v-for="(item, idx) in hours" :key="idx">
|
|
128
|
+
{{ item }}
|
|
129
|
+
</li>
|
|
130
|
+
</ul>
|
|
131
|
+
<ul
|
|
132
|
+
:style="`${state.panel ? '' : 'pointer-events: none; opacity:.35'}`"
|
|
133
|
+
class="fekit-date-view-time-scroll"
|
|
134
|
+
ref="tms"
|
|
135
|
+
ui-scroll=":y xs"
|
|
136
|
+
ui-btns="@a none s :block"
|
|
137
|
+
data-type="m"
|
|
138
|
+
@scroll="timeScroll"
|
|
139
|
+
>
|
|
140
|
+
<li v-for="(item, idx) in seconds" :key="idx">
|
|
141
|
+
{{ item }}
|
|
142
|
+
</li>
|
|
143
|
+
</ul>
|
|
144
|
+
<ul
|
|
145
|
+
:style="`${state.panel ? '' : 'pointer-events: none; opacity:.35'}`"
|
|
146
|
+
class="fekit-date-view-time-scroll"
|
|
147
|
+
ref="tss"
|
|
148
|
+
ui-scroll=":y xs"
|
|
149
|
+
ui-btns="@a none s :block"
|
|
150
|
+
data-type="s"
|
|
151
|
+
@scroll="timeScroll"
|
|
152
|
+
>
|
|
153
|
+
<li v-for="(item, idx) in seconds" :key="idx">
|
|
154
|
+
{{ item }}
|
|
155
|
+
</li>
|
|
156
|
+
</ul>
|
|
157
|
+
</div>
|
|
158
|
+
</div>
|
|
159
|
+
<div v-else class="h-ls"></div>
|
|
160
|
+
</template>
|
|
161
|
+
<div v-if="showTools" ui-date-foot="" ui-flex="row xm" class="flex-fixed nx-sl ny-sl b-solid b-line bt-xs">
|
|
68
162
|
<div ui-flex="row lm" class="nl-ss">
|
|
69
|
-
<
|
|
70
|
-
<span class="
|
|
71
|
-
<span>{{ state.
|
|
72
|
-
</
|
|
163
|
+
<div v-if="state.panel" ui-flex="row lm">
|
|
164
|
+
<span :anim-editing="state.type === baseType" class="nx-ss">{{ idate(state.panel).format(panelFormat) }}</span>
|
|
165
|
+
<!-- <span v-if="!state.isNoTime" :anim-editing="state.type === baseType" class="nx-ss">{{ idate(state.panel).format('HH:mm:ss') }}</span> -->
|
|
166
|
+
</div>
|
|
73
167
|
<div v-else-if="state.shortcuts?.length" ui-flex="row lm">
|
|
74
|
-
<
|
|
75
|
-
|
|
76
|
-
<p
|
|
77
|
-
<p class="bg-main-o-xs co-main r-xl" ui-btn="@a xs none :round"><Icon class="co-main" name="more" /></p>
|
|
168
|
+
<div class="mr-sm-sub nx-sl-sub ny-ss-sub lh-ss nowrap fs-sm dib-sub" ui-scroll=":x y:hidden">
|
|
169
|
+
<p v-for="(item, idx) in state.shortcuts" :key="idx" class="bg-main-o-ss co-main r-xl" ui-btn="@a xs none :round" @click="item?.func">{{ item?.text }}</p>
|
|
170
|
+
<p class="bg-main-o-ss co-main r-xl" ui-btn="@a xs none :round"><Icon class="co-main" name="more" /></p>
|
|
78
171
|
</div>
|
|
79
172
|
</div>
|
|
80
|
-
<div
|
|
173
|
+
<div> </div>
|
|
81
174
|
</div>
|
|
82
|
-
<div>
|
|
83
|
-
<button v-if="state.
|
|
175
|
+
<div class="ml-ss-sub" ui-flex="row rm">
|
|
176
|
+
<button v-if="state.panel" ui-btn="@a xs none" class="nx-ss co-risk" @click="remove">清除</button>
|
|
177
|
+
<button v-if="state.panel && !state.isNoTime" ui-btn="@a xs none" class="nx-ss co-main" @click="update">确定</button>
|
|
84
178
|
</div>
|
|
85
179
|
</div>
|
|
86
180
|
</div>
|
|
87
181
|
</template>
|
|
88
182
|
<script setup lang="ts">
|
|
89
|
-
import { computed, reactive, watch } from 'vue';
|
|
90
|
-
import { idate, isDateString, isString } from '@fekit/utils';
|
|
183
|
+
import { computed, ref, reactive, watch, onMounted } from 'vue';
|
|
184
|
+
import { idate, isDateString, isObject, isString } from '@fekit/utils';
|
|
91
185
|
import { Icon } from '../basic';
|
|
92
186
|
|
|
187
|
+
const normalizeDateInput = (value: any) => {
|
|
188
|
+
if (!value) {
|
|
189
|
+
return value;
|
|
190
|
+
}
|
|
191
|
+
if (isString(value)) {
|
|
192
|
+
if (/^\d{4}$/.test(value)) {
|
|
193
|
+
return `${value}-01-01`;
|
|
194
|
+
}
|
|
195
|
+
if (/^\d{4}-(\d{1,2})$/.test(value)) {
|
|
196
|
+
const [year, month] = value.split('-');
|
|
197
|
+
const m = month.padStart(2, '0');
|
|
198
|
+
return `${year}-${m}-01`;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
return value;
|
|
202
|
+
};
|
|
203
|
+
|
|
204
|
+
interface PickerConfig {
|
|
205
|
+
baseType: number;
|
|
206
|
+
format: string;
|
|
207
|
+
bodyClass: string;
|
|
208
|
+
tools: boolean;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
const PICKER_CONFIGS: Record<string, PickerConfig> = {
|
|
212
|
+
date: { baseType: 0, format: 'YYYY-MM-DD', bodyClass: 'min-h-xs*m', tools: true },
|
|
213
|
+
month: { baseType: 1, format: 'YYYY-MM', bodyClass: 'min-h-ms*s', tools: false },
|
|
214
|
+
year: { baseType: 2, format: 'YYYY', bodyClass: 'min-h-ms*s', tools: false },
|
|
215
|
+
};
|
|
216
|
+
|
|
93
217
|
// 创建日期
|
|
94
218
|
const cDate = (date: any = null) => {
|
|
95
|
-
|
|
219
|
+
const normalized = normalizeDateInput(date);
|
|
220
|
+
// iOS 兼容:Safari 不支持 "YYYY-MM-DD" 格式,需要替换为 "YYYY/MM/DD"
|
|
221
|
+
return isDateString(normalized) ? new Date(normalized?.replace(/-/g, '/')) : new Date();
|
|
96
222
|
};
|
|
97
223
|
|
|
98
224
|
// 快捷预设
|
|
@@ -117,18 +243,24 @@
|
|
|
117
243
|
},
|
|
118
244
|
};
|
|
119
245
|
|
|
120
|
-
const emits: any = defineEmits(['update:modelValue', 'change']);
|
|
246
|
+
const emits: any = defineEmits(['update:modelValue', 'change', 'update']);
|
|
247
|
+
interface TimeProps {
|
|
248
|
+
h: boolean | number;
|
|
249
|
+
m?: boolean | number;
|
|
250
|
+
s?: boolean | number;
|
|
251
|
+
}
|
|
121
252
|
interface Props {
|
|
122
253
|
modelValue?: string | number;
|
|
123
254
|
frame: boolean;
|
|
124
255
|
tools?: boolean;
|
|
125
256
|
range?: boolean;
|
|
126
257
|
format?: string;
|
|
127
|
-
picker?: 'date' | 'week' | 'month' | 'quarter';
|
|
258
|
+
picker?: 'date' | 'week' | 'month' | 'quarter' | 'year';
|
|
128
259
|
holiday?: object;
|
|
129
260
|
shortcuts?: Array<'yesterday' | 'today' | 'tomorrow'>;
|
|
130
261
|
extras?: (item: any) => string;
|
|
131
|
-
|
|
262
|
+
time?: boolean | TimeProps;
|
|
263
|
+
lang?: string;
|
|
132
264
|
}
|
|
133
265
|
const props: any = withDefaults(defineProps<Props>(), {
|
|
134
266
|
// 值
|
|
@@ -136,94 +268,341 @@
|
|
|
136
268
|
// 是否显示框架
|
|
137
269
|
frame: false,
|
|
138
270
|
// 是否是示工具
|
|
139
|
-
tools:
|
|
271
|
+
tools: undefined,
|
|
140
272
|
// 时间范围
|
|
141
273
|
range: false,
|
|
142
274
|
// 面板类型
|
|
143
275
|
picker: 'date',
|
|
144
276
|
// 额外内容
|
|
145
277
|
extras: (item: any) => {
|
|
146
|
-
return `<i class="dib o-ms mb-xs r-xl ${item.today ? 'bg-main' : 'bg-none'}" style="width:.
|
|
278
|
+
return `<i class="dib o-ms mb-xs r-xl ${item.today ? 'bg-main' : 'bg-none'}" style="width:.5em; height:.5em;"></i>`;
|
|
147
279
|
},
|
|
148
280
|
// 快捷选择
|
|
149
281
|
shortcuts: () => ['yesterday', 'today', 'tomorrow'],
|
|
150
282
|
// 数据格式化
|
|
151
|
-
format:
|
|
283
|
+
format: undefined,
|
|
152
284
|
// 节假日
|
|
153
285
|
holiday: () => ({}),
|
|
154
|
-
|
|
155
|
-
|
|
286
|
+
time: false,
|
|
287
|
+
// 语言
|
|
288
|
+
lang: 'zh-CN',
|
|
289
|
+
});
|
|
290
|
+
|
|
291
|
+
const pickerConfig = computed<PickerConfig>(() => {
|
|
292
|
+
const key = props.picker || 'date';
|
|
293
|
+
return PICKER_CONFIGS[key] || PICKER_CONFIGS.date;
|
|
294
|
+
});
|
|
295
|
+
|
|
296
|
+
// 小时
|
|
297
|
+
const hours = computed(() => {
|
|
298
|
+
const _hours: any = [];
|
|
299
|
+
for (let i = 0; i < 24; i++) {
|
|
300
|
+
_hours.push(i > 9 ? `${i}` : `0${i}`);
|
|
301
|
+
}
|
|
302
|
+
return _hours;
|
|
303
|
+
});
|
|
304
|
+
// 分秒
|
|
305
|
+
const seconds = computed(() => {
|
|
306
|
+
const _seconds: any = [];
|
|
307
|
+
for (let i = 0; i < 60; i++) {
|
|
308
|
+
_seconds.push(i > 9 ? `${i}` : `0${i}`);
|
|
309
|
+
}
|
|
310
|
+
return _seconds;
|
|
311
|
+
});
|
|
312
|
+
|
|
313
|
+
const baseType = computed(() => pickerConfig.value.baseType);
|
|
314
|
+
|
|
315
|
+
const panelFormat = computed(() => props.format || pickerConfig.value.format);
|
|
316
|
+
|
|
317
|
+
const bodyClass = computed(() => pickerConfig.value.bodyClass);
|
|
318
|
+
|
|
319
|
+
const showTools = computed(() => {
|
|
320
|
+
if (props.tools !== undefined) {
|
|
321
|
+
return !!props.tools;
|
|
322
|
+
}
|
|
323
|
+
return pickerConfig.value.tools;
|
|
156
324
|
});
|
|
157
325
|
|
|
326
|
+
const isSelectedYear = (year: number) => {
|
|
327
|
+
return !!state.panel && state.curr?.y === year;
|
|
328
|
+
};
|
|
329
|
+
|
|
330
|
+
const isSelectedMonth = (month: number) => {
|
|
331
|
+
return !!state.panel && state.curr?.M === month;
|
|
332
|
+
};
|
|
333
|
+
|
|
158
334
|
// 内部数据
|
|
159
335
|
const state: any = reactive({
|
|
160
|
-
|
|
336
|
+
// 面板显示时间
|
|
337
|
+
panel: undefined,
|
|
338
|
+
// 面板年份选择
|
|
339
|
+
years: 0,
|
|
161
340
|
// 当前时间计算
|
|
162
341
|
curr: computed(() => {
|
|
163
|
-
const date = idate(state.
|
|
164
|
-
const days = date.calendar({ group: true, value: [state.
|
|
165
|
-
|
|
166
|
-
return { days, y, m, d };
|
|
342
|
+
const date = idate(state.panel);
|
|
343
|
+
const days = date.calendar({ group: true, value: [state.panel] });
|
|
344
|
+
return { days, ...date.attr };
|
|
167
345
|
}),
|
|
346
|
+
// 当前面板类型
|
|
347
|
+
type: 0,
|
|
168
348
|
// 值
|
|
169
|
-
value:
|
|
170
|
-
// 范围时间值
|
|
171
|
-
rangeValue: '',
|
|
349
|
+
value: undefined,
|
|
172
350
|
// 快捷选择
|
|
173
351
|
shortcuts: computed(() => {
|
|
174
352
|
return props.shortcuts.map((item: any) => {
|
|
175
353
|
return isString(item) ? shortcutsList[item] : item;
|
|
176
354
|
});
|
|
177
355
|
}),
|
|
356
|
+
// 不带时间(只要时或分的也考虑到)
|
|
357
|
+
isNoTime: computed(() => {
|
|
358
|
+
if (isObject(props.time)) {
|
|
359
|
+
return !(props.time.h || props.time.m || props.time.s);
|
|
360
|
+
} else {
|
|
361
|
+
return !props.time;
|
|
362
|
+
}
|
|
363
|
+
}),
|
|
178
364
|
});
|
|
179
365
|
|
|
366
|
+
watch(
|
|
367
|
+
() => baseType.value,
|
|
368
|
+
(value) => {
|
|
369
|
+
state.type = value;
|
|
370
|
+
},
|
|
371
|
+
{ immediate: true },
|
|
372
|
+
);
|
|
373
|
+
|
|
374
|
+
watch(
|
|
375
|
+
() => panelFormat.value,
|
|
376
|
+
(format) => {
|
|
377
|
+
if (state.panel) {
|
|
378
|
+
const formatted = idate(state.panel).format(format);
|
|
379
|
+
if (formatted !== state.panel) {
|
|
380
|
+
state.panel = formatted;
|
|
381
|
+
}
|
|
382
|
+
state.value = formatted;
|
|
383
|
+
}
|
|
384
|
+
},
|
|
385
|
+
{ immediate: true },
|
|
386
|
+
);
|
|
387
|
+
|
|
388
|
+
// 面板
|
|
389
|
+
const panel: any = reactive({
|
|
390
|
+
years: computed(() => {
|
|
391
|
+
const startYear = Math.floor(state.curr.year / 10) * 10;
|
|
392
|
+
const list = [];
|
|
393
|
+
for (let i = 0; i < 10; i++) {
|
|
394
|
+
list.push(startYear + i);
|
|
395
|
+
}
|
|
396
|
+
return list;
|
|
397
|
+
}),
|
|
398
|
+
sta: computed(() => {
|
|
399
|
+
return panel.years[0];
|
|
400
|
+
}),
|
|
401
|
+
end: computed(() => {
|
|
402
|
+
return panel.years[9];
|
|
403
|
+
}),
|
|
404
|
+
});
|
|
405
|
+
|
|
406
|
+
// 设置日期
|
|
407
|
+
const setDateValue = (type: any, value: number = 0, add: number = 0) => {
|
|
408
|
+
const panelValue = upload(type, value, add);
|
|
409
|
+
state.panel = panelValue;
|
|
410
|
+
state.value = panelValue;
|
|
411
|
+
// 面板返回上一级
|
|
412
|
+
const base = baseType.value;
|
|
413
|
+
const nextType = Math.max(base, state.type - 1);
|
|
414
|
+
state.type = nextType;
|
|
415
|
+
|
|
416
|
+
if (base > 0 && nextType === base) {
|
|
417
|
+
emits('change', panelValue);
|
|
418
|
+
update();
|
|
419
|
+
}
|
|
420
|
+
};
|
|
421
|
+
|
|
422
|
+
// 时分秒
|
|
423
|
+
const ths: any = ref(null);
|
|
424
|
+
const tms: any = ref(null);
|
|
425
|
+
const tss: any = ref(null);
|
|
426
|
+
const setTimeValue = () => {
|
|
427
|
+
const { H = 0, m = 0, s = 0 }: any = state.curr || {};
|
|
428
|
+
if (state.panel) {
|
|
429
|
+
if (ths.value && ths.value.children[H]) {
|
|
430
|
+
ths.value.scrollTop = ths.value.children[H].offsetTop;
|
|
431
|
+
}
|
|
432
|
+
if (tms.value && tms.value.children[m]) {
|
|
433
|
+
tms.value.scrollTop = tms.value.children[m].offsetTop;
|
|
434
|
+
}
|
|
435
|
+
if (tss.value && tss.value.children[s]) {
|
|
436
|
+
tss.value.scrollTop = tss.value.children[s].offsetTop;
|
|
437
|
+
}
|
|
438
|
+
} else {
|
|
439
|
+
if (ths.value && ths.value.children[H]) {
|
|
440
|
+
ths.value.scrollTop = ths.value.children[0].offsetTop;
|
|
441
|
+
}
|
|
442
|
+
if (tms.value && tms.value.children[m]) {
|
|
443
|
+
tms.value.scrollTop = tms.value.children[0].offsetTop;
|
|
444
|
+
}
|
|
445
|
+
if (tss.value && tss.value.children[s]) {
|
|
446
|
+
tss.value.scrollTop = tss.value.children[0].offsetTop;
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
};
|
|
450
|
+
|
|
180
451
|
watch(
|
|
181
452
|
() => props.modelValue,
|
|
182
453
|
(value: any) => {
|
|
183
|
-
|
|
184
|
-
|
|
454
|
+
const formatted = value ? idate(value).format(panelFormat.value) : undefined;
|
|
455
|
+
// 面板显示日期
|
|
456
|
+
state.panel = formatted;
|
|
457
|
+
// 值
|
|
458
|
+
state.value = formatted;
|
|
185
459
|
},
|
|
186
460
|
{ deep: true, immediate: true },
|
|
187
461
|
);
|
|
188
|
-
|
|
462
|
+
|
|
463
|
+
onMounted(() => {
|
|
464
|
+
setTimeValue();
|
|
465
|
+
});
|
|
189
466
|
watch(
|
|
190
|
-
() =>
|
|
191
|
-
(
|
|
192
|
-
|
|
467
|
+
() => state.panel,
|
|
468
|
+
() => {
|
|
469
|
+
setTimeValue();
|
|
193
470
|
},
|
|
194
|
-
{ deep: true, immediate: true },
|
|
195
471
|
);
|
|
196
472
|
|
|
197
473
|
// 更新时间
|
|
198
|
-
const upload = (
|
|
199
|
-
const date = cDate(state.
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
474
|
+
const upload = (type: string = 'm', value: number = 0, add: number = 1) => {
|
|
475
|
+
const date = cDate(state.panel);
|
|
476
|
+
|
|
477
|
+
switch (type) {
|
|
478
|
+
case 'y':
|
|
479
|
+
if (value !== 0) {
|
|
480
|
+
date.setFullYear(value);
|
|
481
|
+
} else {
|
|
482
|
+
date.setFullYear(date.getFullYear() + add);
|
|
483
|
+
}
|
|
484
|
+
break;
|
|
485
|
+
case 'm':
|
|
486
|
+
if (value !== 0) {
|
|
487
|
+
date.setMonth(value - 1);
|
|
488
|
+
} else {
|
|
489
|
+
date.setMonth(date.getMonth() + add);
|
|
490
|
+
}
|
|
491
|
+
break;
|
|
492
|
+
case 'd':
|
|
493
|
+
if (value !== 0) {
|
|
494
|
+
date.setDate(value);
|
|
495
|
+
} else {
|
|
496
|
+
date.setDate(date.getDate() + add);
|
|
497
|
+
}
|
|
498
|
+
break;
|
|
499
|
+
case 'h':
|
|
500
|
+
if (value !== 0) {
|
|
501
|
+
date.setHours(value);
|
|
502
|
+
} else {
|
|
503
|
+
date.setHours(date.getHours() + add);
|
|
504
|
+
}
|
|
505
|
+
break;
|
|
506
|
+
case 'n':
|
|
507
|
+
if (value !== 0) {
|
|
508
|
+
date.setMinutes(value);
|
|
509
|
+
} else {
|
|
510
|
+
date.setMinutes(date.getMinutes() + add);
|
|
511
|
+
}
|
|
512
|
+
break;
|
|
513
|
+
case 's':
|
|
514
|
+
if (value !== 0) {
|
|
515
|
+
date.setSeconds(value);
|
|
516
|
+
} else {
|
|
517
|
+
date.setSeconds(date.getSeconds() + add);
|
|
518
|
+
}
|
|
519
|
+
break;
|
|
520
|
+
default:
|
|
521
|
+
break;
|
|
204
522
|
}
|
|
205
|
-
return idate(date).format(
|
|
523
|
+
return idate(date).format(panelFormat.value);
|
|
206
524
|
};
|
|
207
525
|
|
|
208
526
|
// 日期前翻
|
|
209
|
-
const prev = (
|
|
210
|
-
state.
|
|
527
|
+
const prev = () => {
|
|
528
|
+
state.panel = upload(state.type > 0 ? 'y' : 'm', 0, state.type === 2 ? -10 : -1);
|
|
211
529
|
};
|
|
212
530
|
// 日期后翻
|
|
213
|
-
const next = (
|
|
214
|
-
state.
|
|
215
|
-
};
|
|
216
|
-
// 设置范围时间
|
|
217
|
-
const setRangeValue = (item: any) => {
|
|
218
|
-
if (state.value) {
|
|
219
|
-
state.rangeValue = idate(item.date).format(props.format);
|
|
220
|
-
}
|
|
531
|
+
const next = () => {
|
|
532
|
+
state.panel = upload(state.type > 0 ? 'y' : 'm', 0, state.type === 2 ? 10 : 1);
|
|
221
533
|
};
|
|
222
534
|
|
|
223
535
|
// 向外通信
|
|
224
536
|
const change = (item: any) => {
|
|
225
|
-
|
|
226
|
-
|
|
537
|
+
const panelValue = item ? idate(item.date).format(panelFormat.value) : item;
|
|
538
|
+
state.panel = panelValue;
|
|
539
|
+
state.value = panelValue;
|
|
540
|
+
emits('change', panelValue);
|
|
541
|
+
if (state.isNoTime) {
|
|
542
|
+
update();
|
|
543
|
+
}
|
|
544
|
+
};
|
|
545
|
+
|
|
546
|
+
// 清空日期
|
|
547
|
+
const remove = () => {
|
|
548
|
+
state.panel = undefined;
|
|
549
|
+
state.value = undefined;
|
|
550
|
+
update();
|
|
551
|
+
};
|
|
552
|
+
|
|
553
|
+
// 更新数据
|
|
554
|
+
const update = () => {
|
|
555
|
+
const nextValue = state.panel ? idate(state.panel).format(panelFormat.value) : undefined;
|
|
556
|
+
if (state.panel && nextValue !== state.panel) {
|
|
557
|
+
state.panel = nextValue;
|
|
558
|
+
}
|
|
559
|
+
state.value = nextValue;
|
|
560
|
+
emits('update:modelValue', nextValue);
|
|
561
|
+
emits('update', nextValue);
|
|
562
|
+
};
|
|
563
|
+
|
|
564
|
+
// 面板类型
|
|
565
|
+
const setPanelType = () => {
|
|
566
|
+
if (state.type < 2) {
|
|
567
|
+
state.type += 1;
|
|
568
|
+
}
|
|
569
|
+
};
|
|
570
|
+
|
|
571
|
+
// 时间滚动
|
|
572
|
+
const _timer: any = ref(null);
|
|
573
|
+
const timeScroll = (ev: any) => {
|
|
574
|
+
const item: any = ev.target?.children[0];
|
|
575
|
+
const type: any = ev.target.getAttribute('data-type') || '';
|
|
576
|
+
if (state.panel && item) {
|
|
577
|
+
clearTimeout(_timer.value);
|
|
578
|
+
_timer.value = setTimeout(() => {
|
|
579
|
+
const h = item.offsetHeight;
|
|
580
|
+
const idx = Math.floor(ev.target.scrollTop / h);
|
|
581
|
+
const maxIdx = type === 'h' ? 23 : 59;
|
|
582
|
+
const safeIdx = Math.min(Math.max(idx, 0), maxIdx);
|
|
583
|
+
const { YYYY = 0, MM = 0, DD = 0, HH = '', mm = '', ss = '' }: any = state.curr || {};
|
|
584
|
+
let _panel = `${YYYY}-${MM}-${DD}`;
|
|
585
|
+
if (type === 'h') {
|
|
586
|
+
_panel += ` ${safeIdx}:${mm}:${ss}`;
|
|
587
|
+
}
|
|
588
|
+
if (type === 'm') {
|
|
589
|
+
_panel += ` ${HH}:${safeIdx}:${ss}`;
|
|
590
|
+
}
|
|
591
|
+
if (type === 's') {
|
|
592
|
+
_panel += ` ${HH}:${mm}:${safeIdx}`;
|
|
593
|
+
}
|
|
594
|
+
state.panel = idate(_panel).format('YYYY-MM-DD HH:mm:ss');
|
|
595
|
+
}, 100);
|
|
596
|
+
}
|
|
227
597
|
};
|
|
228
|
-
// 向外通信范围时间
|
|
229
598
|
</script>
|
|
599
|
+
<style lang="scss">
|
|
600
|
+
.fekit-date-view-time-scroll {
|
|
601
|
+
position: relative;
|
|
602
|
+
height: 100%;
|
|
603
|
+
scroll-snap-type: y mandatory;
|
|
604
|
+
& > * {
|
|
605
|
+
scroll-snap-align: center;
|
|
606
|
+
}
|
|
607
|
+
}
|
|
608
|
+
</style>
|