当前位置: 首页 > news >正文

周范围选择器

周范围选择器

原因:

在翻找了不少大佬造的轮子后始终没有找到一个符合我需求的,于是决定自己造一个

方案:

使用date-fns来实现获取周总数,第几周等数据,其他逻辑自行处理(其实可以依托element-ui部分组件,但是当时脑子没转过来)
话不多上代码

<template><div class="week_picker flex"><div class="week_box"><div class="flex flex_column_center"><div ref="startWeekSelect" :class="['week_block',{'week_open': weekIsOpen.start}]"><div class="week_top flex flex-content-center" @click="weekIsOpen.start = !weekIsOpen.start"><div class="week_txt">{{ `${yearData.start}年 第${weekData.startWeek}周` }}</div><div class="icon el-icon-arrow-down"></div></div><div class="week_select_box"><div class="week_select"><div class="year_box flex flex_column_center flex_row_justify"><i class="year_btn el-icon-d-arrow-left" @click="yearIconClick('start','down')"></i><div class="year_txt">{{ yearData.start }}</div><i class="year_btn el-icon-d-arrow-right" @click="yearIconClick('start','up')"></i></div><div class="week_option_box"><div :class="['week_option',{'active':item.value === weekData.startWeek}]"v-for="item in startWeekList":value="item.value"@click="weekOptionClick(item.value)">{{ item.label }}</div></div><div class="arrow_icon"></div></div></div></div><p style="margin: 0 15px">至</p><div ref="endWeekSelect" :class="['week_block',{'week_open': weekIsOpen.end}]"><div class="week_top flex flex-content-center" @click="weekIsOpen.end = !weekIsOpen.end"><div class="week_txt">{{ `${yearData.end}年 第${weekData.endWeek}周` }}</div><div class="icon el-icon-arrow-down"></div></div><div class="week_select_box"><div class="week_select"><div class="year_box flex flex_column_center flex_row_justify"><i :class="['year_btn el-icon-d-arrow-left',{'disabled':this.yearData.end <= this.yearData.start}]"@click="yearIconClick('end','down')"></i><p class="year_txt">{{ yearData.end }}</p><i class="year_btn el-icon-d-arrow-right" @click="yearIconClick('end','up')"></i></div><div class="week_option_box"><div:class="['week_option',{'active':item.value === weekData.endWeek},{'disabled':endWeekDisabled(item.value)}]"v-for="item in endWeekList":value="item.value"@click="weekOptionClick(item.value,'end')">{{ item.label }}</div></div><div class="arrow_icon"></div></div></div></div></div><div class="txt">{{ dateScope }}</div></div></div>
</template><script>import { getWeekStartAndEnd } from '@/utils/ruoyi'
import { getISOWeek, getISOWeeksInYear, getYear } from 'date-fns'export default {name: 'WeekPicker',data() {return {yearData: {// 年份start: '',end: ''},weekTal: { // 一年有多少周start: 0,end: 0},weekData: { // 周数startWeek: '',endWeek: ''},dateData: {start: '',end: ''},weekIsOpen: {start: false,end: false}}},computed: {// 开始周列表startWeekList() {console.log('初始化')let weekList = []const date = new Date()let yearType = this.yearData.start === date.getFullYear()for (let i = 1; i <= this.weekTal.start; i++) {weekList.push({ value: i, label: i === getISOWeek(new Date()) && yearType ? `第${i}周(本周)` : `第${i}周` })}return weekList},// 结束周列表endWeekList() {let weekList = []const date = new Date()let yearType = this.yearData.end === date.getFullYear()for (let i = 1; i <= this.weekTal.end; i++) {weekList.push({ value: i, label: i === getISOWeek(new Date()) && yearType ? `第${i}周(本周)` : `第${i}周` })}return weekList},// 日期范围dateScope() {let monday = ''let sunday = ''if (this.weekData.startWeek) {monday = getWeekStartAndEnd(this.yearData.start, this.weekData.startWeek, false).mondaythis.dateData.start = getWeekStartAndEnd(this.yearData.start, this.weekData.startWeek, true).monday}if (this.weekData.endWeek) {sunday = getWeekStartAndEnd(this.yearData.end, this.weekData.endWeek, false).sundaythis.dateData.end = getWeekStartAndEnd(this.yearData.end, this.weekData.endWeek, true).sunday}if (this.weekData.startWeek && this.weekData.endWeek) {return `(${monday} 至 ${sunday})`}return ''}},created() {this.initDate()// 绑定全局点击事件document.addEventListener('click', this.weekInsideClick)},methods: {// 初始化时间initDate() {this.yearData.end = this.yearData.start = getYear(new Date(new Date().getFullYear(), 4, 1))this.weekTal.end = this.weekTal.start = getISOWeeksInYear(new Date(new Date().getFullYear(), 4, 1))this.weekData.startWeek = getISOWeek(new Date())this.weekData.endWeek = getISOWeek(new Date())},// 结束周禁用选项endWeekDisabled(data) {if (this.yearData.start === this.yearData.end) {return this.weekData.startWeek > data} else {return false}},// 周改变weekOptionClick(data, type = 'start') {let isClose = falseif (type === 'start') {isClose = truethis.weekData.startWeek = dataif (this.yearData.start === this.yearData.end && this.weekData.startWeek > this.weekData.endWeek) {this.weekData.endWeek = data}} else {if (this.yearData.start === this.yearData.end) {if (this.weekData.startWeek <= data) {this.weekData.endWeek = dataisClose = true}} else if (this.yearData.start < this.yearData.end) {this.weekData.endWeek = dataisClose = true}}if (isClose) {this.weekIsOpen.start = falsethis.weekIsOpen.end = falsethis.$emit('change', this.dateData)}},// 点击外部触发weekInsideClick(event) {const isClickedInsideStart = this.$refs.startWeekSelect.contains(event.target)const isClickedInsideEnd = this.$refs.endWeekSelect.contains(event.target)if (!isClickedInsideStart) {this.weekIsOpen.start = false}if (!isClickedInsideEnd) {this.weekIsOpen.end = false}},/** 年份改变** @param type // start | end 点击的是开始周还是结束周* @param direction // up | down 点击的是增加还是减少* @returns {boolean}*/yearIconClick(type, direction) {// 结束年份小于等于开始年份并且点击减少结束年份,禁止点击if (type === 'end' && direction === 'down' && this.yearData.end <= this.yearData.start) {return false}if (direction === 'up') {this.yearData[type]++} else {if (this.yearData[type] >= 1950) {this.yearData[type]--}}if (type === 'start') {this.weekData.startWeek = 1if (this.yearData.start > this.yearData.end) {this.weekData.endWeek = 1this.yearData.end = this.yearData.start}}}},beforeDestroy() {// 移除全局点击事件document.removeEventListener('click', this.weekInsideClick)}
}
</script><style lang="scss">
.week_box {.txt {margin-top: 10px;}
}.week_block {line-height: 34px;border-radius: 4px;border: 1px solid #DCDFE6;position: relative;white-space: nowrap;width: 150px;font-size: 14px;color: #606266;padding: 0 10px;&.week_open {.week_select_box {opacity: 1;pointer-events: auto;max-height: 400px;}}.week_txt {padding-right: 10px;flex: 1;cursor: pointer;}.icon {line-height: 34px;font-size: 14px;color: #C0C4CC;cursor: pointer;}.week_select_box {z-index: 50;position: absolute;top: 100%;left: -1px;right: -6px;white-space: nowrap;line-height: 34px;font-size: 14px;padding: 10px 5px 10px 0;overflow: hidden;max-height: 0;opacity: 0;pointer-events: none;transition: all .3s;.week_select {position: relative;border: solid 1px #dfe4ed;border-radius: 4px;background-color: #fff;box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);}.year_box {padding: 0 5px;font-size: 18px;.year_btn {cursor: pointer;padding: 0 5px;line-height: 46px;&.disabled {cursor: no-drop;color: #c7cace !important;}&:hover {color: #1890ff;}}.year_txt {margin: 0 10px;}}.week_option_box {padding: 5px 0;height: 268px;overflow-y: auto;border-top: 1px solid #dfe4ed;}.week_option {padding: 0 15px;cursor: pointer;color: #606266;&.active {color: #1890ff;font-weight: 600;}&.disabled {cursor: no-drop;color: #c7cace !important;background-color: #fff !important;}&:hover {background-color: #f5f7fa;}}.arrow_icon {position: absolute;top: -6px;border-width: 6px;border-top-width: 0;display: block;width: 0;height: 0;left: 35px;border-color: transparent;border-style: solid;border-bottom-color: #e6ebf5;&:after {content: ' ';position: absolute;top: 1px;border-width: 5px;border-top-width: 0;display: block;width: 0;height: 0;left: 0;margin-left: -5px;border-color: transparent;border-style: solid;border-bottom-color: #FFFFFF;}}}}
</style>

效果如图
image

http://www.jsqmd.com/news/644014/

相关文章:

  • 手把手教你:在Ubuntu 22.04上用Docker离线部署Dify AI工作流平台(附全套镜像包)
  • QQ音乐解码神器qmcdump:三步解锁加密音乐,让音乐真正属于你
  • 更换轮胎四轮定位
  • NVIDIA Profile Inspector终极指南:解锁显卡隐藏性能的简单方法
  • python的flash_attn模块windows版本,基于python3.12,cuda13.2版本编译。
  • HPA与VPA自动伸缩实战(应对流量洪峰的弹性方案)
  • 技术流程图的步骤顺序可视化
  • AirPodsDesktop:Windows用户必备的苹果耳机完整体验指南
  • 2026年木制茶叶盒厂家品牌推荐/竹木制品,实木木盒,木制相框 - 品牌策略师
  • 实景三维模型修复实战:DP、模方、SVS核心功能与场景化应用指南
  • 模块化基础:包、模块、导入导出设计思想
  • 西门子1200PLC(入门)1
  • 【异常】Cursor编辑器 “Taking longer than expected...“ 报错全链路排查与解决方案
  • 【四足机器人运动学实战】三维腿部建模:从几何视图到完整解算
  • 青藏高原冻土退化趋势分析(1961-2020):基于TTOP模型与Stefan方程的综合研究
  • 如何安全解锁WeMod Pro功能?WandEnhancer开源方案深度解析
  • SillyTavern技术架构解析:构建高性能LLM前端与角色系统的实战指南
  • 支付宝消费红包回收让沉睡的零钱重新流动 - 京顺回收
  • 安卓相机直连SDK架构设计:如何为图片直播构建可靠传输通道
  • 告别回调地狱:在 C++ Web 框架中全面拥抱协程
  • 阿里云代理商:解锁 OpenClaw 高效工作流 8 大核心技能实战手册
  • HoRain云--Kotlin命令行编译终极指南:从入门到精通
  • 剖析比较好的全脑教育企业,教学质量与市场口碑深度解读 - mypinpai
  • 非视距·自愈·广覆盖|黎阳之光1.45.8GHz宽带自愈网无线基站,重构工业级无线通信
  • 【异常】Cursor报错We‘re having trouble connecting to the model provider. This might be temporary
  • AnyChart 的tagCloud组件
  • 别再让电源振荡了!手把手教你给UC3842加斜坡补偿(附计算步骤)
  • 3步解决乐谱数字化难题:Audiveris OMR引擎从图像到可编辑乐谱的完整实践指南
  • 【从0到1构建一个ClaudeAgent】规划与协调-任务系统
  • 2026年好用的高精度线材轧机推荐,企业选择探讨 - myqiye