♻️(component): datePicker 加入年月范围选择,调整部分结构

This commit is contained in:
0o张不歪o0 2022-07-17 20:14:17 +08:00
parent aa549e6e80
commit 2d9d506059
4 changed files with 277 additions and 66 deletions

View File

@ -279,16 +279,16 @@ const closeRightMonthPanel = () => {
const footOnOk = () => { const footOnOk = () => {
let format = let format =
datePicker.type === "datetime" ? "YYYY-MM-DD HH:mm:ss" : "YYYY-MM-DD"; datePicker.type === "datetime" ? "YYYY-MM-DD HH:mm:ss" : "YYYY-MM-DD";
let startTimeVal = dayjs(startTime.day) let startTimeVal =startTime.day!==-1&&endTime.day!==-1?dayjs(startTime.day)
.hour(startTime.hms.hh) .hour(startTime.hms.hh)
.minute(startTime.hms.mm) .minute(startTime.hms.mm)
.second(startTime.hms.ss) .second(startTime.hms.ss)
.format(format); .format(format):'';
let endTimeVal = dayjs(endTime.day) let endTimeVal = startTime.day!==-1&&endTime.day!==-1?dayjs(endTime.day)
.hour(endTime.hms.hh) .hour(endTime.hms.hh)
.minute(endTime.hms.mm) .minute(endTime.hms.mm)
.second(endTime.hms.ss) .second(endTime.hms.ss)
.format(format); .format(format):'';
emits("update:startTime", startTimeVal); emits("update:startTime", startTimeVal);
emits("update:endTime", endTimeVal); emits("update:endTime", endTimeVal);
datePicker.ok(); datePicker.ok();
@ -296,11 +296,18 @@ const footOnOk = () => {
// //
const footOnNow = () => { const footOnNow = () => {
//Month.value = dayjs().month(); startTime.year=dayjs().year();
startTime.month=dayjs().month();
startTime.day=new Date(new Date().toDateString()).getTime();
startTime.hms.hh=dayjs().hour();
startTime.hms.mm=dayjs().minute();
startTime.hms.ss=dayjs().second();
endTime.day=-1;
}; };
// //
const footOnClear = () => { const footOnClear = () => {
//Month.value = '' startTime.day=-1;
endTime.day=-1;
}; };
</script> </script>

View File

@ -0,0 +1,221 @@
<template>
<div class="layui-laydate layui-laydate-range">
<div style="display: flex">
<div class="layui-laydate-main laydate-main-list-0">
<div class="layui-laydate-header">
<i class="layui-icon laydate-icon laydate-prev-y" @click="changeYear(-1)"></i>
<div class="laydate-set-ym">
<lay-dropdown ref="dropdownYearPanelRefLeft">
<span class="laydate-range-time">{{ startTime.year || "--" }}</span>
<template #content>
<YearPanel class="time-panel" v-model="startTime.year" @ok="closeLeftYearPanel"></YearPanel>
</template>
</lay-dropdown>
</div>
</div>
<div class="layui-laydate-content" style="height: 220px">
<ul class="layui-laydate-list laydate-month-list">
<li v-for="item of MONTH_NAME" :key="item" :data-unix="getUnix(item, 'left')"
:class="{ 'layui-this': getUnix(item, 'left') === startTime.unix || getUnix(item, 'left') === endTime.unix, 'laydate-range-hover': ifHasRangeHoverClass(getUnix(item, 'left')) }"
@click="handleMonthClick(getUnix(item, 'left'))" @mouseenter="monthItemMouseEnter($event, item)">
{{ item.slice(0, 3) }}
</li>
</ul>
</div>
</div>
<div class="layui-laydate-main laydate-main-list-0">
<div class="layui-laydate-header">
<div class="laydate-set-ym">
<lay-dropdown ref="dropdownYearPanelRefRight">
<span class="laydate-range-time">{{ startTime.year + 1 }}</span>
<template #content>
<YearPanel class="time-panel" v-model="endTime.year" @ok="closeRightYearPanel"></YearPanel>
</template>
</lay-dropdown>
</div>
<i class="layui-icon laydate-icon laydate-next-y" @click="changeYear(1)"></i>
</div>
<div class="layui-laydate-content" style="height: 220px">
<ul class="layui-laydate-list laydate-month-list">
<li v-for="item of MONTH_NAME" :key="item" :data-unix="getUnix(item, 'right')"
:class="{ 'layui-this': getUnix(item, 'right') === startTime.unix || getUnix(item, 'right') === endTime.unix, 'laydate-range-hover': ifHasRangeHoverClass(getUnix(item, 'right')) }"
@click="handleMonthClick(getUnix(item, 'right'))" @mouseenter="monthItemMouseEnter($event, item)">
{{ item.slice(0, 3) }}
</li>
</ul>
</div>
</div>
</div>
<PanelFoot @ok="footOnOk" @now="footOnNow" @clear="footOnClear">
<span v-if="startTime.unix !== -1" class="layui-laydate-preview">
{{ dayjs(startTime.unix).format("YYYY-MM-DD") }}
{{ datePicker.rangeSeparator }}
<template v-if="endTime.unix !== -1">
{{ dayjs(endTime.unix).format("YYYY-MM-DD") }}
</template>
<template v-else> -- </template>
</span>
</PanelFoot>
</div>
</template>
<script lang="ts">
export default {
name: "MonthRange",
};
</script>
<script lang="ts" setup>
import { inject, reactive, ref, watch, computed } from "vue";
import { provideType } from "../interface";
import PanelFoot from "./PanelFoot.vue";
import YearPanel from "./YearPanel.vue";
import dayjs from "dayjs";
export interface DateRangeProps {
startTime: string;
endTime: string;
}
const props = withDefaults(defineProps<DateRangeProps>(), {});
const emits = defineEmits([
"update:modelValue",
"update:startTime",
"update:endTime",
]);
const datePicker: provideType = inject("datePicker") as provideType;
const startTime = reactive({
year: props.startTime ? dayjs(props.startTime).year() : dayjs().year(),
unix: props.startTime ? dayjs(props.startTime).hour(0).minute(0).second(0).valueOf() : -1,
});
const endTime = reactive({
year: props.endTime ? dayjs(props.endTime).year() : dayjs().year() + 1,
unix: props.startTime ? dayjs(props.endTime).hour(0).minute(0).second(0).valueOf() : -1,
});
let hoverMonth = ref(-1);
const MONTH_NAME = [
"1月",
"2月",
"3月",
"4月",
"5月",
"6月",
"7月",
"8月",
"9月",
"10月",
"11月",
"12月",
];
//
const changeYear = (num: number) => {
startTime.year += num;
};
//
const handleMonthClick = (item: number) => {
if (startTime.unix === -1 && endTime.unix === -1) {
startTime.unix = item;
} else if (startTime.unix !== -1 && endTime.unix !== -1) {
hoverMonth.value = -1;
startTime.unix = item;
endTime.unix = -1;
} else if (startTime.unix !== -1 && endTime.unix === -1) {
endTime.unix = item;
if (item < startTime.unix) {
//swap
const first = startTime.unix;
const last = item;
startTime.unix = last;
endTime.unix = first;
}
}
};
// ,
watch(
() => [props.startTime, props.endTime],
() => {
startTime.year = props.startTime ? dayjs(props.startTime).year() : dayjs().year();
startTime.unix = props.startTime ? dayjs(props.startTime).hour(0).minute(0).second(0).valueOf() : -1;
endTime.year = props.endTime ? dayjs(props.endTime).year() : dayjs().year();
endTime.unix = props.startTime ? dayjs(props.endTime).hour(0).minute(0).second(0).valueOf() : -1;
},
);
//
const dropdownYearPanelRefLeft = ref();
const dropdownYearPanelRefRight = ref();
const closeLeftYearPanel = () => {
if (dropdownYearPanelRefLeft.value) dropdownYearPanelRefLeft.value.hide();
};
const closeRightYearPanel = () => {
if (dropdownYearPanelRefRight.value) dropdownYearPanelRefRight.value.hide();
startTime.year = endTime.year;
};
//
const footOnOk = () => {
let format = "YYYY-MM";
let startTimeVal = startTime.unix !== -1 && endTime.unix !== -1 ? dayjs(startTime.unix).format(format) : '';
let endTimeVal = endTime.unix !== -1 && endTime.unix !== -1 ? dayjs(endTime.unix).format(format) : '';
emits("update:startTime", startTimeVal);
emits("update:endTime", endTimeVal);
datePicker.ok();
};
//
const footOnNow = () => {
startTime.year = dayjs().year();
startTime.unix = dayjs(startTime.year + '-' + (dayjs().month() + 1)).valueOf();
endTime.unix = -1;
hoverMonth.value = -1;
};
//
const footOnClear = () => {
startTime.unix = -1;
endTime.unix = -1;
hoverMonth.value = -1;
};
const monthItemMouseEnter = (event: MouseEvent, item: any) => {
if (!datePicker.range) {
return;
}
if (startTime.unix === -1) {
return;
}
if (hoverMonth.value !== -1 && endTime.unix !== -1) {
hoverMonth.value = -1;
return;
}
hoverMonth.value = parseInt((event.target as HTMLElement).dataset.unix as string);
};
const ifHasRangeHoverClass = computed(() => {
return function (item: any) {
if (!datePicker.range) {
return false;
}
if (startTime.unix === -1) {
return false;
}
if (hoverMonth.value === -1 && endTime.unix === -1) {
return false;
}
let hover = endTime.unix !== -1 ? endTime.unix : hoverMonth.value;
let max = startTime.unix > hover ? startTime.unix : hover;
let min = startTime.unix < hover ? startTime.unix : hover;
if (item >= min && item <= max) {
return true;
}
return false;
};
});
const getUnix = computed(() => {
return function (item: any, position: 'left' | 'right') {
let month = MONTH_NAME.indexOf(item);
let year = position === 'left' ? startTime.year : startTime.year + 1;
return dayjs(year + '-' + (month + 1)).valueOf();
}
})
</script>

View File

@ -1,68 +1,34 @@
<template> <template>
<div> <div>
<lay-dropdown <lay-dropdown ref="dropdownRef" :disabled="disabled" :autoFitMinWidth="false">
ref="dropdownRef" <lay-input readonly :name="name" :model-value="(dateValue as string)" :placeholder="placeholder"
:disabled="disabled" prefix-icon="layui-icon-date" :disabled="disabled" v-if="!range">
:autoFitMinWidth="false"
>
<lay-input
readonly
:name="name"
:model-value="(dateValue as string)"
:placeholder="placeholder"
prefix-icon="layui-icon-date"
:disabled="disabled"
v-if="!range"
>
</lay-input> </lay-input>
<div class="laydate-range-inputs" v-else> <div class="laydate-range-inputs" v-else>
<lay-input <lay-input readonly :name="name" :model-value="dateValue[0]" :disabled="disabled" class="start-input">
readonly
:name="name"
:model-value="dateValue[0]"
:disabled="disabled"
class="start-input"
>
</lay-input> </lay-input>
<span class="range-separator">{{ rangeSeparator }}</span> <span class="range-separator">{{ rangeSeparator }}</span>
<lay-input <lay-input readonly :name="name" :model-value="dateValue[1]" :disabled="disabled" class="end-input">
readonly
:name="name"
:model-value="dateValue[1]"
:disabled="disabled"
class="end-input"
>
</lay-input> </lay-input>
</div> </div>
<template #content> <template #content>
<!-- 日期选择 --> <!-- 日期选择 -->
<DatePanel <DatePanel v-if="!range && (showPanel === 'date' || showPanel === 'datetime')" v-model="currentDay"></DatePanel>
v-if="!range && (showPanel === 'date' || showPanel === 'datetime')"
v-model="currentDay"
></DatePanel>
<!-- 时间选择 --> <!-- 时间选择 -->
<TimePanel <TimePanel v-if="!range && showPanel === 'time'" v-model="hms"></TimePanel>
v-if="!range && showPanel === 'time'"
v-model="hms"
></TimePanel>
<!-- 年份选择器 --> <!-- 年份选择器 -->
<YearPanel <YearPanel v-if="!range && (showPanel === 'year' || showPanel === 'yearmonth')" v-model="currentYear">
v-if="!range && (showPanel === 'year' || showPanel === 'yearmonth')"
v-model="currentYear"
>
</YearPanel> </YearPanel>
<!-- 月份选择器 --> <!-- 月份选择器 -->
<MonthPanel <MonthPanel v-if="!range && showPanel === 'month'" v-model="currentMonth"></MonthPanel>
v-if="!range && showPanel === 'month'"
v-model="currentMonth"
></MonthPanel>
<!-- 范围选择 --> <!-- 范围选择 -->
<DateRange <DateRange v-if="range && (showPanel === 'date' || showPanel === 'datetime')"
v-if="range && (showPanel === 'date' || showPanel === 'datetime')" v-model:startTime="rangeValue.first" v-model:endTime="rangeValue.last"></DateRange>
v-model:startTime="rangeValue.first"
v-model:endTime="rangeValue.last" <MonthRange v-if="range && showPanel === 'yearmonth'" v-model:startTime="rangeValue.first"
></DateRange> v-model:endTime="rangeValue.last">
</MonthRange>
</template> </template>
</lay-dropdown> </lay-dropdown>
</div> </div>
@ -95,6 +61,7 @@ import TimePanel from "./components/TimePanel.vue";
import YearPanel from "./components/YearPanel.vue"; import YearPanel from "./components/YearPanel.vue";
import MonthPanel from "./components/MonthPanel.vue"; import MonthPanel from "./components/MonthPanel.vue";
import DateRange from "./components/DateRange.vue"; import DateRange from "./components/DateRange.vue";
import MonthRange from "./components/MonthRange.vue";
export interface LayDatePickerProps { export interface LayDatePickerProps {
type?: "date" | "datetime" | "year" | "time" | "month" | "yearmonth"; type?: "date" | "datetime" | "year" | "time" | "month" | "yearmonth";
@ -198,9 +165,21 @@ const getDateValueByRange = () => {
unWatch = true; unWatch = true;
if (rangeValue.first === "" || rangeValue.last === "") { if (rangeValue.first === "" || rangeValue.last === "") {
dateValue.value = ["", ""]; dateValue.value = ["", ""];
$emits("update:modelValue", dateValue.value);
return; return;
} }
let format = props.type === "datetime" ? "YYYY-MM-DD HH:mm:ss" : "YYYY-MM-DD"; let format ="YYYY-MM-DD";
switch (props.type) {
case "date":
format = 'YYYY-MM-DD';
break;
case "datetime":
format = 'YYYY-MM-DD HH:mm:ss';
break;
case "yearmonth":
format = 'YYYY-MM';
break;
}
dateValue.value = [ dateValue.value = [
dayjs(rangeValue.first).format(format), dayjs(rangeValue.first).format(format),
dayjs(rangeValue.last).format(format), dayjs(rangeValue.last).format(format),
@ -233,7 +212,7 @@ watch(
() => props.type, () => props.type,
() => { () => {
showPanel.value = props.type; showPanel.value = props.type;
if (props.type === "yearmonth") { if (props.type === "yearmonth" && !props.range) {
showPanel.value = "year"; showPanel.value = "year";
} }
}, },

View File

@ -234,13 +234,17 @@ export default {
<lay-date-picker v-model="rangeTime2" range type="datetime" placeholder="type : datetime"></lay-date-picker> <lay-date-picker v-model="rangeTime2" range type="datetime" placeholder="type : datetime"></lay-date-picker>
<span style="margin-left:10px">modelValue:{{rangeTime2}}</span> <span style="margin-left:10px">modelValue:{{rangeTime2}}</span>
</div> </div>
<lay-button @click="rangeTime2=['2001-02-01','2001-03-1']">test</lay-button> <div style="display:flex; align-items: center;margin-bottom: 5px;">
<lay-date-picker v-model="rangeTime3" range type="yearmonth" placeholder="type : datetime"></lay-date-picker>
<span style="margin-left:10px">modelValue:{{rangeTime3}}</span>
</div>
</template> </template>
<script setup> <script setup>
import { ref } from 'vue' import { ref } from 'vue'
const rangeTime1 = ref([]); const rangeTime1 = ref([]);
const rangeTime2 = ref(['2001-01-01','2001-02-1']); const rangeTime2 = ref(['2001-01-01','2001-02-1']);
const rangeTime3 = ref(['2022-01-01','2023-02-1']);
</script> </script>
::: :::