From f58da404d459a3387f78d9bf6fe8933010f137bf Mon Sep 17 00:00:00 2001 From: coder77 <2293444075@qq.com> Date: Thu, 10 Apr 2025 11:02:22 +0800 Subject: [PATCH] feat: 日期选择器增加快捷选择 --- forms/datePicker/CDateRangeAction.vue | 307 +++++++++++++++++++++++++++++++++++++++++-- forms/datePicker/CDatePicker.vue | 25 +- forms/datePicker/cDateRangeAction.scss | 33 ++++ 3 files changed, 333 insertions(+), 32 deletions(-) diff --git a/forms/datePicker/CDatePicker.vue b/forms/datePicker/CDatePicker.vue index dd2c173..824a791 100644 --- a/forms/datePicker/CDatePicker.vue +++ b/forms/datePicker/CDatePicker.vue @@ -1,21 +1,16 @@ /** * CDatePicker - 选择日期范围操作 - * 日期选择组件,用于在表单中选择日期或日期范围 - * 支持三种选择模式:日期选择、日期时间选择和日期范围选择 - * 可限制日期选择范围,支持清除功能和只读模式 * @author Tevin */ <template> - <view - class="c-date-picker" - :class="readOnly?'read-only':''" - > + <view class="c-date-picker" :class="readOnly ? 'read-only' : ''"> <CDateRangeAction - v-if="mode==='dateRange'" + v-if="mode === 'dateRange'" :value="itemRes.formData[itemRes.name]" - :onChange="evt=>handleChange(evt)" + :onChange="evt => handleChange(evt)" :placeholder="placeholder" + :rangeTypes="rangeTypes" > <AtInput :name="itemRes.name" @@ -37,9 +32,9 @@ </AtInput> </CDateRangeAction> <CDateTimeAction - v-else-if="mode==='dateTime'" + v-else-if="mode === 'dateTime'" :value="itemRes.formData[itemRes.name]" - :onChange="evt=>handleChange(evt)" + :onChange="evt => handleChange(evt)" :placeholder="placeholder" > <AtInput @@ -61,14 +56,14 @@ ></view> </AtInput> </CDateTimeAction> - <view v-else-if="mode==='date'"> + <view v-else-if="mode === 'date'"> <picker mode="date" :start="limitStart || pickerStart" :end="limitEnd || pickerEnd" :fields="fields" :value="itemRes.formData[itemRes.name]" - @change="evt=>handleChange(evt.detail.value)" + @change="evt => handleChange(evt.detail.value)" > <AtInput :name="itemRes.name" @@ -122,6 +117,10 @@ limitStart: String, // 结束日期 limitEnd: String, + // 选择器类型,选日期、选周、选月 + picker: String, //date,week,month + // 预设类型 + rangeTypes: Array, // 日期选择粒度 year、month、day fields: { type: String, diff --git a/forms/datePicker/CDateRangeAction.vue b/forms/datePicker/CDateRangeAction.vue index 5c86a3d..f383de6 100644 --- a/forms/datePicker/CDateRangeAction.vue +++ b/forms/datePicker/CDateRangeAction.vue @@ -5,16 +5,10 @@ <template> <view class="c-date-range-action"> - <view - class="c-date-range-slot" - @tap="evt => handleOpen()" - > + <view class="c-date-range-slot" @tap="evt => handleOpen()"> <slot /> </view> - <view - class="c-data-range-float" - ref="floadLayer" - > + <view class="c-data-range-float" ref="floadLayer"> <CDrawer class="c-data-range-drawer" direction="top" @@ -22,7 +16,7 @@ :onClose="evt => handleClose()" > <view class="title"> - <view v-if="placeholder">{{placeholder}}</view> + <view v-if="placeholder">{{ placeholder }}</view> <view v-else>请选择日期</view> </view> <view class="date"> @@ -35,8 +29,8 @@ > <view class="item"> <view class="label">开始日期</view> - <view :class="startDate?'filled':'empty'"> - {{ startDate?startDate:'请选择开始日期' }} + <view :class="startDate ? 'filled' : 'empty'"> + {{ startDate ? startDate : '请选择开始日期' }} </view> <view class="at-icon at-icon-chevron-right" /> </view> @@ -50,12 +44,22 @@ > <view class="item"> <view class="label">结束日期</view> - <view :class="endDate?'filled':'empty'"> - {{ endDate?endDate:'请选择结束日期' }} + <view :class="endDate ? 'filled' : 'empty'"> + {{ endDate ? endDate : '请选择结束日期' }} </view> <view class="at-icon at-icon-chevron-right" /> </view> </picker> + </view> + <view class="quick-select"> + <view + class="quick-select-item" + v-for="(item, index) in quickSelect" + :key="index" + @tap="evt => handleQuickSelect(item)" + > + <view class="quick-select-item-label">{{ item.label }}</view> + </view> </view> <AtButton class="btn" @@ -63,7 +67,8 @@ full :circle="false" :onClick="evt => handleFinish()" - >确定</AtButton> + >确定</AtButton + > </CDrawer> </view> </view> @@ -71,6 +76,7 @@ <script> import Taro from '@tarojs/taro'; +import moment from 'moment'; import { $ } from '@tarojs/extend'; import { AtDrawer, AtButton } from 'taro-ui-vue'; import { CDrawer } from '@components/layout/drawer'; @@ -90,6 +96,13 @@ onChange: Function, // 占位提示 placeholder: String, + // 选择器类型,选日期、选周、选月 + picker: { + type: String, + default: 'date', // date, week, month + }, + // 预设类型 + rangeTypes: Array, }, data() { const year = new Date().getFullYear(); @@ -99,10 +112,274 @@ endDate: '', pickerStart: year - 30 + '-01-01', pickerEnd: year + 30 + '-12-31', + quickSelect: [], }; }, computed: {}, methods: { + _createRanges(ranges) { + const result = []; + + for (let typeName of ranges) { + switch (typeName) { + case 'today': + result.push({ + label: '今天', + value: [ + moment().format('YYYY-MM-DD'), + moment().format('YYYY-MM-DD'), + ], + }); + break; + case 'yesterday': + result.push({ + label: '昨天', + value: [ + moment().subtract(1, 'day').format('YYYY-MM-DD'), + moment().subtract(1, 'day').format('YYYY-MM-DD'), + ], + }); + break; + case 'curWeek': + if (this.limitDays && this.limitDays < 7) { + break; + } + result.push({ + label: '本周', + value: [ + moment().startOf('week').format('YYYY-MM-DD'), + moment().endOf('week').format('YYYY-MM-DD'), + ], + }); + break; + case 'lastWeek': + if (this.limitDays && this.limitDays < 7) { + break; + } + result.push({ + label: '上周', + value: [ + moment() + .subtract(1, 'week') + .startOf('week') + .format('YYYY-MM-DD'), + moment() + .subtract(1, 'week') + .endOf('week') + .format('YYYY-MM-DD'), + ], + }); + break; + case 'curMonth': + if (this.limitDays && this.limitDays < 30) { + break; + } + result.push({ + label: '本月', + value: [ + moment().startOf('month').format('YYYY-MM-DD'), + moment().endOf('month').format('YYYY-MM-DD'), + ], + }); + break; + case 'lastMonth': + if (this.limitDays && this.limitDays < 30) { + break; + } + result.push({ + label: '上月', + value: [ + moment() + .subtract(1, 'months') + .startOf('month') + .format('YYYY-MM-DD'), + moment() + .subtract(1, 'months') + .endOf('month') + .format('YYYY-MM-DD'), + ], + }); + break; + case 'curQuarter': + if (this.limitDays && this.limitDays < 90) { + break; + } + result.push({ + label: '本季', + value: [ + moment().startOf('quarter').format('YYYY-MM-DD'), + moment().endOf('quarter').format('YYYY-MM-DD'), + ], + }); + break; + case 'lastQuarter': + if (this.limitDays && this.limitDays < 90) { + break; + } + result.push({ + label: '上季', + value: [ + moment() + .subtract(1, 'quarter') + .startOf('quarter') + .format('YYYY-MM-DD'), + moment() + .subtract(1, 'quarter') + .endOf('quarter') + .format('YYYY-MM-DD'), + ], + }); + break; + case 'nearly3': + if (this.limitDays && this.limitDays < 3) { + break; + } + result.push({ + label: '最近3天', + value: [ + moment().subtract(2, 'days').format('YYYY-MM-DD'), + moment().format('YYYY-MM-DD'), + ], + }); + break; + case 'nearly7': + if (this.limitDays && this.limitDays < 7) { + break; + } + result.push({ + label: '最近7天', + value: [ + moment().subtract(6, 'days').format('YYYY-MM-DD'), + moment().format('YYYY-MM-DD'), + ], + }); + break; + case 'nearly10': + if (this.limitDays && this.limitDays < 10) { + break; + } + result.push({ + label: '最近10天', + value: [ + moment().subtract(9, 'days').format('YYYY-MM-DD'), + moment().format('YYYY-MM-DD'), + ], + }); + break; + case 'nearly15': + if (this.limitDays && this.limitDays < 15) { + break; + } + result.push({ + label: '最近15天', + value: [ + moment().subtract(14, 'days').format('YYYY-MM-DD'), + moment().format('YYYY-MM-DD'), + ], + }); + break; + case 'nearly30': + if (this.limitDays && this.limitDays < 30) { + break; + } + result.push({ + label: '最近30天', + value: [ + moment().subtract(29, 'days').format('YYYY-MM-DD'), + moment().format('YYYY-MM-DD'), + ], + }); + break; + case 'nearly60': + if (this.limitDays && this.limitDays < 60) { + break; + } + result.push({ + label: '最近60天', + value: [ + moment().subtract(59, 'days').format('YYYY-MM-DD'), + moment().format('YYYY-MM-DD'), + ], + }); + break; + case 'nearly90': + if (this.limitDays && this.limitDays < 90) { + break; + } + result.push({ + label: '最近90天', + value: [ + moment().subtract(89, 'days').format('YYYY-MM-DD'), + moment().format('YYYY-MM-DD'), + ], + }); + break; + case 'nearly4W': + if (this.limitDays && this.limitDays < 28) { + break; + } + result.push({ + label: '最近4周', + value: [ + moment() + .subtract(3, 'week') + .startOf('week') + .format('YYYY-MM-DD'), + moment().endOf('week').format('YYYY-MM-DD'), + ], + }); + break; + case 'nearly12W': + if (this.limitDays && this.limitDays < 84) { + break; + } + result.push({ + label: '最近12周', + value: [ + moment() + .subtract(11, 'week') + .startOf('week') + .format('YYYY-MM-DD'), + moment().endOf('week').format('YYYY-MM-DD'), + ], + }); + break; + case 'nearly3M': + if (this.limitDays && this.limitDays < 90) { + break; + } + result.push({ + label: '最近3个月', + value: [ + moment() + .subtract(2, 'months') + .startOf('month') + .format('YYYY-MM-DD'), + moment().endOf('month').format('YYYY-MM-DD'), + ], + }); + break; + default: + break; + } + } + + return result; + }, + _initQuickSelect() { + const defaultRangeTypes = { + date: ['today', 'curWeek', 'nearly3', 'nearly7'], + week: ['curWeek', 'lastWeek', 'nearly4W', 'nearly12W'], + month: ['curMonth', 'lastMonth', 'curQuarter', 'lastQuarter', 'nearly3M'], + }; + this.quickSelect = this.rangeTypes + ? this._createRanges(this.rangeTypes) + : this._createRanges(defaultRangeTypes[this.picker]); + }, + handleQuickSelect(item) { + this.startDate = item.value[0]; + this.endDate = item.value[1]; + }, handleOpen() { this.drawerShow = true; const curDates = (this.value || ',').split(','); @@ -158,6 +435,8 @@ if ($cFilter.length > 0) { $cFilter.eq(0).after(this.$refs.floadLayer); } + + this._initQuickSelect(); }, }; </script> \ No newline at end of file diff --git a/forms/datePicker/cDateRangeAction.scss b/forms/datePicker/cDateRangeAction.scss index 6326783..3c45ee1 100644 --- a/forms/datePicker/cDateRangeAction.scss +++ b/forms/datePicker/cDateRangeAction.scss @@ -3,7 +3,7 @@ * @author Tevin */ -@import "../../common/sassMixin"; +@import '../../common/sassMixin'; .c-data-range-float { @include position(fixed, 0 0, 9100); @@ -12,8 +12,8 @@ height: 100px; text-align: center; line-height: 100px; - border-top: 1PX solid #eee; - border-bottom: 1PX solid #d6e4ef; + border-top: 1px solid #eee; + border-bottom: 1px solid #d6e4ef; background-color: #f8f8f8; } .item { @@ -22,7 +22,7 @@ height: 96px; padding: 24px 0 24px 24px; white-space: nowrap; - border-bottom: 1PX solid #d6e4ef; + border-bottom: 1px solid #d6e4ef; box-sizing: border-box; background-color: #fff; .label { @@ -47,9 +47,32 @@ padding-bottom: 24px; background-color: #f8f8f8; } + .quick-select { + display: flex; + flex-wrap: wrap; + padding: 0 24px; + .quick-select-item { + height: 60px; + line-height: 60px; + padding: 0 18px; + margin-bottom: 24px; + text-align: center; + color: #1890ff; + background: #e6f7ff; + border: 1px solid #1890ff; + border-color: #91d5ff; + border-radius: 4px; + &:not(:last-child) { + margin-right: 24px; + } + &:active { + background-color: #e8e8e8; + } + } + } .btn { background-color: #36a0e7; border: none; } } -} \ No newline at end of file +} -- Gitblit v1.9.1