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 ++++++++++++++++++++++++++++++++++++++++++++++++--
 1 files changed, 293 insertions(+), 14 deletions(-)

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

--
Gitblit v1.9.1