尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
小程序时间切换器(uin-appX、uvue、uts、vue3)
template view classtime-switch-wrap !-- 顶部分段标签 activeKey 为u-tabs标准绑定字段 -- u-tabs :classtabsClass :listtabList :activeStylemergedActiveStyle :inactiveStylemergedInactiveStyle changeonChange / !-- 导航 -- view classdate-nav-1 u-icon v-ifactiveType ! custom classnav-left nameplay-left-fill size16 clickprevDate / view classdate-text clickopenDatePopup{{ displayDate }}/view u-icon v-ifactiveType ! custom classnav-right nameplay-right-fill size16 clicknextDate / /view !-- 选择日期 -- !-- 底部弹出层 -- view v-ifpopupShowactiveType day classpopup-calendar u-calendar :minDateminCalendarDate monthNum121 :disabledFunallDateCanSelect :showshow confirmonDaySelect / /view !-- 周选择弹窗区间选择 -- view v-ifpopupShowactiveType week classpopup-week u-calendar v-modelselectDay modesingle :showshow title选择任意一天自动匹配完整周一~周日 confirmonWeekSelect closeclosebtn / /view !-- 年月选择弹窗 -- view v-ifpopupShowactiveType month classpopup-month u-picker :showshow v-modelmonthPickerValue :columnsmonthColumns confirmonMonthSelect / /view !-- 年份选择弹窗 -- view v-ifpopupShowactiveType year classpopup-year u-picker :showshow v-modelyearPickerValue :columnsyearColumns confirmonYearSelect / /view !-- 自定义时间可自行扩展区间日历 -- view v-ifpopupShowactiveType custom classpopup-custom u-calendar closeclosebtn :minDateminCalendarDate monthNum121 v-modelweekRange allowSameDay :showshow moderange confirmonCustomSelect / /view /view /template script setup languts import { ref, computed, defineEmits, watch, withDefaults } from vue import { dayuts } from /uni_modules/lime-dayuts; export type TimeDimension day | week | month | year | custom const tabList [ { name: 日, value: day as TimeDimension }, { name: 周, value: week as TimeDimension }, { name: 月, value: month as TimeDimension }, { name: 年, value: year as TimeDimension }, { name: 自定义, value: custom as TimeDimension }, // { name: 自定义wwww, value: custom as TimeDimension }, ] const show ref(false) // 只定义一次Props删除下方重复interface Props interface Props { modelValue : TimeDimension currentDate : string | Date activeStyle ?: Recordstring, string inactiveStyle ?: Recordstring, string enableTabsClass ?: boolean } const props withDefaults(definePropsProps(), { // 【内置默认激活样式】 activeStyle: () ({ color: #1F2329, fontWeight: bold, background: #eff2f7, }), // 【内置默认未激活样式】 inactiveStyle: () ({ fontWeight: 400, color: #1F2329, }), enableTabsClass: false }) const emit defineEmits{ update:modelValue : [val: TimeDimension] update:currentDate : [date: string] change : [ type: TimeDimension, baseDate: string, range?: { start ?: string end ?: string yearMonth ?: string year ?: number } ] }() const tabsClass computed(() { return props.enableTabsClass ? u-tabs-f : }) const baseDate ref(dayuts(props.currentDate)) const popupShow ref(false) const activeType refTimeDimension(props.modelValue) const minCalendarDate computed(() { // 复制一份日期避免修改原baseDate const minDay baseDate.value.subtract(120, month) return minDay.format(YYYY-MM-DD) }) const mergedActiveStyle computed(() ({ ...props.activeStyle })) const mergedInactiveStyle computed(() ({ ...props.inactiveStyle })) const closebtn () { popupShow.value false } const onChange (e) { baseDate.value dayuts(props.currentDate) console.log(e, e) activeType.value e.value // 同步父组件选中tab emit(update:modelValue, e.value) const baseStr baseDate.value.format(YYYY-MM-DD) emit(update:currentDate, baseStr) if (activeType.value week) { const start getWeekStart(baseDate.value).format(YYYY-MM-DD) const end getWeekEnd(baseDate.value).format(YYYY-MM-DD) emit(change, activeType.value, baseStr, { start, end }) } else if (activeType.value month) { const yearMonth baseDate.value.format(YYYY-MM) emit(change, activeType.value, baseStr, { yearMonth }) } else if (activeType.value year) { const year baseDate.value.year() emit(change, activeType.value, baseStr, { year }) } else if (activeType.value custom) { // 自定义默认当天开始、当天结束 const start baseStr const end baseStr weekRange.value [baseStr, baseStr] emit(change, activeType.value, baseStr, { start, end }) } else { // day 无额外参数 emit(change, activeType.value, baseStr) } } const handleWeekDisabled (date : Date) : boolean { const target dayuts(date) const selectStart weekRange.value[0] ? dayuts(weekRange.value[0]) : null // 未选开始日期全部可点 if (!selectStart) return false const diffDays target.diff(selectStart, day) // 只能往后选最多6天凑满7天 if (diffDays 0 || diffDays 6) return true const startWeekDay selectStart.day() // 0周日 1周一 ...6周六 const endWeekDay target.day() // 规则起始必须周一结束必须周日且间隔正好6天共7天 const isFullWeek startWeekDay 1 endWeekDay 0 diffDays 6 return !isFullWeek } // 各选择器绑定值 const selectDay refstring(baseDate.value.format(YYYY-MM-DD)) // 周/自定义共用区间数组 const weekRange refstring[]([ getWeekStart(baseDate.value).format(YYYY-MM-DD), getWeekEnd(baseDate.value).format(YYYY-MM-DD) ]) const monthPickerValue refstring([ String(baseDate.value.year()), String(baseDate.value.month() 1) ]) const yearPickerValue refstring[]([String(baseDate.value.year())]) type DayutsInstance ReturnTypetypeof dayuts // 计算本周周一 function getWeekStart(d : DayutsInstance) : DayutsInstance { const dayNum d.day() const offset dayNum 0 ? -6 : 1 - dayNum return d.add(offset, day) } // 计算本周周日 function getWeekEnd(d : DayutsInstance) : DayutsInstance { return getWeekStart(d).add(6, day) } // 月份picker列 const monthColumns computed(() { const curYear baseDate.value.year() const years : string[] [] for (let i curYear - 10; i curYear 10; i) { years.push(String(i)) } const months [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12] return [years, months] }) // 年份picker列 const yearColumns computed(() { const curYear baseDate.value.year() const years : string[] [] for (let i curYear - 10; i curYear 10; i) { years.push(String(i)) } return [years] }) // 监听外部参数 watch(() props.modelValue, (newVal : TimeDimension) { activeType.value newVal }) watch(() props.currentDate, (val) { baseDate.value dayuts(val) resetPickerValue() syncEmit() }) // 重置选择器绑定值自定义默认当天-当天 const resetPickerValue () { const safeDate baseDate.value.isValid() ? baseDate.value : dayuts() const today safeDate.format(YYYY-MM-DD) selectDay.value today if (activeType.value custom) { weekRange.value [today, today] } else if (activeType.value week) { // 打开周日历默认当前整周 const mon getWeekStart(safeDate) const sun getWeekEnd(safeDate) weekRange.value [mon.format(YYYY-MM-DD), sun.format(YYYY-MM-DD)] } else { weekRange.value [ getWeekStart(safeDate).format(YYYY-MM-DD), getWeekEnd(safeDate).format(YYYY-MM-DD) ] } monthPickerValue.value [ String(safeDate.year()), String(safeDate.month() 1) ] yearPickerValue.value [String(safeDate.year())] } // 打开底部弹窗 const openDatePopup () { resetPickerValue() popupShow.value true show.value true } // 页面展示日期文本新增custom分支展示区间 const displayDate computed(() { const d baseDate.value switch (activeType.value) { case day: return d.format(YYYY/M/D) case week: const s getWeekStart(d) const e getWeekEnd(d) return ${s.format(YYYY/M/D)} - ${e.format(YYYY/M/D)} case month: return d.format(YYYY/M) case year: return String(d.year()) case custom: // 自定义展示当前基准日-当前基准日 const start weekRange.value[0] const end weekRange.value[weekRange.value.length - 1] console.log(weekRange.value, weekRange.value) return ${dayuts(start).format(YYYY/M/D)} - ${dayuts(end).format(YYYY/M/D)} default: return d.format(YYYY/M/D) } }) // 上一周期 const prevDate () { switch (activeType.value) { case day: baseDate.value baseDate.value.subtract(1, day) break case week: baseDate.value baseDate.value.subtract(7, day) break case month: baseDate.value baseDate.value.subtract(1, month) break case year: baseDate.value baseDate.value.subtract(1, year) break case custom: baseDate.value baseDate.value.subtract(1, day) break } syncEmit() } // 下一周期 const nextDate () { switch (activeType.value) { case day: baseDate.value baseDate.value.add(1, day) break case week: baseDate.value baseDate.value.add(7, day) break case month: baseDate.value baseDate.value.add(1, month) break case year: baseDate.value baseDate.value.add(1, year) break case custom: baseDate.value baseDate.value.add(1, day) break } syncEmit() } // 同步通知父组件补全custom分支 const syncEmit () { const baseStr baseDate.value.format(YYYY-MM-DD) emit(update:currentDate, baseStr) if (activeType.value week) { const start getWeekStart(baseDate.value).format(YYYY-MM-DD) const end getWeekEnd(baseDate.value).format(YYYY-MM-DD) emit(change, activeType.value, baseStr, { start, end }) } else if (activeType.value month) { const yearMonth baseDate.value.format(YYYY-MM) console.log(yearMonth, yearMonth) emit(change, activeType.value, baseStr, { yearMonth }) } else if (activeType.value year) { const year baseDate.value.year() emit(change, activeType.value, baseStr, { year }) } else if (activeType.value custom) { const start weekRange.value[0] const end weekRange.value[weekRange.value.length - 1] emit(change, activeType.value, baseStr, { start, end }) } else { emit(change, activeType.value, baseStr) } } // 单日选择确认 const onDaySelect (date : string[]) { baseDate.value dayuts(date[0]) popupShow.value false show.value false syncEmit() } // 周区间选择确认 const onWeekSelect (dateArr : string[]) { const pickDay dayuts(dateArr[0]) // 获取选中日对应的周一、周日 const mon getWeekStart(pickDay) const sun getWeekEnd(pickDay) // 更新区间为完整一周 weekRange.value [mon.format(YYYY-MM-DD), sun.format(YYYY-MM-DD)] // 基准日期设为本周周一 baseDate.value mon popupShow.value false show.value false syncEmit() } // 月份选择确认 const onMonthSelect (res : string[]) { console.log(res, res) const year Number(res.value[0]) const month Number(res.value[1]) - 1 // 必须减1 console.log(转换后year, year, month, month, 最终month, month) baseDate.value dayuts().year(year).month(month).date(1) console.log(baseDate.value, baseDate.value ) popupShow.value false show.value false syncEmit() } // 年份选择确认 const onYearSelect (res : string[]) { const year Number(res.value[0]) baseDate.value dayuts().year(year).month(0).date(1) popupShow.value false show.value false syncEmit() } // 自定义区间选择确认 const onCustomSelect (res : string[]) { console.log(自定义选中区间, res) // 更新基准日期为选中起始日 baseDate.value dayuts(res[0]) // 更新全局区间数组 weekRange.value res // 关闭弹窗 popupShow.value false show.value false // 统一走syncEmit派发事件内部自动处理custom逻辑 syncEmit() } /script style langscss scoped .time-switch-wrap { width: 100%; .date-nav-1 { margin-top: 33rpx; display: flex; flex-direction: row; justify-content: center; align-items: center; .nav-left { margin-right: 53rpx; } .nav-right { margin-left: 53rpx; } .date-text { font-weight: 600; font-size: 29rpx; color: #1F2329; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } } } // 平板适配min-width:768px单位px media screen and (min-width: 768px) { .time-switch-wrap { // u-tabs 标签整体微调大屏不拥挤 :deep(.u-tabs) { height: 40rpx !important; } :deep(.u-tabs__wrapper__scroll-view__item) { padding: 0 40rpx; } :deep(.u-tabs__wrapper__scroll-view__item-text) { font-size: 21rpx !important; } .date-nav-1 { margin-top: 24rpx; .nav-left { margin-right: 36rpx; } .nav-right { margin-left: 36rpx; } .date-text { font-size: 22rpx; } } } } /styleimport { dayuts } from /uni_modules/lime-dayuts const timeTyperef(day) 初始类型 const selectDate ref(dayuts().format(YYYY-MM-DD)) 初始时间也就是当前时间 TimeTabSwitch v-modeltimeType :current-dateselectDate changehandleTimeChange / const handleTimeChange (type : TimeDimension, baseDate : string, range ?: { start ?: string; end ?: string; yearMonth ?: string; year ?: string }) { if (type week range) { console.log(周开始, range.start) console.log(周结束, range.end) itemizeModel.startTime range.start itemizeModel.endTime range.end // 接口请求传 start / end } else if (type month range) { console.log(选择年月, range.yearMonth) itemizeModel.startTime range.yearMonth itemizeModel.endTime range.yearMonth } else if (type year range) { console.log(选择年份, range.year) itemizeModel.startTime range.year } else if (type custom range) { itemizeModel.startTime range.start itemizeModel.endTime range.end } else { console.log(当前维度, type, 基准日期, baseDate) itemizeModel.startTime baseDate itemizeModel.endTime baseDate } // 接口请求逻辑 itemizeModel.time type findEnergyConsumptionSubItem()//调用自己方法 }
RELATED

相关推荐

nVisual 如何解决跨楼层机房的线缆问题?

nVisual 如何解决跨楼层机房的线缆问题?

大家好,这里是 nVisual 频道。本频道将持续更新 nVisual 的使用技巧与常见问题的解决方法,欢迎大家关注。 在机房规划中,有时会遇到跨楼层机房的设计场景:上层机房与下层机房通过竖井连接。这类场景下的仿真设计往往让不少用户感到…

📅 2026/9/9 18:54:18
AI开发成本优化:从开源工具链到工程化实践

AI开发成本优化:从开源工具链到工程化实践

1. AI成本差异背后的技术现实最近在AI技术社区中,关于中美AI开发成本差异的讨论引起了广泛关注。作为长期从事AI工程实践的技术开发者,我们需要从技术角度理性分析这一现象。实际上,成本差异主要体现在基础设施、算力资源、开发工具链和工程化…

📅 2026/9/13 21:08:23
财务智能审核:大模型与小模型协同架构实践

财务智能审核:大模型与小模型协同架构实践

1. 财务合规审核的智能化转型背景 财务合规审核一直是企业运营中的关键环节,传统人工审核方式面临着效率低下、标准不统一、人为错误风险高等痛点。随着企业财务数据量呈指数级增长,审核工作量急剧增加,单纯依靠人工已经难以满足现代企业的需…

📅 2026/9/8 6:13:49
MORE NEWS

更多资讯

📰

使用 Lingo CLI 实现 Markdown 内容本地化:frontmatter 字段翻译与 push/pull 工作流实战

使用 Lingo CLI 实现 Markdown 内容本地化:frontmatter 字段翻译与 push/pull 工作流实战 【免费下载链接】replexica Open-source localization engineering tools. Connects to Lingo.dev localization engineering platform for consistent, quality translation…

📰

Basilisk航天仿真框架:可编程、可审计的高保真动力学内核

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

📰

k-skill seoul-weather-risk 行政洞解析设计:如何把「행정동 이름 + 자연어」确定性转换为 ASK Seoul 的 place_id

k-skill seoul-weather-risk 行政洞解析设计:如何把「행정동 이름 자연어」确定性转换为 ASK Seoul 的 place_id 【免费下载链接】k-skill 한국인을 위한 스킬 모음집 - 에이전트를 한국인으로 项目地址: https://gitcode.com/GitHub_Trending/ks/k-skill 本…

📰

Notepad-- 跨平台文本编辑器指南:如何在 Windows、Linux、macOS 上三步搞定中文编码与文件对比

Notepad-- 跨平台文本编辑器指南:如何在 Windows、Linux、macOS 上三步搞定中文编码与文件对比 【免费下载链接】notepad-- 一个支持windows/linux/mac的文本编辑器,目标是做中国人自己的编辑器,来自中国。 项目地址: https://gitcode.com/…

📰

AI-Infra-Guard mcp-scan 报告格式化提示词深度解析:format_report 模板的设计、调用链与落地实践

AI-Infra-Guard mcp-scan 报告格式化提示词深度解析:format_report 模板的设计、调用链与落地实践 【免费下载链接】AI-Infra-Guard A full-stack AI Red Teaming platform securing AI ecosystems via Agent Scan, Skills Scan, MCP scan, AI Infra scan and LLM j…

📰

通达信主力建仓指标源码解析与实战优化

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬