init
This commit is contained in:
148
src/component/datePicker/components/DatePanel.vue
Normal file
148
src/component/datePicker/components/DatePanel.vue
Normal file
@@ -0,0 +1,148 @@
|
||||
<template>
|
||||
<div class="layui-laydate">
|
||||
<div class="layui-laydate-main laydate-main-list-0">
|
||||
<div class="layui-laydate-header">
|
||||
<i
|
||||
class="layui-icon laydate-icon laydate-prev-y"
|
||||
@click="changeYearOrMonth('year', -1)"
|
||||
></i
|
||||
>
|
||||
<i
|
||||
class="layui-icon laydate-icon laydate-prev-m"
|
||||
@click="changeYearOrMonth('month', -1)"
|
||||
></i
|
||||
>
|
||||
<div class="laydate-set-ym">
|
||||
<span @click="datePicker.showPanel.value = 'year'"
|
||||
>{{ datePicker.currentYear.value }} {{ t("datePicker.year") }}</span
|
||||
>
|
||||
<span @click="datePicker.showPanel.value = 'month'">
|
||||
{{ MONTH_NAME[datePicker.currentMonth.value] }}
|
||||
</span>
|
||||
</div>
|
||||
<i
|
||||
class="layui-icon laydate-icon laydate-next-m"
|
||||
@click="changeYearOrMonth('month', 1)"
|
||||
></i
|
||||
>
|
||||
<i
|
||||
class="layui-icon laydate-icon laydate-next-y"
|
||||
@click="changeYearOrMonth('year', 1)"
|
||||
></i
|
||||
>
|
||||
</div>
|
||||
<DateContent
|
||||
:date-list="dateList"
|
||||
v-model="Day"
|
||||
@simple="footOnOk"
|
||||
@update:model-value="ChildUpdateModelValue"
|
||||
></DateContent>
|
||||
<PanelFoot @ok="footOnOk" @now="footOnNow" @clear="footOnClear">
|
||||
<span
|
||||
v-if="datePicker.type === 'datetime'"
|
||||
@click="datePicker.showPanel.value = 'time'"
|
||||
class="laydate-btns-time"
|
||||
>{{ t("datePicker.selectTime") }}</span
|
||||
>
|
||||
</PanelFoot>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
export default {
|
||||
name: "DatePanel",
|
||||
};
|
||||
</script>
|
||||
<script lang="ts" setup>
|
||||
import { computed, inject, ref, watch } from "vue";
|
||||
import { provideType } from "../interface";
|
||||
import { setDateList } from "../day";
|
||||
import PanelFoot from "./PanelFoot.vue";
|
||||
import DateContent from "./components/DateContent.vue";
|
||||
import dayjs from "dayjs";
|
||||
import { useI18n } from "../../../language";
|
||||
|
||||
export interface TimePanelProps {
|
||||
modelValue: number;
|
||||
}
|
||||
|
||||
const { t } = useI18n();
|
||||
const props = withDefaults(defineProps<TimePanelProps>(), {});
|
||||
const emits = defineEmits(["update:modelValue", "ok"]);
|
||||
const Day = ref(props.modelValue);
|
||||
const datePicker: provideType = inject("datePicker") as provideType;
|
||||
const dateList = ref<any>([]);
|
||||
|
||||
const MONTH_NAME = computed(() => [
|
||||
t("datePicker.january"),
|
||||
t("datePicker.february"),
|
||||
t("datePicker.march"),
|
||||
t("datePicker.april"),
|
||||
t("datePicker.may"),
|
||||
t("datePicker.june"),
|
||||
t("datePicker.july"),
|
||||
t("datePicker.august"),
|
||||
t("datePicker.september"),
|
||||
t("datePicker.october"),
|
||||
t("datePicker.november"),
|
||||
t("datePicker.december"),
|
||||
]);
|
||||
|
||||
// 监听年月, 刷新日期
|
||||
watch(
|
||||
[datePicker.currentYear, datePicker.currentMonth],
|
||||
() => {
|
||||
dateList.value = setDateList(
|
||||
datePicker.currentYear.value,
|
||||
datePicker.currentMonth.value
|
||||
);
|
||||
},
|
||||
{ immediate: true }
|
||||
);
|
||||
|
||||
watch(
|
||||
() => props.modelValue,
|
||||
() => {
|
||||
Day.value = props.modelValue;
|
||||
}
|
||||
);
|
||||
|
||||
// 切换年月
|
||||
const changeYearOrMonth = (type: "year" | "month", num: number) => {
|
||||
if (type === "year") {
|
||||
datePicker.currentYear.value += num;
|
||||
} else {
|
||||
let month = datePicker.currentMonth.value + num;
|
||||
if (month > 11) {
|
||||
month = 0;
|
||||
datePicker.currentYear.value++;
|
||||
} else if (month < 0) {
|
||||
month = 11;
|
||||
datePicker.currentYear.value--;
|
||||
}
|
||||
datePicker.currentMonth.value = month;
|
||||
}
|
||||
};
|
||||
|
||||
//关闭回调
|
||||
const footOnOk = () => {
|
||||
emits("update:modelValue", Day.value);
|
||||
datePicker.ok();
|
||||
};
|
||||
|
||||
//现在回调
|
||||
const footOnNow = () => {
|
||||
datePicker.currentYear.value = dayjs().year();
|
||||
datePicker.currentMonth.value = dayjs().month();
|
||||
Day.value = new Date(new Date().toDateString()).getTime();
|
||||
};
|
||||
|
||||
//清空回调
|
||||
const footOnClear = () => {
|
||||
Day.value = -1;
|
||||
};
|
||||
|
||||
const ChildUpdateModelValue = () => {
|
||||
emits("update:modelValue", Day.value);
|
||||
};
|
||||
</script>
|
||||
350
src/component/datePicker/components/DateRange.vue
Normal file
350
src/component/datePicker/components/DateRange.vue
Normal file
@@ -0,0 +1,350 @@
|
||||
<template>
|
||||
<div
|
||||
class="layui-laydate layui-laydate-range"
|
||||
:class="'layui-laydate-range-' + datePicker.showPanel.value"
|
||||
>
|
||||
<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="changeYearOrMonth('year', -1)"
|
||||
></i
|
||||
>
|
||||
<i
|
||||
class="layui-icon laydate-icon laydate-prev-m"
|
||||
@click="changeYearOrMonth('month', -1)"
|
||||
></i
|
||||
>
|
||||
<div class="laydate-set-ym">
|
||||
<lay-dropdown ref="dropdownYearPanelRefLeft">
|
||||
<span class="laydate-range-time"
|
||||
>{{ startTime.year || "--" }} {{ t("datePicker.year") }}</span
|
||||
>
|
||||
<template #content>
|
||||
<YearPanel
|
||||
class="time-panel"
|
||||
v-model="startTime.year"
|
||||
@ok="closeTimePanel"
|
||||
></YearPanel>
|
||||
</template>
|
||||
</lay-dropdown>
|
||||
<lay-dropdown ref="dropdownMonthPanelRefLeft">
|
||||
<span class="laydate-range-time">
|
||||
{{ MONTH_NAME[startTime.month] }}</span
|
||||
>
|
||||
<template #content>
|
||||
<MonthPanel
|
||||
class="time-panel"
|
||||
v-model="startTime.month"
|
||||
@ok="closeTimePanel"
|
||||
></MonthPanel>
|
||||
</template>
|
||||
</lay-dropdown>
|
||||
<lay-dropdown
|
||||
ref="dropdownTimePanelRefLeft"
|
||||
v-if="datePicker.type === 'datetime'"
|
||||
>
|
||||
<span class="laydate-range-time">
|
||||
{{
|
||||
dayjs()
|
||||
.hour(startTime.hms.hh)
|
||||
.minute(startTime.hms.mm)
|
||||
.second(startTime.hms.ss)
|
||||
.format("HH:mm:ss")
|
||||
}}
|
||||
</span>
|
||||
<template #content>
|
||||
<TimePanel
|
||||
v-model="startTime.hms"
|
||||
class="time-panel"
|
||||
@ok="closeTimePanel"
|
||||
></TimePanel>
|
||||
</template>
|
||||
</lay-dropdown>
|
||||
</div>
|
||||
</div>
|
||||
<DateContent
|
||||
:date-list="prevDateList"
|
||||
v-model:hoverDate="hoverDate"
|
||||
v-model:startDate="startTime.day"
|
||||
v-model:endDate="endTime.day"
|
||||
></DateContent>
|
||||
</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.month + 1 > 11 ? startTime.year + 1 : startTime.year
|
||||
}}
|
||||
{{ t("datePicker.year") }}</span
|
||||
>
|
||||
<template #content>
|
||||
<YearPanel
|
||||
class="time-panel"
|
||||
v-model="endTime.year"
|
||||
@ok="closeRightYearPanel"
|
||||
></YearPanel>
|
||||
</template>
|
||||
</lay-dropdown>
|
||||
<lay-dropdown ref="dropdownMonthPanelRefRight">
|
||||
<span class="laydate-range-time">
|
||||
{{
|
||||
MONTH_NAME[
|
||||
startTime.month + 1 > 11
|
||||
? startTime.month + 1 - 12
|
||||
: startTime.month + 1
|
||||
]
|
||||
}}
|
||||
</span>
|
||||
<template #content>
|
||||
<MonthPanel
|
||||
class="time-panel"
|
||||
v-model="endTime.month"
|
||||
@ok="closeRightMonthPanel"
|
||||
></MonthPanel>
|
||||
</template>
|
||||
</lay-dropdown>
|
||||
<lay-dropdown
|
||||
ref="dropdownTimePanelRefRight"
|
||||
v-if="datePicker.type === 'datetime'"
|
||||
>
|
||||
<span class="laydate-range-time">
|
||||
{{
|
||||
dayjs()
|
||||
.hour(endTime.hms.hh)
|
||||
.minute(endTime.hms.mm)
|
||||
.second(endTime.hms.ss)
|
||||
.format("HH:mm:ss")
|
||||
}}
|
||||
</span>
|
||||
<template #content>
|
||||
<TimePanel
|
||||
v-model="endTime.hms"
|
||||
class="time-panel"
|
||||
@ok="closeTimePanel"
|
||||
></TimePanel>
|
||||
</template>
|
||||
</lay-dropdown>
|
||||
</div>
|
||||
<i
|
||||
class="layui-icon laydate-icon laydate-next-m"
|
||||
@click="changeYearOrMonth('month', 1)"
|
||||
></i
|
||||
>
|
||||
<i
|
||||
class="layui-icon laydate-icon laydate-next-y"
|
||||
@click="changeYearOrMonth('year', 1)"
|
||||
></i
|
||||
>
|
||||
</div>
|
||||
<DateContent
|
||||
:date-list="nextDateList"
|
||||
v-model:hoverDate="hoverDate"
|
||||
v-model:startDate="startTime.day"
|
||||
v-model:endDate="endTime.day"
|
||||
></DateContent>
|
||||
</div>
|
||||
</div>
|
||||
<PanelFoot @ok="footOnOk" @now="footOnNow" @clear="footOnClear">
|
||||
<span v-if="startTime.day !== -1" class="layui-laydate-preview">
|
||||
{{ dayjs(startTime.day).format("YYYY-MM-DD") }}
|
||||
<template v-if="datePicker.type === 'datetime'">
|
||||
{{
|
||||
dayjs()
|
||||
.hour(startTime.hms.hh)
|
||||
.minute(startTime.hms.mm)
|
||||
.second(startTime.hms.ss)
|
||||
.format("HH:mm:ss")
|
||||
}}
|
||||
</template>
|
||||
{{ datePicker.rangeSeparator }}
|
||||
<template v-if="endTime.day !== -1">
|
||||
{{ dayjs(endTime.day).format("YYYY-MM-DD") }}
|
||||
<template v-if="datePicker.type === 'datetime'">
|
||||
{{
|
||||
dayjs()
|
||||
.hour(endTime.hms.hh)
|
||||
.minute(endTime.hms.mm)
|
||||
.second(endTime.hms.ss)
|
||||
.format("HH:mm:ss")
|
||||
}}
|
||||
</template>
|
||||
</template>
|
||||
<template v-else> -- </template>
|
||||
</span>
|
||||
</PanelFoot>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
export default {
|
||||
name: "DateRange",
|
||||
};
|
||||
</script>
|
||||
<script lang="ts" setup>
|
||||
import { computed, inject, reactive, ref, watch } from "vue";
|
||||
import { provideType } from "../interface";
|
||||
import { setDateList } from "../day";
|
||||
import PanelFoot from "./PanelFoot.vue";
|
||||
import DateContent from "./components/DateContent.vue";
|
||||
import TimePanel from "./TimePanel.vue";
|
||||
import YearPanel from "./YearPanel.vue";
|
||||
import MonthPanel from "./MonthPanel.vue";
|
||||
import LayDropdown from "../../dropdown/index.vue";
|
||||
import dayjs from "dayjs";
|
||||
import { useI18n } from "../../../language";
|
||||
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 { t } = useI18n();
|
||||
|
||||
const MONTH_NAME = computed(() => [
|
||||
t("datePicker.january"),
|
||||
t("datePicker.february"),
|
||||
t("datePicker.march"),
|
||||
t("datePicker.april"),
|
||||
t("datePicker.may"),
|
||||
t("datePicker.june"),
|
||||
t("datePicker.july"),
|
||||
t("datePicker.august"),
|
||||
t("datePicker.september"),
|
||||
t("datePicker.october"),
|
||||
t("datePicker.november"),
|
||||
t("datePicker.december"),
|
||||
]);
|
||||
|
||||
const prevDateList = ref<any>([]);
|
||||
const nextDateList = ref<any>([]);
|
||||
const startTime = reactive({
|
||||
year: props.startTime ? dayjs(props.startTime).year() : dayjs().year(),
|
||||
month: props.startTime ? dayjs(props.startTime).month() : dayjs().month(),
|
||||
day: props.startTime ? dayjs(props.startTime).startOf("day").valueOf() : -1,
|
||||
hms: {
|
||||
hh: props.startTime ? dayjs(props.startTime).hour() : 0,
|
||||
mm: props.startTime ? dayjs(props.startTime).minute() : 0,
|
||||
ss: props.startTime ? dayjs(props.startTime).second() : 0,
|
||||
},
|
||||
});
|
||||
const endTime = reactive({
|
||||
year: props.endTime ? dayjs(props.endTime).year() : dayjs().year(),
|
||||
month: props.endTime ? dayjs(props.endTime).month() : dayjs().month(),
|
||||
day: props.endTime ? dayjs(props.endTime).startOf("day").valueOf() : -1,
|
||||
hms: {
|
||||
hh: props.endTime ? dayjs(props.endTime).hour() : 0,
|
||||
mm: props.endTime ? dayjs(props.endTime).minute() : 0,
|
||||
ss: props.endTime ? dayjs(props.endTime).second() : 0,
|
||||
},
|
||||
});
|
||||
const hoverDate = ref(-1);
|
||||
|
||||
// 切换年月
|
||||
const changeYearOrMonth = (type: "year" | "month", num: number) => {
|
||||
if (type === "year") {
|
||||
startTime.year += num;
|
||||
} else {
|
||||
let month = startTime.month + num;
|
||||
if (month > 11) {
|
||||
month = 0;
|
||||
startTime.year++;
|
||||
} else if (month < 0) {
|
||||
month = 11;
|
||||
startTime.year--;
|
||||
}
|
||||
startTime.month = month;
|
||||
}
|
||||
};
|
||||
|
||||
// 监听年月, 刷新日期
|
||||
watch(
|
||||
() => [startTime.year, startTime.month],
|
||||
() => {
|
||||
prevDateList.value = setDateList(startTime.year, startTime.month);
|
||||
nextDateList.value = setDateList(startTime.year, startTime.month + 1);
|
||||
},
|
||||
{ immediate: true }
|
||||
);
|
||||
|
||||
//关闭选择时间的面板
|
||||
const dropdownTimePanelRefLeft = ref();
|
||||
const dropdownTimePanelRefRight = ref();
|
||||
const dropdownYearPanelRefLeft = ref();
|
||||
const dropdownYearPanelRefRight = ref();
|
||||
const dropdownMonthPanelRefLeft = ref();
|
||||
const dropdownMonthPanelRefRight = ref();
|
||||
const closeTimePanel = () => {
|
||||
if (dropdownTimePanelRefLeft.value) dropdownTimePanelRefLeft.value.hide();
|
||||
if (dropdownTimePanelRefRight.value) dropdownTimePanelRefRight.value.hide();
|
||||
if (dropdownYearPanelRefLeft.value) dropdownYearPanelRefLeft.value.hide();
|
||||
if (dropdownMonthPanelRefLeft.value) dropdownMonthPanelRefLeft.value.hide();
|
||||
};
|
||||
const closeRightYearPanel = () => {
|
||||
if (dropdownYearPanelRefRight.value) dropdownYearPanelRefRight.value.hide();
|
||||
startTime.year = endTime.year;
|
||||
};
|
||||
const closeRightMonthPanel = () => {
|
||||
dropdownMonthPanelRefRight.value.hide();
|
||||
let month = endTime.month - 1;
|
||||
if (month > 11) {
|
||||
month = 0;
|
||||
startTime.year++;
|
||||
} else if (month < 0) {
|
||||
month = 11;
|
||||
startTime.year--;
|
||||
}
|
||||
startTime.month = month;
|
||||
};
|
||||
|
||||
//关闭回调
|
||||
const footOnOk = () => {
|
||||
let format =
|
||||
datePicker.type === "datetime" ? "YYYY-MM-DD HH:mm:ss" : "YYYY-MM-DD";
|
||||
let startTimeVal =
|
||||
startTime.day !== -1 && endTime.day !== -1
|
||||
? dayjs(startTime.day)
|
||||
.hour(startTime.hms.hh)
|
||||
.minute(startTime.hms.mm)
|
||||
.second(startTime.hms.ss)
|
||||
.format(format)
|
||||
: "";
|
||||
let endTimeVal =
|
||||
startTime.day !== -1 && endTime.day !== -1
|
||||
? dayjs(endTime.day)
|
||||
.hour(endTime.hms.hh)
|
||||
.minute(endTime.hms.mm)
|
||||
.second(endTime.hms.ss)
|
||||
.format(format)
|
||||
: "";
|
||||
emits("update:startTime", startTimeVal);
|
||||
emits("update:endTime", endTimeVal);
|
||||
datePicker.ok();
|
||||
};
|
||||
|
||||
//现在回调
|
||||
const footOnNow = () => {
|
||||
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 = () => {
|
||||
startTime.day = -1;
|
||||
endTime.day = -1;
|
||||
};
|
||||
</script>
|
||||
126
src/component/datePicker/components/MonthPanel.vue
Normal file
126
src/component/datePicker/components/MonthPanel.vue
Normal file
@@ -0,0 +1,126 @@
|
||||
<template>
|
||||
<div class="layui-laydate">
|
||||
<div class="layui-laydate-main laydate-main-list-0 laydate-ym-show">
|
||||
<div class="layui-laydate-header">
|
||||
<div class="laydate-set-ym">
|
||||
<span @click="datePicker.showPanel.value = 'month'">{{
|
||||
typeof Month !== "string"
|
||||
? MONTH_NAME[Month]
|
||||
: t("datePicker.selectMonth")
|
||||
}}</span>
|
||||
</div>
|
||||
</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"
|
||||
:class="{ 'layui-this': MONTH_NAME.indexOf(item) === Month }"
|
||||
@click="handleMonthClick(item)"
|
||||
>
|
||||
{{ item.slice(0, 3) }}
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<PanelFoot @ok="footOnOk" @now="footOnNow" @clear="footOnClear">
|
||||
<span
|
||||
v-if="datePicker.type === 'yearmonth'"
|
||||
@click="datePicker.showPanel.value = 'year'"
|
||||
class="laydate-btns-time"
|
||||
>{{ t("datePicker.selectYear") }}</span
|
||||
>
|
||||
</PanelFoot>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
export default {
|
||||
name: "TimePanel",
|
||||
};
|
||||
</script>
|
||||
<script lang="ts" setup>
|
||||
import dayjs from "dayjs";
|
||||
import { useI18n } from "../../../language";
|
||||
import { computed, inject, ref, watch } from "vue";
|
||||
import { provideType } from "../interface";
|
||||
import PanelFoot from "./PanelFoot.vue";
|
||||
|
||||
export interface TimePanelProps {
|
||||
modelValue: number | string;
|
||||
max?: number;
|
||||
}
|
||||
const props = withDefaults(defineProps<TimePanelProps>(), {
|
||||
max: dayjs().year() + 100,
|
||||
});
|
||||
const emits = defineEmits(["update:modelValue", "ok"]);
|
||||
const datePicker: provideType = inject("datePicker") as provideType;
|
||||
const Month = ref(props.modelValue);
|
||||
const { t } = useI18n();
|
||||
|
||||
const MONTH_NAME = computed(() => [
|
||||
t("datePicker.january"),
|
||||
t("datePicker.february"),
|
||||
t("datePicker.march"),
|
||||
t("datePicker.april"),
|
||||
t("datePicker.may"),
|
||||
t("datePicker.june"),
|
||||
t("datePicker.july"),
|
||||
t("datePicker.august"),
|
||||
t("datePicker.september"),
|
||||
t("datePicker.october"),
|
||||
t("datePicker.november"),
|
||||
t("datePicker.december"),
|
||||
]);
|
||||
|
||||
// 点击月份
|
||||
const handleMonthClick = (item: any) => {
|
||||
Month.value = MONTH_NAME.value.indexOf(item);
|
||||
if (!datePicker.range) {
|
||||
if (datePicker.type === "yearmonth") {
|
||||
datePicker.currentDay.value = dayjs(datePicker.currentDay.value)
|
||||
.month(MONTH_NAME.value.indexOf(item))
|
||||
.valueOf();
|
||||
}
|
||||
if (datePicker.type === "date" || datePicker.type === "datetime") {
|
||||
emits("update:modelValue", MONTH_NAME.value.indexOf(item));
|
||||
datePicker.showPanel.value = datePicker.type;
|
||||
}
|
||||
}
|
||||
if (datePicker.simple) {
|
||||
footOnOk();
|
||||
}
|
||||
};
|
||||
|
||||
watch(
|
||||
() => props.modelValue,
|
||||
() => {
|
||||
Month.value = props.modelValue;
|
||||
}
|
||||
);
|
||||
|
||||
//关闭回调
|
||||
const footOnOk = () => {
|
||||
emits("update:modelValue", Month.value ? Month.value : -1);
|
||||
if (datePicker.range) {
|
||||
//关闭菜单
|
||||
emits("ok");
|
||||
return;
|
||||
} else {
|
||||
if (datePicker.type === "datetime" || datePicker.type === "date") {
|
||||
datePicker.showPanel.value = datePicker.type;
|
||||
} else {
|
||||
datePicker.ok();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
//现在回调
|
||||
const footOnNow = () => {
|
||||
Month.value = dayjs().month();
|
||||
};
|
||||
|
||||
//清空回调
|
||||
const footOnClear = () => {
|
||||
Month.value = "";
|
||||
};
|
||||
</script>
|
||||
295
src/component/datePicker/components/MonthRange.vue
Normal file
295
src/component/datePicker/components/MonthRange.vue
Normal file
@@ -0,0 +1,295 @@
|
||||
<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 || "--" }} {{ t("datePicker.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 }} {{ t("datePicker.year") }}</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";
|
||||
import LayDropdown from "../../dropdown/index.vue";
|
||||
import { useI18n } from "../../../language";
|
||||
|
||||
export interface DateRangeProps {
|
||||
startTime: string;
|
||||
endTime: string;
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<DateRangeProps>(), {});
|
||||
|
||||
const emits = defineEmits([
|
||||
"update:modelValue",
|
||||
"update:startTime",
|
||||
"update:endTime",
|
||||
]);
|
||||
|
||||
const { t } = useI18n();
|
||||
|
||||
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 = computed(() => [
|
||||
t("datePicker.january"),
|
||||
t("datePicker.february"),
|
||||
t("datePicker.march"),
|
||||
t("datePicker.april"),
|
||||
t("datePicker.may"),
|
||||
t("datePicker.june"),
|
||||
t("datePicker.july"),
|
||||
t("datePicker.august"),
|
||||
t("datePicker.september"),
|
||||
t("datePicker.october"),
|
||||
t("datePicker.november"),
|
||||
t("datePicker.december"),
|
||||
]);
|
||||
|
||||
// 切换年月
|
||||
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.value.indexOf(item);
|
||||
let year = position === "left" ? startTime.year : startTime.year + 1;
|
||||
return dayjs(year + "-" + (month + 1)).valueOf();
|
||||
};
|
||||
});
|
||||
</script>
|
||||
40
src/component/datePicker/components/PanelFoot.vue
Normal file
40
src/component/datePicker/components/PanelFoot.vue
Normal file
@@ -0,0 +1,40 @@
|
||||
<template>
|
||||
<div class="layui-laydate-footer">
|
||||
<slot></slot>
|
||||
<div class="laydate-footer-btns">
|
||||
<span lay-type="clear" class="laydate-btns-clear" @click="handelClear">{{
|
||||
t("datePicker.clear")
|
||||
}}</span>
|
||||
<span lay-type="now" class="laydate-btns-now" @click="handelNow">{{
|
||||
t("datePicker.now")
|
||||
}}</span>
|
||||
<span lay-type="confirm" class="laydate-btns-confirm" @click="handelOk">{{
|
||||
t("datePicker.confirm")
|
||||
}}</span>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
export default {
|
||||
name: "PanelFoot",
|
||||
};
|
||||
</script>
|
||||
<script lang="ts" setup>
|
||||
import { useI18n } from "../../../language";
|
||||
|
||||
const { t } = useI18n();
|
||||
|
||||
const emits = defineEmits(["ok", "clear", "now"]);
|
||||
|
||||
const handelOk = () => {
|
||||
emits("ok");
|
||||
};
|
||||
|
||||
const handelNow = () => {
|
||||
emits("now");
|
||||
};
|
||||
|
||||
const handelClear = () => {
|
||||
emits("clear");
|
||||
};
|
||||
</script>
|
||||
164
src/component/datePicker/components/TimePanel.vue
Normal file
164
src/component/datePicker/components/TimePanel.vue
Normal file
@@ -0,0 +1,164 @@
|
||||
<template>
|
||||
<div class="layui-laydate">
|
||||
<div class="layui-laydate-main laydate-main-list-0 laydate-time-show">
|
||||
<div class="layui-laydate-header">
|
||||
<div class="laydate-set-ym">
|
||||
<span class="laydate-time-text">{{
|
||||
t("datePicker.selectTime")
|
||||
}}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-laydate-content" style="height: 210px">
|
||||
<ul class="layui-laydate-list laydate-time-list" ref="timePanelRef">
|
||||
<li
|
||||
class="num-list"
|
||||
v-for="item in els"
|
||||
:key="item.type"
|
||||
:data-type="item.type"
|
||||
>
|
||||
<ol class="scroll" @click="chooseTime">
|
||||
<li
|
||||
v-for="(it, index) in item.count"
|
||||
:id="item.type + index.toString()"
|
||||
:data-value="index.toString().padStart(2, '0')"
|
||||
:data-type="item.type"
|
||||
:key="it"
|
||||
:class="['num', index == hms[item.type] ? 'layui-this' : '']"
|
||||
>
|
||||
{{ index.toString().padStart(2, "0") }}
|
||||
</li>
|
||||
</ol>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<PanelFoot @ok="footOnOk" @now="footOnNow" @clear="footOnClear">
|
||||
<span
|
||||
v-if="datePicker.type === 'datetime' && !datePicker.range"
|
||||
@click="datePicker.showPanel.value = 'datetime'"
|
||||
class="laydate-btns-time"
|
||||
>{{ t("datePicker.selectDate") }}</span
|
||||
>
|
||||
<template v-else-if="!isNaN(hms.hh) && !isNaN(hms.mm) && !isNaN(hms.ss)">
|
||||
{{
|
||||
dayjs().hour(hms.hh).minute(hms.mm).second(hms.ss).format("HH:mm:ss")
|
||||
}}
|
||||
</template>
|
||||
</PanelFoot>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
export default {
|
||||
name: "TimePanel",
|
||||
};
|
||||
</script>
|
||||
<script lang="ts" setup>
|
||||
import dayjs from "dayjs";
|
||||
import { useI18n } from "../../../language";
|
||||
import { inject, onMounted, ref, nextTick, watch } from "vue";
|
||||
import { provideType } from "../interface";
|
||||
import PanelFoot from "./PanelFoot.vue";
|
||||
export interface hmsType {
|
||||
hh: number;
|
||||
mm: number;
|
||||
ss: number;
|
||||
[key: string]: any;
|
||||
}
|
||||
export interface TimePanelProps {
|
||||
modelValue: hmsType;
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<TimePanelProps>(), {});
|
||||
const emits = defineEmits(["update:modelValue", "ok"]);
|
||||
const datePicker: provideType = inject("datePicker") as provideType;
|
||||
const { t } = useI18n();
|
||||
|
||||
const els = [
|
||||
{ count: 24, type: "hh" },
|
||||
{ count: 60, type: "mm" },
|
||||
{ count: 60, type: "ss" },
|
||||
];
|
||||
const hms = ref<hmsType>({
|
||||
hh: props.modelValue.hh,
|
||||
mm: props.modelValue.mm,
|
||||
ss: props.modelValue.ss,
|
||||
});
|
||||
|
||||
// 点击时间 - hms
|
||||
const chooseTime = (e: any) => {
|
||||
if (e.target.nodeName == "LI") {
|
||||
let { value, type } = e.target.dataset;
|
||||
hms.value[type as keyof typeof hms.value] = parseInt(value);
|
||||
}
|
||||
};
|
||||
|
||||
const timePanelRef = ref();
|
||||
onMounted(() => {
|
||||
scrollTo();
|
||||
});
|
||||
watch(
|
||||
() => props.modelValue,
|
||||
() => {
|
||||
hms.value = {
|
||||
hh: props.modelValue.hh,
|
||||
mm: props.modelValue.mm,
|
||||
ss: props.modelValue.ss,
|
||||
};
|
||||
},
|
||||
{ deep: true }
|
||||
);
|
||||
const scrollTo = () => {
|
||||
nextTick(() => {
|
||||
timePanelRef.value.childNodes.forEach((element: HTMLElement) => {
|
||||
if (element.nodeName === "LI") {
|
||||
let scrollTop = 0;
|
||||
let parentDom = element.firstElementChild as HTMLElement;
|
||||
let childList = parentDom.childNodes;
|
||||
for (let index = 0; index < childList.length; index++) {
|
||||
const child = childList[index] as HTMLElement;
|
||||
if (child.nodeName !== "LI") {
|
||||
continue;
|
||||
}
|
||||
if (child.classList && child.classList.contains("layui-this")) {
|
||||
scrollTop =
|
||||
child.offsetTop -
|
||||
(parentDom.offsetHeight - child.offsetHeight) / 2;
|
||||
parentDom.scrollTo(0, scrollTop);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
//确认关闭回调
|
||||
const footOnOk = () => {
|
||||
emits("update:modelValue", hms.value);
|
||||
if (datePicker.range) {
|
||||
//关闭菜单
|
||||
emits("ok");
|
||||
return;
|
||||
} else {
|
||||
datePicker.ok();
|
||||
if (datePicker.type === "datetime") {
|
||||
datePicker.showPanel.value = "date";
|
||||
}
|
||||
}
|
||||
};
|
||||
//现在回调
|
||||
const footOnNow = () => {
|
||||
hms.value.hh = dayjs().hour();
|
||||
hms.value.mm = dayjs().minute();
|
||||
hms.value.ss = dayjs().second();
|
||||
scrollTo();
|
||||
};
|
||||
|
||||
//清空回调
|
||||
const footOnClear = () => {
|
||||
hms.value.hh = 0;
|
||||
hms.value.mm = 0;
|
||||
hms.value.ss = 0;
|
||||
scrollTo();
|
||||
};
|
||||
</script>
|
||||
146
src/component/datePicker/components/YearPanel.vue
Normal file
146
src/component/datePicker/components/YearPanel.vue
Normal file
@@ -0,0 +1,146 @@
|
||||
<template>
|
||||
<div class="layui-laydate">
|
||||
<div class="layui-laydate-main laydate-main-list-0 laydate-ym-show">
|
||||
<div class="layui-laydate-header">
|
||||
<div class="laydate-set-ym">
|
||||
<span class="laydate-time-text">{{
|
||||
t("datePicker.selectYear")
|
||||
}}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="layui-laydate-content"
|
||||
style="height: 220px; overflow-y: auto"
|
||||
ref="ScrollRef"
|
||||
>
|
||||
<ul class="layui-laydate-list laydate-year-list">
|
||||
<li
|
||||
v-for="item of yearList"
|
||||
:key="item"
|
||||
:class="{ 'layui-this': Year === item }"
|
||||
@click="handleYearClick(item)"
|
||||
>
|
||||
{{ item }}
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<PanelFoot @ok="footOnOk" @now="footOnNow" @clear="footOnClear">
|
||||
<span
|
||||
v-if="datePicker.type === 'yearmonth'"
|
||||
@click="datePicker.showPanel.value = 'month'"
|
||||
class="laydate-btns-time"
|
||||
>{{ t("datePicker.selectMonth") }}</span
|
||||
>
|
||||
<template v-else-if="Year > 0">{{ Year }}</template>
|
||||
</PanelFoot>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
export default {
|
||||
name: "YearPanel",
|
||||
};
|
||||
</script>
|
||||
<script lang="ts" setup>
|
||||
import dayjs from "dayjs";
|
||||
import { useI18n } from "../../../language";
|
||||
import { inject, nextTick, onMounted, ref, watch } from "vue";
|
||||
import { getYears } from "../day";
|
||||
import { provideType } from "../interface";
|
||||
import PanelFoot from "./PanelFoot.vue";
|
||||
|
||||
export interface TimePanelProps {
|
||||
modelValue: number | string;
|
||||
max?: number;
|
||||
}
|
||||
const props = withDefaults(defineProps<TimePanelProps>(), {
|
||||
max: dayjs().year() + 100,
|
||||
});
|
||||
const emits = defineEmits(["update:modelValue", "ok"]);
|
||||
const datePicker: provideType = inject("datePicker") as provideType;
|
||||
const yearList = ref<number[]>(getYears());
|
||||
const unWatch = ref(false);
|
||||
const Year = ref(props.modelValue);
|
||||
const { t } = useI18n();
|
||||
|
||||
// 点击年份
|
||||
const handleYearClick = (item: any) => {
|
||||
unWatch.value = true;
|
||||
Year.value = item;
|
||||
if (!datePicker.range) {
|
||||
if (datePicker.type === "year") {
|
||||
datePicker.currentDay.value = dayjs().year(item).valueOf();
|
||||
} else if (datePicker.type === "yearmonth") {
|
||||
datePicker.currentDay.value = dayjs().year(item).valueOf();
|
||||
datePicker.showPanel.value = "month";
|
||||
emits("update:modelValue", Year.value);
|
||||
} else {
|
||||
emits("update:modelValue", Year.value);
|
||||
datePicker.showPanel.value = datePicker.type;
|
||||
}
|
||||
}
|
||||
|
||||
setTimeout(() => {
|
||||
unWatch.value = false;
|
||||
}, 0);
|
||||
|
||||
if (datePicker.simple) {
|
||||
footOnOk();
|
||||
}
|
||||
};
|
||||
|
||||
const ScrollRef = ref();
|
||||
onMounted(() => {
|
||||
scrollTo();
|
||||
});
|
||||
watch(
|
||||
() => Year,
|
||||
() => {
|
||||
Year.value = props.modelValue;
|
||||
}
|
||||
);
|
||||
const scrollTo = () => {
|
||||
nextTick(() => {
|
||||
let scrollTop = 0;
|
||||
for (const child of ScrollRef.value.firstElementChild.childNodes) {
|
||||
if (child.classList && child.classList.contains("layui-this")) {
|
||||
scrollTop =
|
||||
child.offsetTop -
|
||||
(ScrollRef.value.offsetHeight - child.offsetHeight) / 2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
ScrollRef.value.scrollTo(0, scrollTop);
|
||||
});
|
||||
};
|
||||
|
||||
//关闭回调
|
||||
const footOnOk = () => {
|
||||
emits("update:modelValue", Year.value ? Year.value : -1);
|
||||
if (datePicker.range) {
|
||||
//关闭菜单
|
||||
emits("ok");
|
||||
return;
|
||||
} else {
|
||||
if (datePicker.type === "datetime" || datePicker.type === "date") {
|
||||
datePicker.showPanel.value = datePicker.type;
|
||||
} else {
|
||||
datePicker.ok();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
//现在回调
|
||||
const footOnNow = () => {
|
||||
Year.value = dayjs().year();
|
||||
if (datePicker.type === "yearmonth") {
|
||||
datePicker.currentMonth.value = dayjs().month();
|
||||
}
|
||||
scrollTo();
|
||||
};
|
||||
|
||||
//清空回调
|
||||
const footOnClear = () => {
|
||||
Year.value = "";
|
||||
};
|
||||
</script>
|
||||
169
src/component/datePicker/components/components/DateContent.vue
Normal file
169
src/component/datePicker/components/components/DateContent.vue
Normal file
@@ -0,0 +1,169 @@
|
||||
<template>
|
||||
<div class="layui-laydate-content">
|
||||
<table style="width: 100%">
|
||||
<thead>
|
||||
<tr>
|
||||
<th v-for="item of WEEK_NAME" :key="item">{{ item }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<template
|
||||
v-for="(o, i) of dateList.length % 7 == 0
|
||||
? dateList.length / 7
|
||||
: Math.floor(dateList.length / 7) + 1"
|
||||
:key="i"
|
||||
>
|
||||
<tr>
|
||||
<td
|
||||
v-for="(item, index) of dateList.slice(i * 7, i * 7 + 7)"
|
||||
:key="index"
|
||||
:data-unix="item.value"
|
||||
:class="{
|
||||
'laydate-day-prev': item.type !== 'current',
|
||||
'layui-this':
|
||||
item.value === modelValue ||
|
||||
(datePicker.range &&
|
||||
item.type === 'current' &&
|
||||
(item.value == startDate || item.value == endDate)),
|
||||
'laydate-range-hover': ifHasRangeHoverClass(item),
|
||||
'layui-disabled': item.type !== 'current' && datePicker.range,
|
||||
}"
|
||||
@click="handleDayClick(item)"
|
||||
@mouseenter="dayItemMouseEnter($event, item)"
|
||||
>
|
||||
{{ item.day }}
|
||||
</td>
|
||||
</tr>
|
||||
</template>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
export default {
|
||||
name: "DateContent",
|
||||
};
|
||||
</script>
|
||||
<script lang="ts" setup>
|
||||
import { useI18n } from "../../../../language";
|
||||
import { computed, inject } from "vue";
|
||||
import { provideType } from "../../interface";
|
||||
|
||||
export interface DateContentProps {
|
||||
dateList: any;
|
||||
modelValue?: number;
|
||||
startDate?: number;
|
||||
endDate?: number;
|
||||
hoverDate?: number;
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<DateContentProps>(), {
|
||||
dateList: [],
|
||||
modelValue: -1,
|
||||
hoverDate: -1,
|
||||
startDate: -1,
|
||||
endDate: -1,
|
||||
});
|
||||
|
||||
const { t } = useI18n();
|
||||
|
||||
const WEEK_NAME = computed(() => [
|
||||
t("datePicker.sunday"),
|
||||
t("datePicker.monday"),
|
||||
t("datePicker.tuesday"),
|
||||
t("datePicker.wednesday"),
|
||||
t("datePicker.thursday"),
|
||||
t("datePicker.friday"),
|
||||
t("datePicker.saturday"),
|
||||
]);
|
||||
|
||||
const datePicker: provideType = inject("datePicker") as provideType;
|
||||
|
||||
const emits = defineEmits([
|
||||
"update:modelValue",
|
||||
"update:startDate",
|
||||
"update:endDate",
|
||||
"update:hoverDate",
|
||||
"simple",
|
||||
]);
|
||||
|
||||
// 点击日期
|
||||
const handleDayClick = (item: any) => {
|
||||
if (datePicker.range) {
|
||||
if (item.type !== "current") {
|
||||
return;
|
||||
}
|
||||
|
||||
if (props.startDate === -1 && props.endDate === -1) {
|
||||
emits("update:startDate", item.value);
|
||||
} else if (props.startDate !== -1 && props.endDate !== -1) {
|
||||
emits("update:hoverDate", item.value);
|
||||
emits("update:startDate", item.value);
|
||||
emits("update:endDate", -1);
|
||||
} else if (props.startDate !== -1 && props.endDate === -1) {
|
||||
emits("update:endDate", item.value);
|
||||
if (item.value < props.startDate) {
|
||||
//swap
|
||||
const first = props.startDate;
|
||||
const last = item.value;
|
||||
emits("update:startDate", last);
|
||||
emits("update:endDate", first);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
emits("update:modelValue", item.value);
|
||||
if (item.type !== "current") {
|
||||
datePicker.currentMonth.value =
|
||||
item.type === "prev"
|
||||
? datePicker.currentMonth.value - 1
|
||||
: datePicker.currentMonth.value + 1;
|
||||
}
|
||||
if (datePicker.simple) {
|
||||
emits("simple");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const dayItemMouseEnter = (event: MouseEvent, item: any) => {
|
||||
if (!datePicker.range) {
|
||||
return;
|
||||
}
|
||||
if (props.startDate === -1) {
|
||||
return;
|
||||
}
|
||||
if (item.type !== "current") {
|
||||
return;
|
||||
}
|
||||
if (props.startDate !== -1 && props.endDate !== -1) {
|
||||
emits("update:hoverDate", -1);
|
||||
return;
|
||||
}
|
||||
emits(
|
||||
"update:hoverDate",
|
||||
parseInt((event.target as HTMLElement).dataset.unix as string)
|
||||
);
|
||||
};
|
||||
const ifHasRangeHoverClass = computed(() => {
|
||||
return function (item: any) {
|
||||
if (!datePicker.range) {
|
||||
return false;
|
||||
}
|
||||
if (props.startDate === -1) {
|
||||
return false;
|
||||
}
|
||||
if (item.type !== "current") {
|
||||
return false;
|
||||
}
|
||||
if (props.hoverDate === -1 && props.endDate === -1) {
|
||||
return false;
|
||||
}
|
||||
let hover = props.endDate !== -1 ? props.endDate : props.hoverDate;
|
||||
let max = props.startDate > hover ? props.startDate : hover;
|
||||
let min = props.startDate < hover ? props.startDate : hover;
|
||||
if (item.value >= min && item.value <= max) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
});
|
||||
</script>
|
||||
105
src/component/datePicker/day.ts
Normal file
105
src/component/datePicker/day.ts
Normal file
@@ -0,0 +1,105 @@
|
||||
/**
|
||||
* 获取年份列表
|
||||
*/
|
||||
const getYears = () => {
|
||||
let years = [];
|
||||
for (let i = 1970; i < getYear() + 100; i++) {
|
||||
years.push(i);
|
||||
}
|
||||
return years;
|
||||
};
|
||||
|
||||
/**
|
||||
* 获取当前日期
|
||||
*/
|
||||
const getDate = (val = "") => {
|
||||
if (val) {
|
||||
return new Date(val);
|
||||
} else {
|
||||
return new Date();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 获取当前年份
|
||||
*/
|
||||
const getYear = (val = "") => {
|
||||
return getDate(val).getFullYear();
|
||||
};
|
||||
|
||||
/**
|
||||
* 获取当前月份
|
||||
*/
|
||||
const getMonth = (val = "") => {
|
||||
return getDate(val).getMonth();
|
||||
};
|
||||
|
||||
const getDay = (val = "") => {
|
||||
if (val) {
|
||||
return new Date(getDate(val).toDateString()).getTime();
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 获取月份天数
|
||||
*
|
||||
* @param year
|
||||
* @param month
|
||||
*/
|
||||
const getDayLength = (year: number, month: number): number => {
|
||||
return new Date(year, month + 1, 0).getDate();
|
||||
};
|
||||
|
||||
// 设置日期列表
|
||||
const setDateList = (year: number, month: number) => {
|
||||
const curDays = getDayLength(year, month); // 当月天数
|
||||
const prevDays = getDayLength(year, month - 1); // 上月天数
|
||||
const curFirstDayWeek = new Date(year, month, 1).getDay(); // 当月第一天星期几
|
||||
const list: any[] = [];
|
||||
// 填充上月天数
|
||||
for (let i = prevDays - curFirstDayWeek + 1; i <= prevDays; i++) {
|
||||
list.push({
|
||||
day: i,
|
||||
value: +new Date(year, month - 1, i),
|
||||
isRange: false,
|
||||
isSelected: false,
|
||||
type: "prev",
|
||||
});
|
||||
}
|
||||
// 填充当月天数
|
||||
for (let i = 1; i <= curDays; i++) {
|
||||
list.push({
|
||||
day: i,
|
||||
value: +new Date(year, month, i),
|
||||
isRange: false,
|
||||
isSelected: false,
|
||||
type: "current",
|
||||
});
|
||||
}
|
||||
// 填充下月天数
|
||||
const nextDays = 7 - (list.length % 7);
|
||||
if (nextDays !== 7) {
|
||||
for (let i = 1; i <= nextDays; i++) {
|
||||
list.push({
|
||||
day: i,
|
||||
value: +new Date(year, month + 1, i),
|
||||
isRange: false,
|
||||
isSelected: false,
|
||||
type: "next",
|
||||
});
|
||||
}
|
||||
}
|
||||
return list;
|
||||
};
|
||||
|
||||
export {
|
||||
getDayLength,
|
||||
getYears,
|
||||
getDate,
|
||||
getMonth,
|
||||
getYear,
|
||||
getDay,
|
||||
setDateList,
|
||||
};
|
||||
BIN
src/component/datePicker/font/iconfont.eot
Normal file
BIN
src/component/datePicker/font/iconfont.eot
Normal file
Binary file not shown.
45
src/component/datePicker/font/iconfont.svg
Normal file
45
src/component/datePicker/font/iconfont.svg
Normal file
@@ -0,0 +1,45 @@
|
||||
<?xml version="1.0" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
|
||||
<!--
|
||||
2013-9-30: Created.
|
||||
-->
|
||||
<svg>
|
||||
<metadata>
|
||||
Created by iconfont
|
||||
</metadata>
|
||||
<defs>
|
||||
|
||||
<font id="laydate-icon" horiz-adv-x="1024" >
|
||||
<font-face
|
||||
font-family="laydate-icon"
|
||||
font-weight="500"
|
||||
font-stretch="normal"
|
||||
units-per-em="1024"
|
||||
ascent="896"
|
||||
descent="-128"
|
||||
/>
|
||||
<missing-glyph />
|
||||
|
||||
<glyph glyph-name="x" unicode="x" horiz-adv-x="1001"
|
||||
d="M281 543q-27 -1 -53 -1h-83q-18 0 -36.5 -6t-32.5 -18.5t-23 -32t-9 -45.5v-76h912v41q0 16 -0.5 30t-0.5 18q0 13 -5 29t-17 29.5t-31.5 22.5t-49.5 9h-133v-97h-438v97zM955 310v-52q0 -23 0.5 -52t0.5 -58t-10.5 -47.5t-26 -30t-33 -16t-31.5 -4.5q-14 -1 -29.5 -0.5
|
||||
t-29.5 0.5h-32l-45 128h-439l-44 -128h-29h-34q-20 0 -45 1q-25 0 -41 9.5t-25.5 23t-13.5 29.5t-4 30v167h911zM163 247q-12 0 -21 -8.5t-9 -21.5t9 -21.5t21 -8.5q13 0 22 8.5t9 21.5t-9 21.5t-22 8.5zM316 123q-8 -26 -14 -48q-5 -19 -10.5 -37t-7.5 -25t-3 -15t1 -14.5
|
||||
t9.5 -10.5t21.5 -4h37h67h81h80h64h36q23 0 34 12t2 38q-5 13 -9.5 30.5t-9.5 34.5q-5 19 -11 39h-368zM336 498v228q0 11 2.5 23t10 21.5t20.5 15.5t34 6h188q31 0 51.5 -14.5t20.5 -52.5v-227h-327z" />
|
||||
|
||||
|
||||
|
||||
<glyph glyph-name="youyou" unicode="" d="M283.648 721.918976 340.873216 780.926976 740.352 383.997952 340.876288-12.925952 283.648 46.077952 619.52 383.997952Z" horiz-adv-x="1024" />
|
||||
|
||||
|
||||
<glyph glyph-name="zuozuo" unicode="" d="M740.352 721.918976 683.126784 780.926976 283.648 383.997952 683.123712-12.925952 740.352 46.077952 404.48 383.997952Z" horiz-adv-x="1024" />
|
||||
|
||||
|
||||
<glyph glyph-name="xiayiye" unicode="" d="M62.573 384.103l423.401 423.662c18.985 18.985 49.757 18.985 68.727 0 18.982-18.972 18.985-49.746 0-68.729l-355.058-355.067 356.796-356.796c18.977-18.971 18.976-49.746 0-68.727-18.982-18.976-49.751-18.976-68.727 0l-39.753 39.753 0.269 0.246-385.655 385.661zM451.365 384.103l423.407 423.662c18.985 18.985 49.757 18.985 68.727 0 18.982-18.972 18.985-49.746 0-68.729l-355.058-355.067 356.796-356.796c18.977-18.971 18.976-49.746 0-68.727-18.982-18.976-49.757-18.977-68.727 0l-39.762 39.754 0.273 0.249-385.662 385.661zM451.365 384.103z" horiz-adv-x="1024" />
|
||||
|
||||
|
||||
<glyph glyph-name="xiayiye1" unicode="" d="M948.066926 382.958838l-411.990051-412.24426c-18.47333-18.47333-48.417689-18.47333-66.875207 0-18.47333 18.461167-18.47333 48.405526 0 66.875207L814.691135 383.088983 467.512212 730.269123c-18.466032 18.458735-18.466032 48.405526 0 66.873991 18.468465 18.464816 48.410391 18.464816 66.872774 0l38.682336-38.682336-0.261507-0.239614 375.259894-375.265975v0.003649m-378.312834 0L157.756743-29.285422c-18.47333-18.47333-48.415256-18.47333-66.872775 0-18.47333 18.461167-18.47333 48.405526 0 66.875207L436.369787 383.088983 89.19208 730.269123c-18.4636 18.458735-18.4636 48.405526 0 66.873991 18.470898 18.464816 48.415256 18.464816 66.872774 0l38.692067-38.682336-0.266372-0.239614 375.267191-375.265975-0.004865 0.003649m0 0z" horiz-adv-x="1024" />
|
||||
|
||||
|
||||
|
||||
|
||||
</font>
|
||||
</defs></svg>
|
||||
|
After Width: | Height: | Size: 3.0 KiB |
BIN
src/component/datePicker/font/iconfont.ttf
Normal file
BIN
src/component/datePicker/font/iconfont.ttf
Normal file
Binary file not shown.
BIN
src/component/datePicker/font/iconfont.woff
Normal file
BIN
src/component/datePicker/font/iconfont.woff
Normal file
Binary file not shown.
579
src/component/datePicker/index.less
Normal file
579
src/component/datePicker/index.less
Normal file
@@ -0,0 +1,579 @@
|
||||
@import "../dropdown/index.less";
|
||||
@import "../input/index.less";
|
||||
|
||||
@lg: 44px;
|
||||
@md: 38px;
|
||||
@sm: 32px;
|
||||
@xs: 26px;
|
||||
@lg-width: 260px;
|
||||
@md-width: 220px;
|
||||
@sm-width: 180px;
|
||||
@xs-width: 140px;
|
||||
@lg-range-width: 520px;
|
||||
@md-range-width: 440px;
|
||||
@sm-range-width: 360px;
|
||||
@xs-range-width: 280px;
|
||||
|
||||
.set-size(@size,@width) {
|
||||
& {
|
||||
width: @width;
|
||||
height: @size;
|
||||
.layui-input {
|
||||
height: @size;
|
||||
line-height: @size;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.layui-date-picker {
|
||||
&[size="lg"] {
|
||||
.set-size(@lg,@lg-width);
|
||||
}
|
||||
&[size="md"] {
|
||||
.set-size(@md,@md-width);
|
||||
}
|
||||
&[size="sm"] {
|
||||
.set-size(@sm,@sm-width);
|
||||
}
|
||||
&[size="xs"] {
|
||||
.set-size(@xs,@xs-width);
|
||||
}
|
||||
}
|
||||
.layui-date-range-picker {
|
||||
&[size="lg"] {
|
||||
.set-size(@lg,@lg-range-width);
|
||||
}
|
||||
&[size="md"] {
|
||||
.set-size(@md,@md-range-width);
|
||||
}
|
||||
&[size="sm"] {
|
||||
.set-size(@sm,@sm-range-width);
|
||||
}
|
||||
&[size="xs"] {
|
||||
.set-size(@xs,@xs-range-width);
|
||||
}
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "laydate-icon";
|
||||
src: url("./font/iconfont.eot");
|
||||
src: url("./font/iconfont.eot#iefix") format("embedded-opentype"),
|
||||
url("./font/iconfont.svg#iconfont") format("svg"),
|
||||
url("./font/iconfont.woff") format("woff"),
|
||||
url("./font/iconfont.ttf") format("truetype");
|
||||
}
|
||||
|
||||
.laydate-icon {
|
||||
font-family: "laydate-icon" !important;
|
||||
font-size: 16px;
|
||||
font-style: normal;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
html #layuicss-laydate {
|
||||
display: none;
|
||||
position: absolute;
|
||||
width: 1989px;
|
||||
}
|
||||
|
||||
/* 初始化 */
|
||||
.layui-laydate * {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
/* 主体结构 */
|
||||
.layui-laydate,
|
||||
.layui-laydate * {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.layui-laydate {
|
||||
z-index: 66666666;
|
||||
border-radius: 2px;
|
||||
font-size: 14px;
|
||||
-webkit-animation-duration: 0.2s;
|
||||
animation-duration: 0.2s;
|
||||
-webkit-animation-fill-mode: both;
|
||||
animation-fill-mode: both;
|
||||
}
|
||||
.layui-laydate-main {
|
||||
width: 272px;
|
||||
}
|
||||
.layui-laydate-header *,
|
||||
.layui-laydate-content td,
|
||||
.layui-laydate-list li {
|
||||
transition-duration: 0.3s;
|
||||
-webkit-transition-duration: 0.3s;
|
||||
}
|
||||
|
||||
/* 微微往下滑入 */
|
||||
@keyframes laydate-downbit {
|
||||
0% {
|
||||
opacity: 0.3;
|
||||
transform: translate3d(0, -5px, 0);
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
transform: translate3d(0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
.layui-laydate {
|
||||
animation-name: laydate-downbit;
|
||||
}
|
||||
.layui-laydate-static {
|
||||
position: relative;
|
||||
z-index: 0;
|
||||
display: inline-block;
|
||||
margin: 0;
|
||||
-webkit-animation: none;
|
||||
animation: none;
|
||||
}
|
||||
|
||||
/* 展开年月列表时 */
|
||||
.laydate-ym-show .laydate-prev-m,
|
||||
.laydate-ym-show .laydate-next-m {
|
||||
display: none !important;
|
||||
}
|
||||
.laydate-ym-show .laydate-prev-y,
|
||||
.laydate-ym-show .laydate-next-y {
|
||||
display: inline-block !important;
|
||||
}
|
||||
.laydate-ym-show .laydate-set-ym span[lay-type="month"] {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
/* 展开时间列表时 */
|
||||
.laydate-time-show .layui-laydate-header .layui-icon,
|
||||
.laydate-time-show .laydate-set-ym span[lay-type="year"],
|
||||
.laydate-time-show .laydate-set-ym span[lay-type="month"] {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
/* 头部结构 */
|
||||
.layui-laydate-header {
|
||||
position: relative;
|
||||
line-height: 30px;
|
||||
padding: 10px 70px 5px;
|
||||
}
|
||||
.layui-laydate-header * {
|
||||
vertical-align: bottom;
|
||||
}
|
||||
.layui-laydate-header i {
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
padding: 0 5px;
|
||||
color: #999;
|
||||
font-size: 18px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.layui-laydate-header i.laydate-prev-y {
|
||||
left: 15px;
|
||||
}
|
||||
.layui-laydate-header i.laydate-prev-m {
|
||||
left: 45px;
|
||||
}
|
||||
.layui-laydate-header i.laydate-next-y {
|
||||
right: 15px;
|
||||
}
|
||||
.layui-laydate-header i.laydate-next-m {
|
||||
right: 45px;
|
||||
}
|
||||
.laydate-set-ym {
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
box-sizing: border-box;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.laydate-set-ym span {
|
||||
padding: 0 10px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.laydate-time-text {
|
||||
cursor: default !important;
|
||||
}
|
||||
|
||||
/* 主体结构 */
|
||||
.layui-laydate-content {
|
||||
position: relative;
|
||||
padding: 10px;
|
||||
-moz-user-select: none;
|
||||
-webkit-user-select: none;
|
||||
-ms-user-select: none;
|
||||
}
|
||||
.layui-laydate-content table {
|
||||
border-collapse: collapse;
|
||||
border-spacing: 0;
|
||||
}
|
||||
.layui-laydate-content th,
|
||||
.layui-laydate-content td {
|
||||
width: 36px;
|
||||
height: 30px;
|
||||
padding: 5px;
|
||||
text-align: center !important;
|
||||
}
|
||||
.layui-laydate-content th {
|
||||
font-weight: 400;
|
||||
}
|
||||
.layui-laydate-content td {
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
}
|
||||
.laydate-day-mark {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
line-height: 30px;
|
||||
font-size: 12px;
|
||||
overflow: hidden;
|
||||
}
|
||||
.laydate-day-mark::after {
|
||||
position: absolute;
|
||||
content: "";
|
||||
right: 2px;
|
||||
top: 2px;
|
||||
width: 5px;
|
||||
height: 5px;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
/* 底部结构 */
|
||||
.layui-laydate-footer {
|
||||
position: relative;
|
||||
height: 46px;
|
||||
line-height: 26px;
|
||||
padding: 10px;
|
||||
}
|
||||
.layui-laydate-footer span {
|
||||
display: inline-block;
|
||||
vertical-align: top;
|
||||
height: 26px;
|
||||
line-height: 24px;
|
||||
padding: 0 10px;
|
||||
border: 1px solid #c9c9c9;
|
||||
border-radius: 2px;
|
||||
background-color: #fff;
|
||||
font-size: 12px;
|
||||
cursor: pointer;
|
||||
white-space: nowrap;
|
||||
transition: all 0.3s;
|
||||
}
|
||||
.layui-laydate-footer span:hover {
|
||||
color: #5fb878;
|
||||
}
|
||||
.layui-laydate-footer span.layui-laydate-preview {
|
||||
cursor: default;
|
||||
border-color: transparent !important;
|
||||
}
|
||||
.layui-laydate-footer span.layui-laydate-preview:hover {
|
||||
color: #666;
|
||||
}
|
||||
.layui-laydate-footer span:first-child.layui-laydate-preview {
|
||||
padding-left: 0;
|
||||
}
|
||||
.laydate-footer-btns {
|
||||
position: absolute;
|
||||
right: 10px;
|
||||
top: 10px;
|
||||
}
|
||||
.laydate-footer-btns span {
|
||||
margin: 0 0 0 -1px;
|
||||
}
|
||||
|
||||
/* 年月列表 */
|
||||
.layui-laydate-list {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
padding: 10px;
|
||||
box-sizing: border-box;
|
||||
background-color: #fff;
|
||||
}
|
||||
.layui-laydate-list > li {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
width: 33.3%;
|
||||
height: 36px;
|
||||
line-height: 36px;
|
||||
margin: 3px 0;
|
||||
vertical-align: middle;
|
||||
text-align: center;
|
||||
cursor: pointer;
|
||||
}
|
||||
.laydate-month-list > li {
|
||||
width: 25%;
|
||||
margin: 17px 0;
|
||||
}
|
||||
.laydate-time-list > li {
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
line-height: normal;
|
||||
cursor: default;
|
||||
}
|
||||
.laydate-time-list p {
|
||||
position: relative;
|
||||
top: -4px;
|
||||
line-height: 29px;
|
||||
}
|
||||
.laydate-time-list ol {
|
||||
height: 181px;
|
||||
overflow: hidden;
|
||||
}
|
||||
.laydate-time-list > li:hover ol {
|
||||
overflow-y: auto;
|
||||
}
|
||||
.laydate-time-list ol li {
|
||||
width: 130%;
|
||||
padding-left: 4px;
|
||||
height: 30px;
|
||||
line-height: 30px;
|
||||
text-align: left;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
/* 提示 */
|
||||
.layui-laydate-hint {
|
||||
top: 115px;
|
||||
left: 50%;
|
||||
width: 250px;
|
||||
margin-left: -125px;
|
||||
line-height: 20px;
|
||||
padding: 15px;
|
||||
text-align: center;
|
||||
font-size: 12px;
|
||||
color: #ff5722;
|
||||
}
|
||||
|
||||
/* 双日历 */
|
||||
.layui-laydate-range {
|
||||
min-width: 546px;
|
||||
}
|
||||
.layui-laydate-range .layui-laydate-main {
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
}
|
||||
.layui-laydate-range .laydate-main-list-1 .layui-laydate-header,
|
||||
.layui-laydate-range .laydate-main-list-1 .layui-laydate-content {
|
||||
border-left: 1px solid #e2e2e2;
|
||||
}
|
||||
|
||||
/* 默认简约主题 */
|
||||
.layui-laydate,
|
||||
.layui-laydate-hint {
|
||||
background-color: #fff;
|
||||
color: #666;
|
||||
}
|
||||
.layui-laydate-header {
|
||||
border-bottom: 1px solid #e2e2e2;
|
||||
}
|
||||
.layui-laydate-header i:hover,
|
||||
.layui-laydate-header span:hover {
|
||||
color: #5fb878;
|
||||
}
|
||||
.layui-laydate-content {
|
||||
border-top: none 0;
|
||||
border-bottom: none 0;
|
||||
}
|
||||
.layui-laydate-content th {
|
||||
color: #333;
|
||||
}
|
||||
.layui-laydate-content td {
|
||||
color: #666;
|
||||
}
|
||||
.layui-laydate-content td.laydate-selected {
|
||||
background-color: #b5fff8;
|
||||
}
|
||||
.laydate-selected:hover {
|
||||
background-color: #00f7de !important;
|
||||
}
|
||||
.layui-laydate-content td:hover,
|
||||
.layui-laydate-list li:hover {
|
||||
background-color: #eee;
|
||||
color: #333;
|
||||
}
|
||||
.laydate-time-list li ol {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
border: 1px solid #e2e2e2;
|
||||
}
|
||||
.laydate-time-list li:first-child ol {
|
||||
border-left-width: 1px;
|
||||
}
|
||||
.laydate-time-list > li:hover {
|
||||
background: none;
|
||||
}
|
||||
.layui-laydate-content .laydate-day-prev,
|
||||
.layui-laydate-content .laydate-day-next {
|
||||
color: #d2d2d2;
|
||||
}
|
||||
.laydate-selected.laydate-day-prev,
|
||||
.laydate-selected.laydate-day-next {
|
||||
background-color: #f8f8f8 !important;
|
||||
}
|
||||
.layui-laydate-footer {
|
||||
border-top: 1px solid #e2e2e2;
|
||||
}
|
||||
.layui-laydate-hint {
|
||||
color: #ff5722;
|
||||
}
|
||||
.laydate-day-mark::after {
|
||||
background-color: #5fb878;
|
||||
}
|
||||
.layui-laydate-content td.layui-this .laydate-day-mark::after {
|
||||
display: none;
|
||||
}
|
||||
.layui-laydate-footer span[lay-type="date"] {
|
||||
color: #5fb878;
|
||||
}
|
||||
.layui-laydate .layui-this {
|
||||
background-color: #009688 !important;
|
||||
color: #fff !important;
|
||||
}
|
||||
.layui-laydate .laydate-disabled,
|
||||
.layui-laydate .laydate-disabled:hover {
|
||||
background: none !important;
|
||||
color: #d2d2d2 !important;
|
||||
cursor: not-allowed !important;
|
||||
-moz-user-select: none;
|
||||
-webkit-user-select: none;
|
||||
-ms-user-select: none;
|
||||
}
|
||||
|
||||
/* 墨绿/自定义背景色主题 */
|
||||
.laydate-theme-molv {
|
||||
border: none;
|
||||
}
|
||||
.laydate-theme-molv.layui-laydate-range {
|
||||
width: 548px;
|
||||
}
|
||||
.laydate-theme-molv .layui-laydate-main {
|
||||
width: 274px;
|
||||
}
|
||||
.laydate-theme-molv .layui-laydate-header {
|
||||
border: none;
|
||||
background-color: #009688;
|
||||
}
|
||||
.laydate-theme-molv .layui-laydate-header i,
|
||||
.laydate-theme-molv .layui-laydate-header span {
|
||||
color: #f6f6f6;
|
||||
}
|
||||
.laydate-theme-molv .layui-laydate-header i:hover,
|
||||
.laydate-theme-molv .layui-laydate-header span:hover {
|
||||
color: #fff;
|
||||
}
|
||||
.laydate-theme-molv .layui-laydate-content {
|
||||
border: 1px solid #e2e2e2;
|
||||
border-top: none;
|
||||
border-bottom: none;
|
||||
}
|
||||
.laydate-theme-molv .laydate-main-list-1 .layui-laydate-content {
|
||||
border-left: none;
|
||||
}
|
||||
.laydate-theme-molv .layui-laydate-footer {
|
||||
border: 1px solid #e2e2e2;
|
||||
}
|
||||
|
||||
/* 格子主题 */
|
||||
.laydate-theme-grid .layui-laydate-content td,
|
||||
.laydate-theme-grid .layui-laydate-content thead,
|
||||
.laydate-theme-grid .laydate-year-list > li,
|
||||
.laydate-theme-grid .laydate-month-list > li {
|
||||
border: 1px solid #e2e2e2;
|
||||
}
|
||||
.laydate-theme-grid .laydate-selected,
|
||||
.laydate-theme-grid .laydate-selected:hover {
|
||||
background-color: #f2f2f2 !important;
|
||||
color: #009688 !important;
|
||||
}
|
||||
.laydate-theme-grid .laydate-selected.laydate-day-prev,
|
||||
.laydate-theme-grid .laydate-selected.laydate-day-next {
|
||||
color: #d2d2d2 !important;
|
||||
}
|
||||
.laydate-theme-grid .laydate-year-list,
|
||||
.laydate-theme-grid .laydate-month-list {
|
||||
margin: 1px 0 0 1px;
|
||||
}
|
||||
.laydate-theme-grid .laydate-year-list > li,
|
||||
.laydate-theme-grid .laydate-month-list > li {
|
||||
margin: 0 -1px -1px 0;
|
||||
}
|
||||
.laydate-theme-grid .laydate-year-list > li {
|
||||
height: 43px;
|
||||
line-height: 43px;
|
||||
}
|
||||
.laydate-theme-grid .laydate-month-list > li {
|
||||
height: 71px;
|
||||
line-height: 71px;
|
||||
}
|
||||
.laydate-range-hover{
|
||||
background-color: var(--global-neutral-color-2) !important;
|
||||
}
|
||||
.layui-laydate-content .layui-disabled:hover{
|
||||
background-color: transparent !important;
|
||||
}
|
||||
|
||||
.laydate-range-inputs{
|
||||
display: flex;
|
||||
align-items: center;
|
||||
border-width: 1px;
|
||||
border-style: solid;
|
||||
display: inline-flex;
|
||||
border-color: var(--input-border-color);
|
||||
border-radius: var(--input-border-radius);
|
||||
.range-separator{
|
||||
margin: 0 5px;
|
||||
color: var(--global-neutral-color-8);
|
||||
background-color: transparent;
|
||||
}
|
||||
.layui-input-wrapper{
|
||||
border: none;
|
||||
box-sizing: border-box;
|
||||
input{
|
||||
text-align: center;
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
.layui-input {
|
||||
border: none;
|
||||
}
|
||||
}
|
||||
.layui-laydate-range{
|
||||
.laydate-set-ym{
|
||||
overflow: visible;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.laydate-set-ym .layui-dropdown{
|
||||
width: auto !important;
|
||||
}
|
||||
|
||||
.time-panel{
|
||||
.layui-laydate-main{
|
||||
width: 272px;
|
||||
display: unset !important;
|
||||
}
|
||||
.layui-laydate-preview{
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
.layui-laydate-content{
|
||||
.laydate-year-list{
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
}
|
||||
.layui-laydate-list{
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
}
|
||||
.layui-laydate-range-datetime{
|
||||
.layui-laydate-main{
|
||||
width: 340px;
|
||||
}
|
||||
}
|
||||
5
src/component/datePicker/index.ts
Normal file
5
src/component/datePicker/index.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
import { withInstall, WithInstallType } from "../../utils";
|
||||
import Component from "./index.vue";
|
||||
|
||||
const component: WithInstallType<typeof Component> = withInstall(Component);
|
||||
export default component;
|
||||
417
src/component/datePicker/index.vue
Normal file
417
src/component/datePicker/index.vue
Normal file
@@ -0,0 +1,417 @@
|
||||
<template>
|
||||
<div
|
||||
:class="['layui-date-picker', { 'layui-date-range-picker': range }]"
|
||||
:size="size"
|
||||
>
|
||||
<lay-dropdown
|
||||
ref="dropdownRef"
|
||||
:disabled="disabled"
|
||||
:autoFitMinWidth="false"
|
||||
:contentClass="contentClass"
|
||||
:contentStyle="contentStyle"
|
||||
updateAtScroll
|
||||
>
|
||||
<lay-input
|
||||
:name="name"
|
||||
:readonly="readonly"
|
||||
:placeholder="startPlaceholder"
|
||||
:prefix-icon="prefixIcon"
|
||||
:suffix-icon="suffixIcon"
|
||||
:disabled="disabled"
|
||||
v-model="dateValue"
|
||||
v-if="!range"
|
||||
@change="onChange"
|
||||
@blur="$emit('blur')"
|
||||
@focus="$emit('focus')"
|
||||
:allow-clear="!disabled && allowClear"
|
||||
:size="size"
|
||||
@clear="
|
||||
dateValue = '';
|
||||
onChange();
|
||||
"
|
||||
>
|
||||
</lay-input>
|
||||
<div class="laydate-range-inputs" v-else>
|
||||
<lay-input
|
||||
:readonly="readonly"
|
||||
:name="name"
|
||||
v-model="dateValue[0]"
|
||||
:placeholder="startPlaceholder"
|
||||
:disabled="disabled"
|
||||
@change="onChange"
|
||||
@blur="$emit('blur')"
|
||||
@focus="$emit('focus')"
|
||||
class="start-input"
|
||||
:size="size"
|
||||
>
|
||||
</lay-input>
|
||||
<span class="range-separator">{{ rangeSeparator }}</span>
|
||||
<lay-input
|
||||
:readonly="readonly"
|
||||
:name="name"
|
||||
:allow-clear="disabled && allowClear"
|
||||
:placeholder="endPlaceholder"
|
||||
v-model="dateValue[1]"
|
||||
:disabled="disabled"
|
||||
@change="onChange"
|
||||
@blur="$emit('blur')"
|
||||
@focus="$emit('focus')"
|
||||
class="end-input"
|
||||
:size="size"
|
||||
@clear="
|
||||
dateValue = [];
|
||||
onChange();
|
||||
"
|
||||
>
|
||||
</lay-input>
|
||||
</div>
|
||||
|
||||
<template #content>
|
||||
<!-- 日期选择 -->
|
||||
<DatePanel
|
||||
v-if="!range && (showPanel === 'date' || showPanel === 'datetime')"
|
||||
v-model="currentDay"
|
||||
></DatePanel>
|
||||
<!-- 时间选择 -->
|
||||
<TimePanel
|
||||
v-if="!range && showPanel === 'time'"
|
||||
v-model="hms"
|
||||
></TimePanel>
|
||||
<!-- 年份选择器 -->
|
||||
<YearPanel
|
||||
v-if="!range && (showPanel === 'year' || showPanel === 'yearmonth')"
|
||||
v-model="currentYear"
|
||||
>
|
||||
</YearPanel>
|
||||
<!-- 月份选择器 -->
|
||||
<MonthPanel
|
||||
v-if="!range && showPanel === 'month'"
|
||||
v-model="currentMonth"
|
||||
></MonthPanel>
|
||||
<!-- 范围选择 -->
|
||||
<DateRange
|
||||
v-if="range && (showPanel === 'date' || showPanel === 'datetime')"
|
||||
v-model:startTime="rangeValue.first"
|
||||
v-model:endTime="rangeValue.last"
|
||||
></DateRange>
|
||||
|
||||
<MonthRange
|
||||
v-if="range && showPanel === 'yearmonth'"
|
||||
v-model:startTime="rangeValue.first"
|
||||
v-model:endTime="rangeValue.last"
|
||||
>
|
||||
</MonthRange>
|
||||
</template>
|
||||
</lay-dropdown>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
export default {
|
||||
name: "LayDatePicker",
|
||||
};
|
||||
</script>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import "./index.less";
|
||||
import dayjs from "dayjs";
|
||||
import { LayIcon } from "@layui/icons-vue";
|
||||
import LayInput from "../input/index.vue";
|
||||
import LayDropdown from "../dropdown/index.vue";
|
||||
import { getMonth, getYear, getDay } from "./day";
|
||||
import {
|
||||
ref,
|
||||
watch,
|
||||
defineProps,
|
||||
defineEmits,
|
||||
reactive,
|
||||
provide,
|
||||
StyleValue,
|
||||
} from "vue";
|
||||
import DatePanel from "./components/DatePanel.vue";
|
||||
import TimePanel from "./components/TimePanel.vue";
|
||||
import YearPanel from "./components/YearPanel.vue";
|
||||
import MonthPanel from "./components/MonthPanel.vue";
|
||||
import DateRange from "./components/DateRange.vue";
|
||||
import MonthRange from "./components/MonthRange.vue";
|
||||
import { computed } from "@vue/reactivity";
|
||||
|
||||
export interface DatePickerProps {
|
||||
type?: "date" | "datetime" | "year" | "time" | "month" | "yearmonth";
|
||||
placeholder?: string | string[];
|
||||
modelValue?: string | number | string[];
|
||||
disabled?: boolean;
|
||||
simple?: boolean;
|
||||
name?: string;
|
||||
max?: string;
|
||||
min?: string;
|
||||
range?: boolean;
|
||||
rangeSeparator?: string;
|
||||
readonly?: boolean;
|
||||
allowClear?: boolean;
|
||||
size?: "lg" | "md" | "sm" | "xs";
|
||||
prefixIcon?: string;
|
||||
suffixIcon?: string;
|
||||
timestamp?: boolean;
|
||||
contentClass?: string | Array<string | object> | object;
|
||||
contentStyle?: StyleValue;
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<DatePickerProps>(), {
|
||||
modelValue: "",
|
||||
type: "date",
|
||||
disabled: false,
|
||||
simple: false,
|
||||
range: false,
|
||||
rangeSeparator: "至",
|
||||
readonly: false,
|
||||
allowClear: false,
|
||||
size: "md",
|
||||
prefixIcon: "layui-icon-date",
|
||||
suffixIcon: "",
|
||||
timestamp: false,
|
||||
});
|
||||
|
||||
const startPlaceholder = computed(() => {
|
||||
if (Array.isArray(props.placeholder)) {
|
||||
return props.placeholder[0];
|
||||
}
|
||||
return props.placeholder;
|
||||
});
|
||||
|
||||
const endPlaceholder = computed(() => {
|
||||
if (Array.isArray(props.placeholder)) {
|
||||
return props.placeholder[1];
|
||||
}
|
||||
return props.placeholder;
|
||||
});
|
||||
|
||||
const dropdownRef = ref(null);
|
||||
const $emits = defineEmits(["update:modelValue", "change", "blur", "focus"]);
|
||||
const hms = ref({
|
||||
hh: 0,
|
||||
mm: 0,
|
||||
ss: 0,
|
||||
});
|
||||
const currentYear = ref<number>(0);
|
||||
const currentMonth = ref<number>(0);
|
||||
const currentDay = ref<number>(0);
|
||||
const showPanel = ref<string>("date");
|
||||
const rangeValue = reactive({ first: "", last: "" });
|
||||
|
||||
let unWatch = false;
|
||||
// 计算结果日期
|
||||
const dateValue = props.range ? ref(["", ""]) : ref("");
|
||||
const getDateValue = () => {
|
||||
unWatch = true;
|
||||
let dayjsVal;
|
||||
switch (props.type) {
|
||||
case "date":
|
||||
dayjsVal =
|
||||
currentDay.value !== -1
|
||||
? dayjs(currentDay.value).format("YYYY-MM-DD")
|
||||
: "";
|
||||
break;
|
||||
case "datetime":
|
||||
dayjsVal =
|
||||
currentDay.value !== -1
|
||||
? dayjs(currentDay.value)
|
||||
.hour(hms.value.hh)
|
||||
.minute(hms.value.mm)
|
||||
.second(hms.value.ss)
|
||||
.format("YYYY-MM-DD HH:mm:ss")
|
||||
: "";
|
||||
break;
|
||||
case "year":
|
||||
dayjsVal =
|
||||
currentYear.value !== -1
|
||||
? dayjs().year(currentYear.value).format("YYYY")
|
||||
: "";
|
||||
break;
|
||||
case "month":
|
||||
dayjsVal =
|
||||
currentMonth.value !== -1 ? (currentMonth.value + 1).toString() : "";
|
||||
break;
|
||||
case "time":
|
||||
dayjsVal = dayjs()
|
||||
.hour(hms.value.hh)
|
||||
.minute(hms.value.mm)
|
||||
.second(hms.value.ss)
|
||||
.format("HH:mm:ss");
|
||||
break;
|
||||
case "yearmonth":
|
||||
dayjsVal =
|
||||
currentYear.value !== -1 && currentMonth.value !== -1
|
||||
? dayjs()
|
||||
.year(currentYear.value)
|
||||
.month(currentMonth.value)
|
||||
.format("YYYY-MM")
|
||||
: "";
|
||||
break;
|
||||
default:
|
||||
dayjsVal =
|
||||
currentDay.value !== -1
|
||||
? dayjs(currentDay.value)
|
||||
.hour(hms.value.hh)
|
||||
.minute(hms.value.mm)
|
||||
.second(hms.value.ss)
|
||||
.format()
|
||||
: "";
|
||||
break;
|
||||
}
|
||||
dateValue.value = dayjsVal !== "Invalid Date" ? dayjsVal : "";
|
||||
if (dayjsVal === "Invalid Date") {
|
||||
unWatch = false;
|
||||
$emits("update:modelValue", "");
|
||||
return;
|
||||
}
|
||||
if (props.timestamp) {
|
||||
$emits("update:modelValue", dayjs(dayjsVal).unix() * 1000);
|
||||
$emits("change", dayjs(dayjsVal).unix() * 1000);
|
||||
} else {
|
||||
$emits("update:modelValue", dayjsVal);
|
||||
$emits("change", dayjsVal);
|
||||
}
|
||||
setTimeout(() => {
|
||||
unWatch = false;
|
||||
}, 0);
|
||||
};
|
||||
const getDateValueByRange = () => {
|
||||
unWatch = true;
|
||||
if (rangeValue.first === "" || rangeValue.last === "") {
|
||||
dateValue.value = ["", ""];
|
||||
$emits("update:modelValue", dateValue.value);
|
||||
$emits("change", dateValue.value);
|
||||
return;
|
||||
}
|
||||
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 = [
|
||||
dayjs(rangeValue.first).format(format),
|
||||
dayjs(rangeValue.last).format(format),
|
||||
];
|
||||
$emits("update:modelValue", dateValue.value);
|
||||
$emits("change", dateValue.value);
|
||||
setTimeout(() => {
|
||||
unWatch = false;
|
||||
}, 0);
|
||||
};
|
||||
|
||||
// 确认事件
|
||||
const ok = () => {
|
||||
if (!props.range) {
|
||||
getDateValue();
|
||||
} else {
|
||||
getDateValueByRange();
|
||||
}
|
||||
if (dropdownRef.value)
|
||||
// @ts-ignore
|
||||
dropdownRef.value.hide();
|
||||
showPanel.value = props.type;
|
||||
};
|
||||
|
||||
//面板类型判断
|
||||
watch(
|
||||
() => props.type,
|
||||
() => {
|
||||
showPanel.value = props.type;
|
||||
if (props.type === "yearmonth" && !props.range) {
|
||||
showPanel.value = "year";
|
||||
}
|
||||
},
|
||||
{ immediate: true }
|
||||
);
|
||||
|
||||
//监听modelValue改变
|
||||
watch(
|
||||
() => props.modelValue,
|
||||
() => {
|
||||
if (unWatch) {
|
||||
return;
|
||||
}
|
||||
let initModelValue: string =
|
||||
props.range && props.modelValue
|
||||
? (props.modelValue as string[])[0] || ""
|
||||
: (props.modelValue as string);
|
||||
if (props.type === "month" || props.type === "year") {
|
||||
initModelValue += "";
|
||||
}
|
||||
|
||||
hms.value.hh = isNaN(dayjs(initModelValue).hour())
|
||||
? 0
|
||||
: dayjs(initModelValue).hour();
|
||||
hms.value.mm = isNaN(dayjs(initModelValue).minute())
|
||||
? 0
|
||||
: dayjs(initModelValue).minute();
|
||||
hms.value.ss = isNaN(dayjs(initModelValue).second())
|
||||
? 0
|
||||
: dayjs(initModelValue).second();
|
||||
|
||||
if (initModelValue.length === 8 && props.type === "time") {
|
||||
let modelValue = initModelValue;
|
||||
modelValue = "1970-01-01 " + modelValue;
|
||||
hms.value.hh = dayjs(modelValue).hour();
|
||||
hms.value.mm = dayjs(modelValue).minute();
|
||||
hms.value.ss = dayjs(modelValue).second();
|
||||
}
|
||||
|
||||
currentYear.value = initModelValue ? getYear(initModelValue) : -1;
|
||||
currentMonth.value = initModelValue ? getMonth(initModelValue) : -1;
|
||||
currentDay.value = initModelValue ? getDay(initModelValue) : -1;
|
||||
if (props.type === "date" || props.type === "datetime") {
|
||||
if (currentYear.value === -1) currentYear.value = dayjs().year();
|
||||
if (currentMonth.value === -1) currentMonth.value = dayjs().month();
|
||||
if (props.timestamp) {
|
||||
currentDay.value = initModelValue
|
||||
? dayjs(parseInt(initModelValue)).startOf("date").unix() * 1000
|
||||
: -1;
|
||||
}
|
||||
}
|
||||
rangeValue.first = initModelValue;
|
||||
rangeValue.last =
|
||||
props.range && props.modelValue
|
||||
? (props.modelValue as string[])[1] || ""
|
||||
: "";
|
||||
if (!props.range) {
|
||||
getDateValue();
|
||||
} else {
|
||||
getDateValueByRange();
|
||||
}
|
||||
},
|
||||
{ immediate: true }
|
||||
);
|
||||
|
||||
const onChange = () => {
|
||||
if (dropdownRef.value)
|
||||
// @ts-ignore
|
||||
dropdownRef.value.hide();
|
||||
$emits("update:modelValue", dateValue.value);
|
||||
};
|
||||
|
||||
provide("datePicker", {
|
||||
currentYear: currentYear,
|
||||
currentMonth: currentMonth,
|
||||
currentDay: currentDay,
|
||||
dateValue: dateValue,
|
||||
type: props.type,
|
||||
showPanel: showPanel,
|
||||
hms: hms,
|
||||
ok: () => ok(),
|
||||
getDateValue: () => getDateValue,
|
||||
range: props.range,
|
||||
rangeValue: rangeValue,
|
||||
rangeSeparator: props.rangeSeparator,
|
||||
simple: props.simple,
|
||||
timestamp: props.timestamp,
|
||||
});
|
||||
</script>
|
||||
27
src/component/datePicker/interface.ts
Normal file
27
src/component/datePicker/interface.ts
Normal file
@@ -0,0 +1,27 @@
|
||||
import { Ref } from "vue";
|
||||
|
||||
export type DatePickerType = "date" | "datetime" | "year" | "time" | "month";
|
||||
|
||||
export type provideType = {
|
||||
currentYear: Ref;
|
||||
currentMonth: Ref;
|
||||
currentDay: Ref;
|
||||
dateValue: Ref;
|
||||
hms: Ref;
|
||||
type: string;
|
||||
showPanel: Ref;
|
||||
clear: Function;
|
||||
now: Function;
|
||||
ok: Function;
|
||||
range: boolean;
|
||||
rangeValue: {
|
||||
first: string;
|
||||
last: string;
|
||||
hover: string;
|
||||
firstTime: { hh: number; mm: number; ss: number };
|
||||
lastTime: { hh: number; mm: number; ss: number };
|
||||
};
|
||||
rangeSeparator: string;
|
||||
simple: boolean;
|
||||
timestamp: boolean;
|
||||
};
|
||||
Reference in New Issue
Block a user