UNPKG

song-ui-u

Version:

vue3 + js的PC前端组件库

601 lines (598 loc) 22.6 kB
import { defineComponent, ref, computed, onMounted, onUnmounted, createVNode, createTextVNode, resolveComponent } from 'vue'; import '../../button/index.mjs'; import '../../buttonGroup/index.mjs'; import { XIcon } from '../../icon/index.mjs'; import { XInput } from '../../input/index.mjs'; import '../../textarea/index.mjs'; import '../../row/index.mjs'; import '../../col/index.mjs'; import '../../container/index.mjs'; import '../../checkbox/index.mjs'; import '../../switch/index.mjs'; import '../../form/index.mjs'; import '../../message/index.mjs'; import '../../mask/src/mask.mjs'; import '../../modal/index.mjs'; import '../../messageBox/index.mjs'; import '../../drawer/index.mjs'; import '../../badge/index.mjs'; import '../../space/index.mjs'; import '../../image/index.mjs'; import '../../radio/index.mjs'; import '../../divider/index.mjs'; import '../../chat/index.mjs'; import '../../progress/index.mjs'; import '../../upload/index.mjs'; import '../../vTree/index.mjs'; import '../../table/index.mjs'; import '../../tabs/index.mjs'; import '../../menu/index.mjs'; import '../../steps/index.mjs'; import '../../header/index.mjs'; import '../../breadcrumble/index.mjs'; import '../index.mjs'; import '../../tooltip/index.mjs'; import '../../popover/index.mjs'; import '../../timePicker/index.mjs'; import '../../select/index.mjs'; import '../../collapse/index.mjs'; import '../../card/index.mjs'; import '../../timeline/index.mjs'; import '../../tag/index.mjs'; import '../../result/index.mjs'; import '../../sender/index.mjs'; import { Calendar, ChevronsLeft, ChevronLeft, ChevronRight, ChevronsRight } from 'song-ui-pro-icon'; import { useNamespace } from '../../../hook/use-namespace/index.mjs'; import '../../../hook/use-zindex/index.mjs'; import { addMonths, parse, format, setMonth, setYear, isSameDay, setDate, endOfMonth, getDay, subDays, isToday, addDays, isAfter, isBefore, subYears, addYears, subMonths } from 'date-fns'; var datePicker = /* @__PURE__ */ defineComponent({ name: "x-date-picker", props: { modelValue: { type: [String, Date, Array], default: "" }, placeholder: { type: String, default: "\u8BF7\u9009\u62E9\u65E5\u671F" }, format: { type: String, default: "yyyy-MM-dd" }, disabled: { type: Boolean, default: false }, readonly: { type: Boolean, default: false }, clearance: { type: Boolean, default: true }, model: { type: String, default: "date" }, multiple: { type: Boolean, default: false }, range: { type: Boolean, default: false }, startPlaceholder: { type: String, default: "\u5F00\u59CB\u65E5\u671F" }, endPlaceholder: { type: String, default: "\u7ED3\u675F\u65E5\u671F" } }, setup(props, { emit }) { const ns = useNamespace("date-picker"); const visible = ref(false); const currentDate = ref(new Date(props.modelValue || /* @__PURE__ */ new Date())); const nextMonthDate = ref(addMonths(currentDate.value, 1)); const displayValue = ref(""); const weekDays = ["\u65E5", "\u4E00", "\u4E8C", "\u4E09", "\u56DB", "\u4E94", "\u516D"]; const rangeState = ref({ selecting: false, // 是否正在选择范围 startDate: null, // 开始日期 endDate: null // 结束日期 }); if (props.range && Array.isArray(props.modelValue) && props.modelValue.length === 2) { rangeState.value.startDate = parse(props.modelValue[0], props.format, /* @__PURE__ */ new Date()); rangeState.value.endDate = parse(props.modelValue[1], props.format, /* @__PURE__ */ new Date()); displayValue.value = `${formatDate(rangeState.value.startDate)} \u81F3 ${formatDate(rangeState.value.endDate)}`; } const currentYear = computed(() => currentDate.value.getFullYear()); const currentMonth = computed(() => currentDate.value.getMonth()); const placeholder = computed(() => { if (props.range) return `${props.startPlaceholder} \u81F3 ${props.endPlaceholder}`; if (props.model == "date") return "\u8BF7\u9009\u62E9\u65E5\u671F"; if (props.model == "year") return "\u8BF7\u9009\u62E9\u5E74\u4EFD"; if (props.model == "month") return "\u8BF7\u9009\u62E9\u6708\u4EFD"; }); const years = computed(() => { const startYear = currentYear.value - 10; const endYear = currentYear.value + 10; const years2 = []; for (let year = startYear; year <= endYear; year++) { years2.push({ year, isSelected: isSelected(year), isYear: isYear(year) }); } return years2; }); const months = computed(() => { const months2 = []; for (let month = 0; month < 12; month++) { months2.push({ month, name: `${month + 1}\u6708`, isSelected: isSelectedMonth(month), isCurrentMonth: isCurrentMonth(month) }); } return months2; }); const isSelectedMonth = (month) => { if (!props.modelValue) return false; if (props.model === "month") { if (props.multiple) { const formattedMonth = format(setMonth(setYear(/* @__PURE__ */ new Date(), currentYear.value), month), "yyyy-MM"); return multipleData.value.includes(formattedMonth); } return month === new Date(props.modelValue).getMonth(); } return false; }; const isCurrentMonth = (month) => { return month === (/* @__PURE__ */ new Date()).getMonth(); }; const isYear = (data) => { return data == currentYear.value; }; const isSelected = (value) => { if (!props.modelValue) return false; if (props.model === "date") { if (props.range) { const date = new Date(value); if (!rangeState.value.startDate && !rangeState.value.endDate) return false; if (rangeState.value.startDate && isSameDay(date, rangeState.value.startDate)) return true; if (rangeState.value.endDate && isSameDay(date, rangeState.value.endDate)) return true; return false; } if (props.multiple) { return multipleData.value.includes(formatDate(value)); } return isSameDay(new Date(value), new Date(props.modelValue)); } if (props.model === "year") { if (props.multiple) { return multipleData.value.includes(value.toString()); } return value == new Date(props.modelValue).getFullYear(); } if (props.model === "month") { if (props.multiple) { const formattedMonth = format(setMonth(setYear(/* @__PURE__ */ new Date(), currentYear.value), value), "yyyy-MM"); return multipleData.value.includes(formattedMonth); } return value == new Date(props.modelValue).getMonth(); } return false; }; const isInRange = (value) => { if (!props.range || !rangeState.value.startDate || !rangeState.value.endDate) return false; const date = new Date(value); const start = rangeState.value.startDate; const end = rangeState.value.endDate; return isAfter(date, start) && isBefore(date, end); }; const formatDate = (date) => { return format(date, props.format); }; const showPanel = () => { if (props.disabled || props.readonly) return; visible.value = true; console.log("showPanel", visible.value); }; const handleClear = () => { emit("update:modelValue", props.range ? [] : ""); emit("change", props.range ? [] : ""); displayValue.value = ""; if (props.multiple) { multipleData.value = []; visible.value = false; } if (props.range) { rangeState.value.startDate = null; rangeState.value.endDate = null; rangeState.value.selecting = false; } }; const multipleData = ref([]); const selectDate = (value) => { if (props.model === "year") { const formattedYear = value.toString(); emit("update:modelValue", formattedYear); emit("change", formattedYear); if (!props.multiple) { displayValue.value = formattedYear; } if (props.multiple) { if (multipleData.value.includes(formattedYear)) { multipleData.value = multipleData.value.filter((item) => item !== formattedYear); } else { multipleData.value.push(formattedYear); } } return; } if (props.model === "month") { const selectedDate = setMonth(setYear(/* @__PURE__ */ new Date(), currentYear.value), value.month); const formattedMonth = format(selectedDate, "yyyy-MM"); emit("update:modelValue", formattedMonth); emit("change", formattedMonth); console.log(format(selectedDate, "yyyy-MM")); if (!props.multiple) { displayValue.value = formattedMonth; } if (props.multiple) { if (multipleData.value.includes(formattedMonth)) { multipleData.value = multipleData.value.filter((item) => item !== formattedMonth); } else { multipleData.value.push(formattedMonth); } } return; } if (!value.isCurrentMonth) { currentDate.value = value.date; return; } if (props.model === "date") { if (props.range) { const selectedDate = value.date; if (!rangeState.value.selecting) { rangeState.value.startDate = selectedDate; rangeState.value.endDate = null; rangeState.value.selecting = true; } else { if (isBefore(selectedDate, rangeState.value.startDate)) { rangeState.value.endDate = rangeState.value.startDate; rangeState.value.startDate = selectedDate; } else { rangeState.value.endDate = selectedDate; } const startFormatted = formatDate(rangeState.value.startDate); const endFormatted = formatDate(rangeState.value.endDate); emit("update:modelValue", [startFormatted, endFormatted]); emit("change", [startFormatted, endFormatted]); displayValue.value = `${startFormatted} \u81F3 ${endFormatted}`; rangeState.value.selecting = false; visible.value = false; } return; } if (!props.multiple) { const formattedDate = formatDate(value.date); emit("update:modelValue", formattedDate); emit("change", formattedDate); displayValue.value = formattedDate; visible.value = false; return; } if (props.multiple) { if (multipleData.value.includes(formatDate(value.date))) { multipleData.value = multipleData.value.filter((item) => item !== formatDate(value.date)); } else { multipleData.value.push(formatDate(value.date)); } } } if (!props.multiple) { visible.value = false; } }; const confirm = () => { visible.value = false; emit("update:modelValue", multipleData.value.join(",")); emit("change", multipleData.value.join(",")); displayValue.value = multipleData.value.join(","); }; const prevYear = () => { currentDate.value = subYears(currentDate.value, 1); if (props.range) { nextMonthDate.value = subYears(nextMonthDate.value, 1); } }; const nextYear = () => { currentDate.value = addYears(currentDate.value, 1); if (props.range) { nextMonthDate.value = addYears(nextMonthDate.value, 1); } }; const prevMonth = () => { currentDate.value = subMonths(currentDate.value, 1); if (props.range) { nextMonthDate.value = subMonths(nextMonthDate.value, 1); } }; const nextMonth = () => { currentDate.value = addMonths(currentDate.value, 1); if (props.range) { nextMonthDate.value = addMonths(nextMonthDate.value, 1); } }; const generateUniqueId = () => { return `date-picker-${Math.random().toString(36).substr(2, 9)}`; }; const uniqueId = ref(generateUniqueId()); const handleClickOutside = (e) => { const root = e.currentTarget; const panel = root.querySelector(".x-date-picker__panel"); const input = root.querySelector(".x-date-picker__input"); if (panel && !panel.contains(e.target) && !input.contains(e.target)) { visible.value = false; } }; onMounted(() => { const root = document.querySelector(`[data-id="${uniqueId.value}"]`); if (root) { root.addEventListener("click", handleClickOutside); } }); onUnmounted(() => { const root = document.querySelector(`[data-id="${uniqueId.value}"]`); if (root) { root.removeEventListener("click", handleClickOutside); } }); const nextMonthDays = computed(() => { const year = nextMonthDate.value.getFullYear(); const month = nextMonthDate.value.getMonth(); const firstDay = setDate(setMonth(setYear(/* @__PURE__ */ new Date(), year), month), 1); const lastDay = endOfMonth(setMonth(setYear(/* @__PURE__ */ new Date(), year), month)); const days2 = []; for (let i = getDay(firstDay); i > 0; i--) { const date = subDays(firstDay, i); days2.push({ day: date.getDate(), date, isCurrentMonth: false }); } for (let i = 1; i <= lastDay.getDate(); i++) { const date = setDate(setMonth(setYear(/* @__PURE__ */ new Date(), year), month), i); days2.push({ day: i, date, isCurrentMonth: true, isToday: isToday(date), isSelected: isSelected(date), isInRange: isInRange(date) }); } const remaining = 42 - days2.length; for (let i = 1; i <= remaining; i++) { const date = addDays(lastDay, i); days2.push({ day: date.getDate(), date, isCurrentMonth: false }); } return days2; }); const days = computed(() => { const year = currentYear.value; const month = currentMonth.value; const firstDay = setDate(setMonth(setYear(/* @__PURE__ */ new Date(), year), month), 1); const lastDay = endOfMonth(setMonth(setYear(/* @__PURE__ */ new Date(), year), month)); const days2 = []; for (let i = getDay(firstDay); i > 0; i--) { const date = subDays(firstDay, i); days2.push({ day: date.getDate(), date, isCurrentMonth: false }); } for (let i = 1; i <= lastDay.getDate(); i++) { const date = setDate(setMonth(setYear(/* @__PURE__ */ new Date(), year), month), i); days2.push({ day: i, date, isCurrentMonth: true, isToday: isToday(date), isSelected: isSelected(date), isInRange: isInRange(date) }); } const remaining = 42 - days2.length; for (let i = 1; i <= remaining; i++) { const date = addDays(lastDay, i); days2.push({ day: date.getDate(), date, isCurrentMonth: false }); } return days2; }); const renderDays = (data, getKey, getContent, getClasses, onClick) => { return createVNode("div", { "class": ns.e("days") }, [data.map((item, index) => createVNode("span", { "key": getKey(item, index), "class": getClasses(item), "onClick": () => onClick(item) }, [getContent(item)]))]); }; return () => createVNode("div", { "data-id": uniqueId.value, "class": ns.b() }, [createVNode("div", { "class": [ns.e("input"), ns.is("range", props.range)], "onClick": showPanel }, [createVNode(XInput, { "modelValue": displayValue.value, "placeholder": placeholder.value, "disabled": props.disabled, "readonly": props.readonly, "clearance": props.clearance, "onClear": handleClear }, { prepend: () => createVNode(XIcon, null, { default: () => [createVNode(Calendar, null, null)] }) })]), visible.value && createVNode("div", { "class": [ns.e("panel"), props.range ? ns.m("panel", "range") : ""] }, [createVNode("div", { "class": props.range ? ns.e("panel-left") : "" }, [props.model == "date" && createVNode("div", { "class": ns.e("header") }, [createVNode("span", { "class": ns.e("prev-year"), "onClick": prevYear }, [createVNode(XIcon, null, { default: () => [createVNode(ChevronsLeft, null, null)] })]), createVNode("span", { "class": ns.e("prev-month"), "onClick": prevMonth }, [createVNode(XIcon, null, { default: () => [createVNode(ChevronLeft, null, null)] })]), createVNode("span", { "class": ns.e("header-label") }, [currentYear.value, createTextVNode("\u5E74 "), currentMonth.value + 1, createTextVNode("\u6708")]), createVNode("span", { "class": ns.e("next-month"), "onClick": nextMonth }, [createVNode(XIcon, null, { default: () => [createVNode(ChevronRight, null, null)] })]), createVNode("span", { "class": ns.e("next-year"), "onClick": nextYear }, [createVNode(XIcon, null, { default: () => [createVNode(ChevronsRight, null, null)] })])]), props.model == "year" && createVNode("div", { "class": ns.e("header") }, [createVNode("span", { "class": ns.e("prev-year"), "onClick": prevYear }, [createVNode(XIcon, null, { default: () => [createVNode(ChevronsLeft, null, null)] })]), createVNode("span", { "class": ns.e("header-label") }, [currentYear.value, createTextVNode("\u5E74")]), createVNode("span", { "class": ns.e("next-year"), "onClick": nextYear }, [createVNode(XIcon, null, { default: () => [createVNode(ChevronsRight, null, null)] })])]), props.model == "month" && createVNode("div", { "class": ns.e("header") }, [createVNode("span", { "class": ns.e("prev-year"), "onClick": prevYear }, [createVNode(XIcon, null, { default: () => [createVNode(ChevronsLeft, null, null)] })]), createVNode("span", { "class": ns.e("header-label") }, [currentYear.value, createTextVNode("\u5E74")]), createVNode("span", { "class": ns.e("next-year"), "onClick": nextYear }, [createVNode(XIcon, null, { default: () => [createVNode(ChevronsRight, null, null)] })])]), createVNode("div", { "class": ns.e("content") }, [props.model == "date" && createVNode("div", { "class": ns.e("week-header") }, [weekDays.map((day) => createVNode("span", { "key": day }, [day]))]), props.model == "date" && renderDays( days.value, (_, index) => index, // 使用索引作为 key (cell) => cell.day, // 显示日期 (cell) => [ns.e("cell"), ns.is("selected", cell.isSelected), ns.is("today", cell.isToday), ns.is("not-current-month", !cell.isCurrentMonth), ns.is("in-range", cell.isInRange), ns.is("range-start", props.range && rangeState.value.startDate && isSameDay(cell.date, rangeState.value.startDate)), ns.is("range-end", props.range && rangeState.value.endDate && isSameDay(cell.date, rangeState.value.endDate))], (cell) => selectDate(cell) ), props.model == "year" && renderDays( years.value, (cell) => cell.year, // 使用年份作为 key (cell) => cell.year, // 显示年份 (cell) => [ns.e("cell"), ns.is("today", cell.isYear), ns.is("selected", cell.isSelected)], (cell) => selectDate(cell.year) ), props.model == "month" && renderDays( months.value, (cell) => cell.month, // 使用月份作为 key (cell) => cell.name, // 显示月份名称 (cell) => [ns.e("cell"), ns.is("selected", cell.isSelected), ns.is("today", cell.isCurrentMonth)], (cell) => selectDate(cell) )]), props.multiple && createVNode("div", { "class": ns.e("footer") }, [createVNode(resolveComponent("x-button"), { "type": "primary", "size": "small", "onClick": () => confirm() }, { default: () => [createTextVNode("\u786E\u5B9A")] }), createVNode(resolveComponent("x-button"), { "size": "small", "onClick": () => handleClear() }, { default: () => [createTextVNode("\u53D6\u6D88")] })])]), props.range && props.model === "date" && createVNode("div", { "class": ns.e("panel-right") }, [createVNode("div", { "class": ns.e("header") }, [createVNode("span", { "class": ns.e("prev-year"), "onClick": prevYear }, [createVNode(XIcon, null, { default: () => [createVNode(ChevronsLeft, null, null)] })]), createVNode("span", { "class": ns.e("prev-month"), "onClick": prevMonth }, [createVNode(XIcon, null, { default: () => [createVNode(ChevronLeft, null, null)] })]), createVNode("span", { "class": ns.e("header-label") }, [nextMonthDate.value.getFullYear(), createTextVNode("\u5E74"), " ", nextMonthDate.value.getMonth() + 1, createTextVNode("\u6708")]), createVNode("span", { "class": ns.e("next-month"), "onClick": nextMonth }, [createVNode(XIcon, null, { default: () => [createVNode(ChevronRight, null, null)] })]), createVNode("span", { "class": ns.e("next-year"), "onClick": nextYear }, [createVNode(XIcon, null, { default: () => [createVNode(ChevronsRight, null, null)] })])]), createVNode("div", { "class": ns.e("content") }, [createVNode("div", { "class": ns.e("week-header") }, [weekDays.map((day) => createVNode("span", { "key": day }, [day]))]), renderDays(nextMonthDays.value, (_, index) => index, (cell) => cell.day, (cell) => [ns.e("cell"), ns.is("selected", cell.isSelected), ns.is("today", cell.isToday), ns.is("not-current-month", !cell.isCurrentMonth), ns.is("in-range", cell.isInRange), ns.is("range-start", props.range && rangeState.value.startDate && isSameDay(cell.date, rangeState.value.startDate)), ns.is("range-end", props.range && rangeState.value.endDate && isSameDay(cell.date, rangeState.value.endDate))], (cell) => selectDate(cell))])])])]); } }); export { datePicker as default }; //# sourceMappingURL=index.mjs.map