@hbdlzy/ui-core 0.1.1 → 0.1.2
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 +37 -2
- package/components.manifest.json +195 -163
- package/dist/index.cjs +1 -1
- package/dist/index.js +1877 -13
- package/dist/style.css +1 -1
- package/package.json +2 -1
- package/src/components/OutlinedCascader/OutlinedCascader.types.ts +28 -0
- package/src/components/OutlinedCascader/OutlinedCascader.vue +250 -0
- package/src/components/OutlinedCascader/README.md +91 -0
- package/src/components/OutlinedCascader/index.ts +10 -0
- package/src/components/OutlinedDatePicker/OutlinedDatePicker.types.ts +40 -0
- package/src/components/OutlinedDatePicker/OutlinedDatePicker.vue +365 -0
- package/src/components/OutlinedDatePicker/README.md +137 -0
- package/src/components/OutlinedDatePicker/index.ts +11 -0
- package/src/components/OutlinedDateTimePicker/OutlinedDateTimePicker.types.ts +34 -0
- package/src/components/OutlinedDateTimePicker/OutlinedDateTimePicker.vue +421 -0
- package/src/components/OutlinedDateTimePicker/README.md +88 -0
- package/src/components/OutlinedDateTimePicker/index.ts +11 -0
- package/src/components/OutlinedInput/OutlinedInput.types.ts +32 -0
- package/src/components/OutlinedInput/OutlinedInput.vue +307 -0
- package/src/components/OutlinedInput/README.md +154 -0
- package/src/components/OutlinedInput/index.ts +10 -0
- package/src/components/OutlinedSelect/OutlinedSelect.types.ts +48 -0
- package/src/components/OutlinedSelect/OutlinedSelect.vue +359 -0
- package/src/components/OutlinedSelect/README.md +166 -0
- package/src/components/OutlinedSelect/index.ts +12 -0
- package/src/components/OutlinedTimePicker/OutlinedTimePicker.types.ts +36 -0
- package/src/components/OutlinedTimePicker/OutlinedTimePicker.vue +303 -0
- package/src/components/OutlinedTimePicker/README.md +93 -0
- package/src/components/OutlinedTimePicker/index.ts +10 -0
- package/src/components/OutlinedTreeSelect/OutlinedTreeSelect.types.ts +56 -0
- package/src/components/OutlinedTreeSelect/OutlinedTreeSelect.vue +354 -0
- package/src/components/OutlinedTreeSelect/README.md +107 -0
- package/src/components/OutlinedTreeSelect/index.ts +12 -0
- package/src/index.ts +14 -0
|
@@ -0,0 +1,421 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div
|
|
3
|
+
class="outlined-date-time-picker"
|
|
4
|
+
:class="[rootClass]"
|
|
5
|
+
:style="rootStyle"
|
|
6
|
+
>
|
|
7
|
+
<div
|
|
8
|
+
class="outlined-date-time-picker__field"
|
|
9
|
+
:class="fieldClasses"
|
|
10
|
+
:style="fieldStyle"
|
|
11
|
+
>
|
|
12
|
+
<el-date-picker
|
|
13
|
+
ref="datePickerRef"
|
|
14
|
+
class="outlined-date-time-picker__control"
|
|
15
|
+
:model-value="dateValue"
|
|
16
|
+
type="date"
|
|
17
|
+
format="YYYY-MM-DD"
|
|
18
|
+
value-format="YYYY-MM-DD"
|
|
19
|
+
:placeholder="placeholder"
|
|
20
|
+
:clearable="clearable"
|
|
21
|
+
:disabled-date="resolvedDisabledDate"
|
|
22
|
+
:style="controlStyle"
|
|
23
|
+
@update:model-value="handleDateUpdate"
|
|
24
|
+
@focus="handleFocus('date')"
|
|
25
|
+
@blur="handleBlur('date', $event)"
|
|
26
|
+
@change="handleDateChange"
|
|
27
|
+
@visible-change="handleVisibleChange('date', $event)"
|
|
28
|
+
/>
|
|
29
|
+
|
|
30
|
+
<div
|
|
31
|
+
v-if="floatingLabel"
|
|
32
|
+
class="outlined-date-time-picker__label"
|
|
33
|
+
:class="dateLabelClasses"
|
|
34
|
+
>
|
|
35
|
+
{{ floatingLabel }}
|
|
36
|
+
</div>
|
|
37
|
+
</div>
|
|
38
|
+
|
|
39
|
+
<span class="outlined-date-time-picker__separator">{{ separatorText }}</span>
|
|
40
|
+
|
|
41
|
+
<div
|
|
42
|
+
class="outlined-date-time-picker__field"
|
|
43
|
+
:class="fieldClasses"
|
|
44
|
+
:style="fieldStyle"
|
|
45
|
+
>
|
|
46
|
+
<el-time-picker
|
|
47
|
+
ref="timePickerRef"
|
|
48
|
+
class="outlined-date-time-picker__control"
|
|
49
|
+
:model-value="timeValue"
|
|
50
|
+
format="HH:mm"
|
|
51
|
+
value-format="HH:mm"
|
|
52
|
+
:placeholder="timePlaceholder"
|
|
53
|
+
:clearable="clearable"
|
|
54
|
+
:disabled="!dateValue"
|
|
55
|
+
:disabled-hours="resolvedDisabledHours"
|
|
56
|
+
:disabled-minutes="resolvedDisabledMinutes"
|
|
57
|
+
:style="controlStyle"
|
|
58
|
+
@update:model-value="handleTimeUpdate"
|
|
59
|
+
@focus="handleFocus('time')"
|
|
60
|
+
@blur="handleBlur('time', $event)"
|
|
61
|
+
@change="handleTimeChange"
|
|
62
|
+
@visible-change="handleVisibleChange('time', $event)"
|
|
63
|
+
/>
|
|
64
|
+
|
|
65
|
+
<div
|
|
66
|
+
class="outlined-date-time-picker__label"
|
|
67
|
+
:class="timeLabelClasses"
|
|
68
|
+
>
|
|
69
|
+
{{ timePlaceholder }}
|
|
70
|
+
</div>
|
|
71
|
+
</div>
|
|
72
|
+
</div>
|
|
73
|
+
</template>
|
|
74
|
+
|
|
75
|
+
<script setup lang="ts">
|
|
76
|
+
import { computed, ref, useAttrs, watch } from 'vue'
|
|
77
|
+
import dayjs from 'dayjs'
|
|
78
|
+
import type {
|
|
79
|
+
OutlinedDateTimePickerCssValue,
|
|
80
|
+
OutlinedDateTimePickerDisabledDate,
|
|
81
|
+
OutlinedDateTimePickerExpose,
|
|
82
|
+
OutlinedDateTimePickerProps,
|
|
83
|
+
OutlinedDateTimePickerValue
|
|
84
|
+
} from './OutlinedDateTimePicker.types'
|
|
85
|
+
|
|
86
|
+
defineOptions({
|
|
87
|
+
name: 'OutlinedDateTimePicker',
|
|
88
|
+
inheritAttrs: false
|
|
89
|
+
})
|
|
90
|
+
|
|
91
|
+
const props = withDefaults(defineProps<OutlinedDateTimePickerProps>(), {
|
|
92
|
+
value: '',
|
|
93
|
+
placeholder: '',
|
|
94
|
+
label: '',
|
|
95
|
+
inputHeight: 40,
|
|
96
|
+
isBorder: false,
|
|
97
|
+
disabledDate: undefined,
|
|
98
|
+
separatorText: '-',
|
|
99
|
+
timePlaceholder: '时间',
|
|
100
|
+
clearable: false,
|
|
101
|
+
marginBottom: 20,
|
|
102
|
+
paddingTop: 20
|
|
103
|
+
})
|
|
104
|
+
|
|
105
|
+
const emit = defineEmits<{
|
|
106
|
+
(event: 'input', value: OutlinedDateTimePickerValue): void
|
|
107
|
+
(event: 'update:value', value: OutlinedDateTimePickerValue): void
|
|
108
|
+
(event: 'change', value: OutlinedDateTimePickerValue): void
|
|
109
|
+
(event: 'focus', payload: { field: 'date' | 'time'; event: FocusEvent }): void
|
|
110
|
+
(event: 'blur', payload: { field: 'date' | 'time'; event: FocusEvent }): void
|
|
111
|
+
(event: 'visible-change', payload: { field: 'date' | 'time'; visible: boolean }): void
|
|
112
|
+
}>()
|
|
113
|
+
|
|
114
|
+
const attrs = useAttrs()
|
|
115
|
+
const datePickerRef = ref<any>(null)
|
|
116
|
+
const timePickerRef = ref<any>(null)
|
|
117
|
+
const dateValue = ref<string | null>(null)
|
|
118
|
+
const timeValue = ref<string | null>(null)
|
|
119
|
+
const dateFocused = ref(false)
|
|
120
|
+
const timeFocused = ref(false)
|
|
121
|
+
const dateBlurred = ref(false)
|
|
122
|
+
const timeBlurred = ref(false)
|
|
123
|
+
const dateVisible = ref(false)
|
|
124
|
+
const timeVisible = ref(false)
|
|
125
|
+
|
|
126
|
+
watch(
|
|
127
|
+
() => props.value,
|
|
128
|
+
(value) => {
|
|
129
|
+
syncFromValue(value)
|
|
130
|
+
},
|
|
131
|
+
{ immediate: true }
|
|
132
|
+
)
|
|
133
|
+
|
|
134
|
+
const rootClass = computed(() => attrs.class)
|
|
135
|
+
const rootStyle = computed(() => attrs.style)
|
|
136
|
+
const floatingLabel = computed(() => props.label || props.placeholder || '')
|
|
137
|
+
|
|
138
|
+
const fieldClasses = computed(() => ({
|
|
139
|
+
'outlined-date-time-picker__field--bordered': props.isBorder
|
|
140
|
+
}))
|
|
141
|
+
|
|
142
|
+
const fieldStyle = computed(() => ({
|
|
143
|
+
marginBottom: toCssValue(props.marginBottom),
|
|
144
|
+
paddingTop: toCssValue(props.paddingTop)
|
|
145
|
+
}))
|
|
146
|
+
|
|
147
|
+
const controlStyle = computed(() => ({
|
|
148
|
+
height: `${props.inputHeight}px`
|
|
149
|
+
}))
|
|
150
|
+
|
|
151
|
+
const resolvedDisabledDate = computed(() => createDisabledDateHandler(props.disabledDate))
|
|
152
|
+
|
|
153
|
+
const resolvedDisabledHours = computed(() => {
|
|
154
|
+
if (!shouldLimitCurrentTime()) {
|
|
155
|
+
return undefined
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
return () => {
|
|
159
|
+
const hours = new Date().getHours()
|
|
160
|
+
return Array.from({ length: hours }, (_, index) => index)
|
|
161
|
+
}
|
|
162
|
+
})
|
|
163
|
+
|
|
164
|
+
const resolvedDisabledMinutes = computed(() => {
|
|
165
|
+
if (!shouldLimitCurrentTime()) {
|
|
166
|
+
return undefined
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
return () => {
|
|
170
|
+
const minutes = new Date().getMinutes()
|
|
171
|
+
return Array.from({ length: minutes }, (_, index) => index)
|
|
172
|
+
}
|
|
173
|
+
})
|
|
174
|
+
|
|
175
|
+
const dateLabelClasses = computed(() => ({
|
|
176
|
+
'outlined-date-time-picker__label--floating': dateFocused.value || Boolean(dateValue.value),
|
|
177
|
+
'outlined-date-time-picker__label--placeholder': !dateFocused.value && !dateValue.value,
|
|
178
|
+
'outlined-date-time-picker__label--filled': Boolean(dateValue.value) && !dateFocused.value
|
|
179
|
+
}))
|
|
180
|
+
|
|
181
|
+
const timeLabelClasses = computed(() => ({
|
|
182
|
+
'outlined-date-time-picker__label--floating': timeFocused.value || Boolean(timeValue.value),
|
|
183
|
+
'outlined-date-time-picker__label--placeholder': !timeFocused.value && !timeValue.value,
|
|
184
|
+
'outlined-date-time-picker__label--filled': Boolean(timeValue.value) && !timeFocused.value
|
|
185
|
+
}))
|
|
186
|
+
|
|
187
|
+
function syncFromValue(value: OutlinedDateTimePickerValue) {
|
|
188
|
+
if (!value) {
|
|
189
|
+
dateValue.value = null
|
|
190
|
+
timeValue.value = null
|
|
191
|
+
return
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
const [datePart, timePart] = value.split(' ')
|
|
195
|
+
dateValue.value = datePart || null
|
|
196
|
+
timeValue.value = timePart || null
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
function handleDateUpdate(value: string | null) {
|
|
200
|
+
dateValue.value = value || null
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
function handleTimeUpdate(value: string | null) {
|
|
204
|
+
timeValue.value = value || null
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
function handleDateChange() {
|
|
208
|
+
if (dateValue.value && !timeValue.value) {
|
|
209
|
+
timeValue.value = dayjs().format('HH:mm')
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
emitCombinedValue()
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
function handleTimeChange() {
|
|
216
|
+
emitCombinedValue()
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
function handleFocus(field: 'date' | 'time') {
|
|
220
|
+
return (event: FocusEvent) => {
|
|
221
|
+
if (field === 'date') {
|
|
222
|
+
dateBlurred.value = false
|
|
223
|
+
dateFocused.value = true
|
|
224
|
+
} else {
|
|
225
|
+
timeBlurred.value = false
|
|
226
|
+
timeFocused.value = true
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
emit('focus', { field, event })
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
function handleBlur(field: 'date' | 'time', event: FocusEvent) {
|
|
234
|
+
if (field === 'date') {
|
|
235
|
+
dateBlurred.value = true
|
|
236
|
+
|
|
237
|
+
if (!dateVisible.value) {
|
|
238
|
+
dateFocused.value = false
|
|
239
|
+
emitCombinedValue()
|
|
240
|
+
}
|
|
241
|
+
} else {
|
|
242
|
+
timeBlurred.value = true
|
|
243
|
+
|
|
244
|
+
if (!timeVisible.value) {
|
|
245
|
+
timeFocused.value = false
|
|
246
|
+
emitCombinedValue()
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
emit('blur', { field, event })
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
function handleVisibleChange(field: 'date' | 'time', visible: boolean) {
|
|
254
|
+
if (field === 'date') {
|
|
255
|
+
dateVisible.value = visible
|
|
256
|
+
|
|
257
|
+
if (!visible && dateBlurred.value) {
|
|
258
|
+
dateFocused.value = false
|
|
259
|
+
}
|
|
260
|
+
} else {
|
|
261
|
+
timeVisible.value = visible
|
|
262
|
+
|
|
263
|
+
if (!visible && timeBlurred.value) {
|
|
264
|
+
timeFocused.value = false
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
emit('visible-change', { field, visible })
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
function emitCombinedValue() {
|
|
272
|
+
const value = dateValue.value && timeValue.value ? `${dateValue.value} ${timeValue.value}` : ''
|
|
273
|
+
emit('input', value)
|
|
274
|
+
emit('update:value', value)
|
|
275
|
+
emit('change', value)
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
function createDisabledDateHandler(disabledDate: OutlinedDateTimePickerDisabledDate | undefined) {
|
|
279
|
+
if (!disabledDate) {
|
|
280
|
+
return undefined
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
if (typeof disabledDate === 'function') {
|
|
284
|
+
return disabledDate
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
const boundary = normalizeBoundary(disabledDate)
|
|
288
|
+
return (value: Date) => value.getTime() < boundary - 86400000
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
function normalizeBoundary(value: Exclude<OutlinedDateTimePickerDisabledDate, (date: Date) => boolean>) {
|
|
292
|
+
if (value === 'nowDate') {
|
|
293
|
+
return Date.now()
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
if (value instanceof Date) {
|
|
297
|
+
return value.getTime()
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
if (typeof value === 'number') {
|
|
301
|
+
return value
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
return new Date(value).getTime()
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
function shouldLimitCurrentTime() {
|
|
308
|
+
return Boolean(props.disabledDate) && dateValue.value === dayjs().format('YYYY-MM-DD')
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
function toCssValue(value: OutlinedDateTimePickerCssValue | undefined) {
|
|
312
|
+
if (typeof value === 'number') {
|
|
313
|
+
return `${value}px`
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
return value
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
defineExpose<OutlinedDateTimePickerExpose>({
|
|
320
|
+
focusDate: () => {
|
|
321
|
+
datePickerRef.value?.focus?.()
|
|
322
|
+
},
|
|
323
|
+
focusTime: () => {
|
|
324
|
+
timePickerRef.value?.focus?.()
|
|
325
|
+
},
|
|
326
|
+
blurDate: () => {
|
|
327
|
+
datePickerRef.value?.blur?.()
|
|
328
|
+
},
|
|
329
|
+
blurTime: () => {
|
|
330
|
+
timePickerRef.value?.blur?.()
|
|
331
|
+
},
|
|
332
|
+
openDatePanel: () => {
|
|
333
|
+
datePickerRef.value?.handleOpen?.()
|
|
334
|
+
},
|
|
335
|
+
openTimePanel: () => {
|
|
336
|
+
timePickerRef.value?.handleOpen?.()
|
|
337
|
+
},
|
|
338
|
+
getDatePickerRef: () => datePickerRef.value,
|
|
339
|
+
getTimePickerRef: () => timePickerRef.value
|
|
340
|
+
})
|
|
341
|
+
</script>
|
|
342
|
+
|
|
343
|
+
<style scoped>
|
|
344
|
+
.outlined-date-time-picker {
|
|
345
|
+
display: flex;
|
|
346
|
+
align-items: center;
|
|
347
|
+
gap: 8px;
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
.outlined-date-time-picker__field {
|
|
351
|
+
position: relative;
|
|
352
|
+
flex: 1;
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
.outlined-date-time-picker__separator {
|
|
356
|
+
flex: 0 0 auto;
|
|
357
|
+
color: var(--el-text-color-regular);
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
.outlined-date-time-picker__label {
|
|
361
|
+
position: absolute;
|
|
362
|
+
left: -2px;
|
|
363
|
+
padding: 2px 5px;
|
|
364
|
+
border-radius: 2px;
|
|
365
|
+
background-color: #ffffff;
|
|
366
|
+
font-size: 12px;
|
|
367
|
+
line-height: 1;
|
|
368
|
+
transition: color 200ms cubic-bezier(0, 0, 0.2, 1), transform 200ms cubic-bezier(0, 0, 0.2, 1);
|
|
369
|
+
pointer-events: none;
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
.outlined-date-time-picker__label--floating {
|
|
373
|
+
top: 18px;
|
|
374
|
+
z-index: 1;
|
|
375
|
+
opacity: 1;
|
|
376
|
+
transform: translate(14px, -6px) scale(1);
|
|
377
|
+
color: var(--el-color-primary);
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
.outlined-date-time-picker__label--placeholder {
|
|
381
|
+
top: 50%;
|
|
382
|
+
left: 1px;
|
|
383
|
+
z-index: -1;
|
|
384
|
+
opacity: 0;
|
|
385
|
+
transform: translate(14px, 6px) scale(1);
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
.outlined-date-time-picker__label--filled {
|
|
389
|
+
color: var(--el-text-color-regular);
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
:deep(.outlined-date-time-picker__control.el-date-editor) {
|
|
393
|
+
width: 100%;
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
:deep(.outlined-date-time-picker__control .el-input__wrapper) {
|
|
397
|
+
position: relative;
|
|
398
|
+
min-height: inherit;
|
|
399
|
+
height: inherit;
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
:deep(.outlined-date-time-picker__control .el-input__prefix) {
|
|
403
|
+
position: absolute;
|
|
404
|
+
right: 0;
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
:deep(.outlined-date-time-picker__control .el-input__suffix) {
|
|
408
|
+
position: absolute;
|
|
409
|
+
right: 30px;
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
:deep(.outlined-date-time-picker__field--bordered .el-input__wrapper) {
|
|
413
|
+
box-shadow: none;
|
|
414
|
+
border-radius: 0;
|
|
415
|
+
border-bottom: 1px solid #cccccc;
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
:deep(.outlined-date-time-picker__field--bordered .el-input__wrapper.is-focus) {
|
|
419
|
+
border-bottom-color: var(--el-color-primary);
|
|
420
|
+
}
|
|
421
|
+
</style>
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
# OutlinedDateTimePicker
|
|
2
|
+
|
|
3
|
+
`OutlinedDateTimePicker` 是 `OutlinedForm` 系列里的日期时间组合控件,用来统一封装“先选日期,再补时间”的输入壳子、浮动标签、禁用日期规则和实例方法暴露。
|
|
4
|
+
|
|
5
|
+
## 适用场景
|
|
6
|
+
|
|
7
|
+
- 页面里经常出现“日期 + 时间”成对输入,但不想每次都重复写两个控件的布局和状态联动
|
|
8
|
+
- 需要统一日期时间输入框的浮动标签风格
|
|
9
|
+
- 需要基于当前日期限制时间可选范围
|
|
10
|
+
- 需要在页面层直接调用日期面板或时间面板的打开方法
|
|
11
|
+
|
|
12
|
+
## 基本用法
|
|
13
|
+
|
|
14
|
+
```vue
|
|
15
|
+
<script setup lang="ts">
|
|
16
|
+
import { ref } from 'vue'
|
|
17
|
+
import { OutlinedDateTimePicker, type OutlinedDateTimePickerExpose } from '@hbdlzy/ui'
|
|
18
|
+
|
|
19
|
+
const pickerRef = ref<OutlinedDateTimePickerExpose | null>(null)
|
|
20
|
+
const executeAt = ref('')
|
|
21
|
+
|
|
22
|
+
const openDatePanel = () => {
|
|
23
|
+
pickerRef.value?.openDatePanel()
|
|
24
|
+
}
|
|
25
|
+
</script>
|
|
26
|
+
|
|
27
|
+
<template>
|
|
28
|
+
<OutlinedDateTimePicker
|
|
29
|
+
ref="pickerRef"
|
|
30
|
+
v-model:value="executeAt"
|
|
31
|
+
placeholder="执行日期"
|
|
32
|
+
time-placeholder="执行时间"
|
|
33
|
+
:is-border="true"
|
|
34
|
+
:disabled-date="'nowDate'"
|
|
35
|
+
clearable
|
|
36
|
+
/>
|
|
37
|
+
|
|
38
|
+
<el-button @click="openDatePanel">
|
|
39
|
+
打开日期面板
|
|
40
|
+
</el-button>
|
|
41
|
+
</template>
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## Props
|
|
45
|
+
|
|
46
|
+
| 属性 | 类型 | 默认值 | 说明 |
|
|
47
|
+
| --- | --- | --- | --- |
|
|
48
|
+
| `value` | `string` | `''` | `v-model:value` 绑定值,格式为 `YYYY-MM-DD HH:mm` |
|
|
49
|
+
| `placeholder` | `string` | `''` | 日期部分占位文案,也会作为浮动标签主文案 |
|
|
50
|
+
| `label` | `string` | `''` | 自定义浮动标签文案,优先级高于 `placeholder` |
|
|
51
|
+
| `inputHeight` | `number` | `40` | 输入框高度 |
|
|
52
|
+
| `isBorder` | `boolean` | `false` | 是否启用下边框风格 |
|
|
53
|
+
| `disabledDate` | `string \| number \| Date \| ((date: Date) => boolean)` | `undefined` | 日期禁用规则,支持 `nowDate` |
|
|
54
|
+
| `separatorText` | `string` | `'-'` | 日期和时间之间的分隔文案 |
|
|
55
|
+
| `timePlaceholder` | `string` | `'时间'` | 时间部分占位文案 |
|
|
56
|
+
| `clearable` | `boolean` | `false` | 是否允许清空 |
|
|
57
|
+
| `marginBottom` | `string \| number` | `20` | 外层下边距 |
|
|
58
|
+
| `paddingTop` | `string \| number` | `20` | 外层上内边距,用于浮动标签留白 |
|
|
59
|
+
|
|
60
|
+
## Emits
|
|
61
|
+
|
|
62
|
+
| 事件 | 参数 | 说明 |
|
|
63
|
+
| --- | --- | --- |
|
|
64
|
+
| `input` | `string` | 输入值变化时触发 |
|
|
65
|
+
| `update:value` | `string` | `v-model:value` 同步事件 |
|
|
66
|
+
| `change` | `string` | 日期或时间确认变化后触发 |
|
|
67
|
+
| `focus` | `{ field: 'date' \| 'time'; event: FocusEvent }` | 某一侧输入聚焦时触发 |
|
|
68
|
+
| `blur` | `{ field: 'date' \| 'time'; event: FocusEvent }` | 某一侧输入失焦时触发 |
|
|
69
|
+
| `visible-change` | `{ field: 'date' \| 'time'; visible: boolean }` | 日期面板或时间面板开关变化时触发 |
|
|
70
|
+
|
|
71
|
+
## Expose
|
|
72
|
+
|
|
73
|
+
| 方法 | 说明 |
|
|
74
|
+
| --- | --- |
|
|
75
|
+
| `focusDate()` | 聚焦日期输入 |
|
|
76
|
+
| `focusTime()` | 聚焦时间输入 |
|
|
77
|
+
| `blurDate()` | 取消日期输入聚焦 |
|
|
78
|
+
| `blurTime()` | 取消时间输入聚焦 |
|
|
79
|
+
| `openDatePanel()` | 打开日期面板 |
|
|
80
|
+
| `openTimePanel()` | 打开时间面板 |
|
|
81
|
+
| `getDatePickerRef()` | 获取内部 `el-date-picker` 实例 |
|
|
82
|
+
| `getTimePickerRef()` | 获取内部 `el-time-picker` 实例 |
|
|
83
|
+
|
|
84
|
+
## 设计约束
|
|
85
|
+
|
|
86
|
+
- 组件内部只处理输入壳子、标签浮层、日期禁用和时间联动,不直接耦合接口、表单校验器或业务规则
|
|
87
|
+
- 如果只选了日期但没有选时间,组件会在日期确认时自动补一个当前 `HH:mm`
|
|
88
|
+
- 页面层如果需要更复杂的日期时间协议,建议继续在外层包业务组件,不要把业务判断塞回 `ui-core`
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import OutlinedDateTimePicker from './OutlinedDateTimePicker.vue'
|
|
2
|
+
|
|
3
|
+
export default OutlinedDateTimePicker
|
|
4
|
+
|
|
5
|
+
export type {
|
|
6
|
+
OutlinedDateTimePickerCssValue,
|
|
7
|
+
OutlinedDateTimePickerDisabledDate,
|
|
8
|
+
OutlinedDateTimePickerExpose,
|
|
9
|
+
OutlinedDateTimePickerProps,
|
|
10
|
+
OutlinedDateTimePickerValue
|
|
11
|
+
} from './OutlinedDateTimePicker.types'
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
export type OutlinedInputValue = string | number
|
|
2
|
+
|
|
3
|
+
export type OutlinedInputCssValue = string | number
|
|
4
|
+
|
|
5
|
+
export interface OutlinedInputProps {
|
|
6
|
+
value?: OutlinedInputValue
|
|
7
|
+
disabled?: boolean
|
|
8
|
+
regex?: RegExp
|
|
9
|
+
placeholder?: string
|
|
10
|
+
label?: string
|
|
11
|
+
maxlength?: string | number
|
|
12
|
+
max?: string | number
|
|
13
|
+
min?: string | number
|
|
14
|
+
typeInput?: string
|
|
15
|
+
showPassword?: boolean
|
|
16
|
+
isNumber?: boolean
|
|
17
|
+
inputHeight?: number
|
|
18
|
+
isBorder?: boolean
|
|
19
|
+
suffixText?: string
|
|
20
|
+
clearable?: boolean
|
|
21
|
+
showWordLimit?: boolean
|
|
22
|
+
marginBottom?: OutlinedInputCssValue
|
|
23
|
+
paddingTop?: OutlinedInputCssValue
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export interface OutlinedInputExpose {
|
|
27
|
+
focus: () => void
|
|
28
|
+
blur: () => void
|
|
29
|
+
clear: () => void
|
|
30
|
+
select: () => void
|
|
31
|
+
getInputRef: () => unknown | null
|
|
32
|
+
}
|