|
@@ -1,67 +1,37 @@
|
|
|
<template>
|
|
|
- <div class="date-input-container">
|
|
|
- <div
|
|
|
- class="date-picker"
|
|
|
- :class="bordered ? 'bordered' : ''"
|
|
|
- @click="isShowStartTime = true"
|
|
|
- :style="{ width: width, height: height, background: background, border: borderStyle, 'border-radius': borderRadius }">
|
|
|
- <!-- 日历图标 -->
|
|
|
- <img v-show="isShowCalendarIcon && position === 'left'" class="calendar left" src="../assets/img/common/rl.png" />
|
|
|
- <!-- 日期范围 -->
|
|
|
- <span class="text-container" :class="textClass">
|
|
|
- <span class="timePosition">{{ startDateText || (mode === 'time' ? '开始时间' : '开始日期') }}</span>
|
|
|
- <span class="spacer">{{ spacer }}</span>
|
|
|
- <span class="timePosition">{{ endDateText || (mode === 'time' ? '结束时间' : '结束日期') }}</span>
|
|
|
- </span>
|
|
|
-
|
|
|
- <div class="right-btn">
|
|
|
- <!-- 清除按钮 -->
|
|
|
- <img v-show="isShowClearBtn && startDateText" @click.stop="clearDate()" class="clear-date" src="../assets/img/login/user.png" />
|
|
|
-
|
|
|
- <!-- 日历图标 -->
|
|
|
- <img v-show="isShowCalendarIcon && position === 'right'" class="calendar right" src="../assets/img/common/rl.png" />
|
|
|
-
|
|
|
- <!-- 箭头图标 -->
|
|
|
- <van-icon v-show="isShowArrowIcon" name="arrow-down" class="arrow-down" />
|
|
|
- </div>
|
|
|
- </div>
|
|
|
-
|
|
|
- <van-popup v-model:show="isShowStartTime" round position="bottom">
|
|
|
- <van-date-picker
|
|
|
- v-model="startTime"
|
|
|
- :type="mode"
|
|
|
- :title="mode === 'time' ? '选择开始时间' : '选择开始日期'"
|
|
|
- @confirm="onConfirmStartDate"
|
|
|
- @cancel="isShowStartTime = false"
|
|
|
- />
|
|
|
- </van-popup>
|
|
|
-
|
|
|
- <van-popup v-model:show="isShowEndTime" round position="bottom">
|
|
|
- <van-date-picker
|
|
|
- v-model="endTime"
|
|
|
- :type="mode"
|
|
|
- :title="mode === 'time' ? '选择结束时间' : '选择结束日期'"
|
|
|
- @confirm="onConfirmEndDate"
|
|
|
- @cancel="isShowEndTime = false"
|
|
|
- />
|
|
|
- </van-popup>
|
|
|
+ <div class="date-input-container" @click="showDateRangePicker = true">
|
|
|
+ <div class="text">{{ startDateLabel ? startDateLabel : '请选择' }}</div>
|
|
|
+ <div class="spacer-text">{{ spacer }}</div>
|
|
|
+ <div class="text">{{ endDateLabel ? endDateLabel : '请选择' }}</div>
|
|
|
</div>
|
|
|
+ <van-popup v-model:show="showDateRangePicker" position="bottom">
|
|
|
+ <van-picker-group
|
|
|
+ v-if="showDateRangePicker"
|
|
|
+ title="预约日期"
|
|
|
+ :tabs="['开始日期', '结束日期']"
|
|
|
+ next-step-text="下一步"
|
|
|
+ @confirm="onConfirm"
|
|
|
+ @cancel="showDateRangePicker = false"
|
|
|
+ >
|
|
|
+ <van-date-picker v-model="startDate" />
|
|
|
+ <van-date-picker v-model="endDate" />
|
|
|
+ </van-picker-group>
|
|
|
+ </van-popup>
|
|
|
</template>
|
|
|
|
|
|
<script lang="ts" setup name="DateRangePicker">
|
|
|
-import dayjs from 'dayjs'
|
|
|
-import {onMounted, ref} from "vue";
|
|
|
+import {computed, onMounted, ref} from "vue";
|
|
|
|
|
|
const props = defineProps({
|
|
|
modelValue: [Array, String],
|
|
|
- // 模式: date-年月日 year-month - 年月 month-day - 月日 time - 时间 datehour年月日小时 datetime年月日时分
|
|
|
- mode: {
|
|
|
- type: String,
|
|
|
- default: 'date'
|
|
|
- },
|
|
|
+ // // 模式: date-年月日 year-month - 年月 month-day - 月日 time - 时间 datehour年月日小时 datetime年月日时分
|
|
|
+ // mode: {
|
|
|
+ // type: String,
|
|
|
+ // default: 'date'
|
|
|
+ // },
|
|
|
spacer: {
|
|
|
type: String,
|
|
|
- default: '-'
|
|
|
+ default: '至'
|
|
|
},
|
|
|
// 是否显示清除日期按钮
|
|
|
isShowClearBtn: {
|
|
@@ -73,212 +43,45 @@ const props = defineProps({
|
|
|
type: Boolean,
|
|
|
default: true
|
|
|
},
|
|
|
-
|
|
|
- // 是否显示箭头图标
|
|
|
- isShowArrowIcon: {
|
|
|
- type: Boolean,
|
|
|
- default: false
|
|
|
- },
|
|
|
-
|
|
|
// 是否显示边框
|
|
|
bordered: {
|
|
|
type: Boolean,
|
|
|
default: true
|
|
|
- },
|
|
|
-
|
|
|
- // 容器宽度
|
|
|
- width: {
|
|
|
- type: String,
|
|
|
- default: () => '100vw'
|
|
|
- },
|
|
|
-
|
|
|
- height: {
|
|
|
- type: String,
|
|
|
- default: () => '38px'
|
|
|
- },
|
|
|
-
|
|
|
- background: {
|
|
|
- type: String,
|
|
|
- default: () => '#ffffff'
|
|
|
- },
|
|
|
-
|
|
|
- borderStyle: {
|
|
|
- type: String,
|
|
|
- default: () => '1px solid #dddddd;'
|
|
|
- },
|
|
|
-
|
|
|
- borderRadius: {
|
|
|
- type: String,
|
|
|
- default: () => '5px'
|
|
|
- },
|
|
|
-
|
|
|
- // 日历图标的位置: left、right
|
|
|
- position: {
|
|
|
- type: String,
|
|
|
- default: () => 'right'
|
|
|
}
|
|
|
});
|
|
|
const emits = defineEmits(['update:modelValue', 'change']);
|
|
|
-let startDateText = ref(props.modelValue[0] || '');
|
|
|
-let endDateText = ref(props.modelValue[1] || '');
|
|
|
-let isShowStartTime = ref(false)
|
|
|
-let isShowEndTime = ref(false);
|
|
|
-let textClass = ref(''); // 日期样式
|
|
|
-let startTime = ref('');
|
|
|
-let endTime = ref('');
|
|
|
-let format = ref(''); // 日期格式
|
|
|
-
|
|
|
-onMounted(() => {
|
|
|
- textClass.value = props.position
|
|
|
- switch (props.mode) {
|
|
|
- case 'date': // 年月日
|
|
|
- format.value = 'YYYY-MM-DD'
|
|
|
- break
|
|
|
- case 'year-month': // 年月
|
|
|
- format.value = 'YYYY-MM'
|
|
|
- break
|
|
|
- case 'month-day': // 月日
|
|
|
- format.value = 'MM-DD'
|
|
|
- break
|
|
|
- case 'datetime': // 年月日小时分钟
|
|
|
- format.value = 'YYYY-MM-DD hh:mm'
|
|
|
- break
|
|
|
- case 'datehour': // 年月日小时
|
|
|
- format.value = 'YYYY-MM-DD hh'
|
|
|
- break
|
|
|
- case 'time': // 小时分钟
|
|
|
- format.value = undefined
|
|
|
- break
|
|
|
- }
|
|
|
-
|
|
|
- if (format.value) {
|
|
|
- startTime.value = props.modelValue[0] ? new Date(props.modelValue[0]) : new Date();
|
|
|
- endTime.value = props.modelValue[1] ? new Date(props.modelValue[1]) : new Date();
|
|
|
- } else {
|
|
|
- startTime.value = props.modelValue[0];
|
|
|
- endTime.value = props.modelValue[1];
|
|
|
- }
|
|
|
-})
|
|
|
-
|
|
|
-
|
|
|
-const onConfirmStartDate = (val) => {
|
|
|
- if (format.value) {
|
|
|
- startTime.value = dayjs(val).format(format.value)
|
|
|
- } else {
|
|
|
- startTime.value = val
|
|
|
- }
|
|
|
-
|
|
|
- startDateText.value = startTime.value
|
|
|
- isShowStartTime.value = false
|
|
|
- isShowEndTime.value = true
|
|
|
-};
|
|
|
-const onConfirmEndDate = (val) => {
|
|
|
- if (format.value) {
|
|
|
- endTime.value = dayjs(val).format(format.value)
|
|
|
- } else {
|
|
|
- endTime.value = val
|
|
|
- }
|
|
|
-
|
|
|
- endDateText.value = endTime.value
|
|
|
- isShowEndTime.value = false
|
|
|
- emits('update:modelValue', [startTime.value, endTime.value])
|
|
|
- emits('change', [startTime.value, endTime.value])
|
|
|
-};
|
|
|
-const clearDate = () => {
|
|
|
- startDateText.value = ''
|
|
|
- endDateText.value = ''
|
|
|
- emits('update:modelValue', ['', ''])
|
|
|
- emits('change', ['', ''])
|
|
|
+let showDateRangePicker = ref(false);
|
|
|
+let startDate = ref([]);
|
|
|
+let endDate = ref([]);
|
|
|
+let startDateLabel = ref();
|
|
|
+let endDateLabel = ref();
|
|
|
+// 日期范围选择
|
|
|
+const onConfirm = () => {
|
|
|
+ showDateRangePicker.value = false;
|
|
|
+ startDateLabel.value = startDate.value[0] +'-'+ startDate.value[1] + '-' + startDate.value[2];
|
|
|
+ endDateLabel.value = endDate.value[0] +'-'+ endDate.value[1] + '-' + endDate.value[2];
|
|
|
+ emits('update:modelValue', [startDateLabel.value, endDateLabel.value])
|
|
|
+ emits('change', [startDateLabel.value, endDateLabel.value])
|
|
|
}
|
|
|
</script>
|
|
|
|
|
|
<style lang="scss" scoped>
|
|
|
.date-input-container {
|
|
|
position: relative;
|
|
|
-
|
|
|
- .date-picker {
|
|
|
- position: relative;
|
|
|
- display: flex;
|
|
|
- align-items: center;
|
|
|
- justify-content: space-between;
|
|
|
- z-index: 499;
|
|
|
- text-indent: 5px;
|
|
|
- white-space: nowrap;
|
|
|
- padding: 0 5px;
|
|
|
- border-radius: 15px;
|
|
|
- &.bordered {
|
|
|
- border: 1px solid #dddddd;
|
|
|
- border-radius: 5px;
|
|
|
- }
|
|
|
-
|
|
|
- .text-container {
|
|
|
- display: inline-block;
|
|
|
- white-space: nowrap;
|
|
|
- text-overflow: ellipsis;
|
|
|
- overflow: hidden;
|
|
|
- width: 100%;
|
|
|
- display: flex;
|
|
|
- justify-content: space-around;
|
|
|
- align-items: center;
|
|
|
-
|
|
|
- &.left {
|
|
|
- margin-left: 15px;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- .timePosition {
|
|
|
- display: inline-block;
|
|
|
- vertical-align: middle;
|
|
|
- &:last-child {
|
|
|
- min-width: 75px;
|
|
|
- white-space: nowrap;
|
|
|
- text-overflow: ellipsis;
|
|
|
- overflow: hidden;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- .spacer {
|
|
|
- display: inline-block;
|
|
|
- height: 28px;
|
|
|
- margin: 0 5px;
|
|
|
- line-height: 28px;
|
|
|
- vertical-align: middle;
|
|
|
- }
|
|
|
-
|
|
|
- .date {
|
|
|
- font-style: normal;
|
|
|
- font-size: 14px;
|
|
|
- }
|
|
|
- .right-btn {
|
|
|
- display: flex;
|
|
|
- align-items: center;
|
|
|
- .clear-date {
|
|
|
- margin: 0 6px;
|
|
|
- width: 15px;
|
|
|
- height: 15px;
|
|
|
- vertical-align: middle;
|
|
|
- }
|
|
|
-
|
|
|
- .calendar {
|
|
|
- vertical-align: middle;
|
|
|
- margin-left: 6px;
|
|
|
- width: 15px;
|
|
|
- height: 14px;
|
|
|
-
|
|
|
- &.left {
|
|
|
- margin-right: 6px;
|
|
|
- }
|
|
|
-
|
|
|
- &.right {
|
|
|
- margin-left: 10px;
|
|
|
- }
|
|
|
- }
|
|
|
- .arrow-down {
|
|
|
- vertical-align: middle;
|
|
|
- width: 7px;
|
|
|
- right: 12px;
|
|
|
- }
|
|
|
- }
|
|
|
+ width: 100%;
|
|
|
+ height: 35px;
|
|
|
+ border: 1px solid #ccc;
|
|
|
+ border-radius: 4px;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ .text {
|
|
|
+ flex: 1;
|
|
|
+ font-size: 14px;
|
|
|
+ text-align: center;
|
|
|
+ }
|
|
|
+ .spacer-text {
|
|
|
+ font-size: 14px;
|
|
|
+ margin: 0 5px;
|
|
|
}
|
|
|
}
|
|
|
</style>
|