123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208 |
- import { createVNode as _createVNode } from "vue";
- import { ref, computed, defineComponent } from "vue";
- import { pick, addUnit, numericProp, setScrollTop, createNamespace, makeRequiredProp } from "../utils/index.mjs";
- import { getMonthEndDay } from "../datetime-picker/utils.mjs";
- import { t, bem, compareDay, getPrevDay, getNextDay, formatMonthTitle } from "./utils.mjs";
- import { useRect, useToggle } from "@vant/use";
- import { useExpose } from "../composables/use-expose.mjs";
- import { useHeight } from "../composables/use-height.mjs";
- import CalendarDay from "./CalendarDay.mjs";
- const [name] = createNamespace("calendar-month");
- const calendarMonthProps = {
- date: makeRequiredProp(Date),
- type: String,
- color: String,
- minDate: makeRequiredProp(Date),
- maxDate: makeRequiredProp(Date),
- showMark: Boolean,
- rowHeight: numericProp,
- formatter: Function,
- lazyRender: Boolean,
- currentDate: [Date, Array],
- allowSameDay: Boolean,
- showSubtitle: Boolean,
- showMonthTitle: Boolean,
- firstDayOfWeek: Number
- };
- var stdin_default = defineComponent({
- name,
- props: calendarMonthProps,
- emits: ["click", "update-height"],
- setup(props, {
- emit,
- slots
- }) {
- const [visible, setVisible] = useToggle();
- const daysRef = ref();
- const monthRef = ref();
- const height = useHeight(monthRef);
- const title = computed(() => formatMonthTitle(props.date));
- const rowHeight = computed(() => addUnit(props.rowHeight));
- const offset = computed(() => {
- const realDay = props.date.getDay();
- if (props.firstDayOfWeek) {
- return (realDay + 7 - props.firstDayOfWeek) % 7;
- }
- return realDay;
- });
- const totalDay = computed(() => getMonthEndDay(props.date.getFullYear(), props.date.getMonth() + 1));
- const shouldRender = computed(() => visible.value || !props.lazyRender);
- const getTitle = () => title.value;
- const getMultipleDayType = (day) => {
- const isSelected = (date) => props.currentDate.some((item) => compareDay(item, date) === 0);
- if (isSelected(day)) {
- const prevDay = getPrevDay(day);
- const nextDay = getNextDay(day);
- const prevSelected = isSelected(prevDay);
- const nextSelected = isSelected(nextDay);
- if (prevSelected && nextSelected) {
- return "multiple-middle";
- }
- if (prevSelected) {
- return "end";
- }
- if (nextSelected) {
- return "start";
- }
- return "multiple-selected";
- }
- return "";
- };
- const getRangeDayType = (day) => {
- const [startDay, endDay] = props.currentDate;
- if (!startDay) {
- return "";
- }
- const compareToStart = compareDay(day, startDay);
- if (!endDay) {
- return compareToStart === 0 ? "start" : "";
- }
- const compareToEnd = compareDay(day, endDay);
- if (props.allowSameDay && compareToStart === 0 && compareToEnd === 0) {
- return "start-end";
- }
- if (compareToStart === 0) {
- return "start";
- }
- if (compareToEnd === 0) {
- return "end";
- }
- if (compareToStart > 0 && compareToEnd < 0) {
- return "middle";
- }
- return "";
- };
- const getDayType = (day) => {
- const {
- type,
- minDate,
- maxDate,
- currentDate
- } = props;
- if (compareDay(day, minDate) < 0 || compareDay(day, maxDate) > 0) {
- return "disabled";
- }
- if (currentDate === null) {
- return "";
- }
- if (Array.isArray(currentDate)) {
- if (type === "multiple") {
- return getMultipleDayType(day);
- }
- if (type === "range") {
- return getRangeDayType(day);
- }
- } else if (type === "single") {
- return compareDay(day, currentDate) === 0 ? "selected" : "";
- }
- return "";
- };
- const getBottomInfo = (dayType) => {
- if (props.type === "range") {
- if (dayType === "start" || dayType === "end") {
- return t(dayType);
- }
- if (dayType === "start-end") {
- return `${t("start")}/${t("end")}`;
- }
- }
- };
- const renderTitle = () => {
- if (props.showMonthTitle) {
- return _createVNode("div", {
- "class": bem("month-title")
- }, [title.value]);
- }
- };
- const renderMark = () => {
- if (props.showMark && shouldRender.value) {
- return _createVNode("div", {
- "class": bem("month-mark")
- }, [props.date.getMonth() + 1]);
- }
- };
- const placeholders = computed(() => {
- const count = Math.ceil((totalDay.value + offset.value) / 7);
- return Array(count).fill({
- type: "placeholder"
- });
- });
- const days = computed(() => {
- const days2 = [];
- const year = props.date.getFullYear();
- const month = props.date.getMonth();
- for (let day = 1; day <= totalDay.value; day++) {
- const date = new Date(year, month, day);
- const type = getDayType(date);
- let config = {
- date,
- type,
- text: day,
- bottomInfo: getBottomInfo(type)
- };
- if (props.formatter) {
- config = props.formatter(config);
- }
- days2.push(config);
- }
- return days2;
- });
- const disabledDays = computed(() => days.value.filter((day) => day.type === "disabled"));
- const scrollToDate = (body, targetDate) => {
- if (daysRef.value) {
- const daysRect = useRect(daysRef.value);
- const totalRows = placeholders.value.length;
- const currentRow = Math.ceil((targetDate.getDate() + offset.value) / 7);
- const rowOffset = (currentRow - 1) * daysRect.height / totalRows;
- setScrollTop(body, daysRect.top + rowOffset + body.scrollTop - useRect(body).top);
- }
- };
- const renderDay = (item, index) => _createVNode(CalendarDay, {
- "item": item,
- "index": index,
- "color": props.color,
- "offset": offset.value,
- "rowHeight": rowHeight.value,
- "onClick": (item2) => emit("click", item2)
- }, pick(slots, ["top-info", "bottom-info"]));
- const renderDays = () => _createVNode("div", {
- "ref": daysRef,
- "role": "grid",
- "class": bem("days")
- }, [renderMark(), (shouldRender.value ? days : placeholders).value.map(renderDay)]);
- useExpose({
- getTitle,
- getHeight: () => height.value,
- setVisible,
- scrollToDate,
- disabledDays
- });
- return () => _createVNode("div", {
- "class": bem("month"),
- "ref": monthRef
- }, [renderTitle(), renderDays()]);
- }
- });
- export {
- stdin_default as default
- };
|