浏览代码

feat(calendar): 添加自定义周起始日配置 (#1827)

大胡子 3 年之前
父节点
当前提交
234d343f05

+ 23 - 0
src/packages/__VUE/calendar/__tests__/calendar.spec.ts

@@ -62,6 +62,29 @@ test('show-today prop', async () => {
   expect(wrapper.find('.calendar-curr-tip-curr').exists()).toBeFalsy();
   expect(wrapper.find('.calendar-curr-tip-curr').exists()).toBeFalsy();
 });
 });
 
 
+test('first-day-of-week prop', async () => {
+  const wrapper = mount(Calendar, {
+    props: {
+      poppable: false,
+      firstDayOfWeek: 2,
+      startDate: '2022-01-01',
+      endDate: '2022-01-31'
+    }
+  });
+  await nextTick();
+  const weekdays = ['日', '一', '二', '三', '四', '五', '六'];
+  // 头部周第1个元素
+  const weekday = wrapper.findAll('.calendar-week-item')[0].text();
+  expect(weekday).toEqual(weekdays[2]);
+  // 日期面板第7个元素, 判断最后一天的日期是否匹配
+  const calendarMonth = wrapper.find('.calendar-month');
+  const monthTitle = calendarMonth.find('.calendar-month-title').text();
+  const dayText = calendarMonth.findAll('.calendar-day')[6].text();
+  const date = new Date(monthTitle.replace(/[年月]/g, '/') + dayText);
+  const index = date.getDay();
+  expect(index).toEqual(1);
+});
+
 test('should render slot correctly', async () => {
 test('should render slot correctly', async () => {
   const wrapper = mount(Calendar, {
   const wrapper = mount(Calendar, {
     props: {
     props: {

+ 31 - 3
src/packages/__VUE/calendar/demo.vue

@@ -170,6 +170,24 @@
       </nut-calendar>
       </nut-calendar>
     </div>
     </div>
     <h2>{{ translate('title3') }}</h2>
     <h2>{{ translate('title3') }}</h2>
+    <div>
+      <nut-cell
+        :show-icon="true"
+        :title="translate('single')"
+        :desc="date8 ? `${date8}` : translate('please')"
+        @click="openSwitch('isVisible8')"
+      >
+      </nut-cell>
+      <nut-calendar
+        v-model:visible="isVisible8"
+        :default-value="date8"
+        @close="closeSwitch('isVisible8')"
+        @choose="setChooseValue8"
+        :first-day-of-week="2"
+      >
+      </nut-calendar>
+    </div>
+    <h2>{{ translate('title4') }}</h2>
     <div class="test-calendar-wrapper">
     <div class="test-calendar-wrapper">
       <nut-calendar :poppable="false" :default-value="date2" :is-auto-back-fill="true" @choose="setChooseValue2">
       <nut-calendar :poppable="false" :default-value="date2" :is-auto-back-fill="true" @choose="setChooseValue2">
       </nut-calendar>
       </nut-calendar>
@@ -190,7 +208,8 @@ const initTranslate = () =>
       title: '基础用法',
       title: '基础用法',
       title1: '快捷选择',
       title1: '快捷选择',
       title2: '自定义日历',
       title2: '自定义日历',
-      title3: '平铺展示',
+      title3: '自定义周起始日',
+      title4: '平铺展示',
 
 
       please: '请选择',
       please: '请选择',
       single: '选择单个日期',
       single: '选择单个日期',
@@ -213,7 +232,8 @@ const initTranslate = () =>
       title: 'Basic Usage',
       title: 'Basic Usage',
       title1: 'Quick Select',
       title1: 'Quick Select',
       title2: 'Custom Calendar',
       title2: 'Custom Calendar',
-      title3: 'Tiled Display',
+      title3: 'Custom First Day Of Week',
+      title4: 'Tiled Display',
 
 
       please: 'Please Select Date',
       please: 'Please Select Date',
       single: 'Select Single Date',
       single: 'Select Single Date',
@@ -244,6 +264,7 @@ interface TestCalendarState {
   isVisible5: boolean;
   isVisible5: boolean;
   isVisible6: boolean;
   isVisible6: boolean;
   isVisible7: boolean;
   isVisible7: boolean;
+  isVisible8: boolean;
   date1: string[];
   date1: string[];
   date2: string;
   date2: string;
   date3: string;
   date3: string;
@@ -251,6 +272,7 @@ interface TestCalendarState {
   date5: string[];
   date5: string[];
   date6: string[];
   date6: string[];
   date7: string[];
   date7: string[];
+  date8: string;
 }
 }
 export default createDemo({
 export default createDemo({
   props: {},
   props: {},
@@ -268,13 +290,15 @@ export default createDemo({
       date5: ['2021-12-23', '2021-12-26'],
       date5: ['2021-12-23', '2021-12-26'],
       date6: [],
       date6: [],
       date7: [],
       date7: [],
+      date8: '',
       isVisible1: false,
       isVisible1: false,
       isVisible2: false,
       isVisible2: false,
       isVisible3: false,
       isVisible3: false,
       isVisible4: false,
       isVisible4: false,
       isVisible5: false,
       isVisible5: false,
       isVisible6: false,
       isVisible6: false,
-      isVisible7: false
+      isVisible7: false,
+      isVisible8: false
     });
     });
     const openSwitch = (param: string) => {
     const openSwitch = (param: string) => {
       state[`${param}`] = true;
       state[`${param}`] = true;
@@ -321,6 +345,9 @@ export default createDemo({
       });
       });
       state.date7 = [...dateArr];
       state.date7 = [...dateArr];
     };
     };
+    const setChooseValue8 = (param: string) => {
+      state.date8 = param[3];
+    };
     const clickBtn = (param: string) => {
     const clickBtn = (param: string) => {
       let date = [Utils.date2Str(new Date()), Utils.getDay(6)];
       let date = [Utils.date2Str(new Date()), Utils.getDay(6)];
       state.date5 = date;
       state.date5 = date;
@@ -351,6 +378,7 @@ export default createDemo({
       setChooseValue4,
       setChooseValue4,
       setChooseValue5,
       setChooseValue5,
       setChooseValue6,
       setChooseValue6,
+      setChooseValue8,
       clickBtn,
       clickBtn,
       clickBtn1,
       clickBtn1,
       goDate,
       goDate,

+ 55 - 0
src/packages/__VUE/calendar/doc.en-US.md

@@ -496,6 +496,60 @@ export default {
 
 
 ```
 ```
 :::
 :::
+
+### Custom First Day Of Week
+:::demo
+```html
+<template>
+  <nut-cell
+    :showIcon="true"
+    title="Custom First Day Of Week"
+    :desc="date ? `${date} ${dateWeek}` : 'Please Select Date'"
+    @click="openSwitch('isVisible')"
+    :first-day-of-week="2"
+  >
+  </nut-cell>
+  <nut-calendar
+    v-model:visible="isVisible"
+    :default-value="date"
+    @close="closeSwitch('isVisible')"
+    @choose="setChooseValue"
+    :start-date="`2019-10-11`"
+    :end-date="`2022-11-11`"
+  >
+  </nut-calendar>
+</template>
+<script lang="ts">
+import { reactive, toRefs } from 'vue';
+export default {
+  setup() {
+    const state = reactive({
+      isVisible: false,
+      date: '',
+      dateWeek: ''
+    });
+    const openSwitch = param => {
+      state[`${param}`] = true;
+    };
+    const closeSwitch = param => {
+      state[`${param}`] = false;
+    };
+    const setChooseValue = param => {
+      state.date = param[3];
+      state.dateWeek = param[4];
+    };
+    return {
+      ...toRefs(state),
+      openSwitch,
+      closeSwitch,
+      setChooseValue
+    };
+  }
+};
+</script>
+```
+
+:::
 ### Tiled Display
 ### Tiled Display
 :::demo
 :::demo
 ```html
 ```html
@@ -560,6 +614,7 @@ export default {
 | show-title          | Whether to show the calendar title               | Boolean          | true |
 | show-title          | Whether to show the calendar title               | Boolean          | true |
 | show-sub-title          | Whether to display the date title              | Boolean          | true |
 | show-sub-title          | Whether to display the date title              | Boolean          | true |
 | to-date-animation          | Whether to use scroll animation              | Boolean          | true |
 | to-date-animation          | Whether to use scroll animation              | Boolean          | true |
+| first-day-of-week          | Set the start day of week              | 0-6          | 0 |
 
 
 ### Events
 ### Events
 
 

+ 56 - 0
src/packages/__VUE/calendar/doc.md

@@ -487,6 +487,61 @@ export default {
 
 
 ```
 ```
 :::
 :::
+
+### 自定义周起始日
+:::demo
+```html
+<template>
+  <nut-cell
+    :showIcon="true"
+    title="自定义周起始日"
+    :desc="date ? `${date} ${dateWeek}` : '请选择'"
+    @click="openSwitch('isVisible')"
+    :first-day-of-week="2"
+  >
+  </nut-cell>
+  <nut-calendar
+    v-model:visible="isVisible"
+    :default-value="date"
+    @close="closeSwitch('isVisible')"
+    @choose="setChooseValue"
+    :start-date="`2019-10-11`"
+    :end-date="`2022-11-11`"
+  >
+  </nut-calendar>
+</template>
+<script lang="ts">
+import { reactive, toRefs } from 'vue';
+export default {
+  setup() {
+    const state = reactive({
+      isVisible: false,
+      date: '',
+      dateWeek: ''
+    });
+    const openSwitch = param => {
+      state[`${param}`] = true;
+    };
+    const closeSwitch = param => {
+      state[`${param}`] = false;
+    };
+    const setChooseValue = param => {
+      state.date = param[3];
+      state.dateWeek = param[4];
+    };
+    return {
+      ...toRefs(state),
+      openSwitch,
+      closeSwitch,
+      setChooseValue
+    };
+  }
+};
+</script>
+```
+
+:::
+
 ### 平铺展示
 ### 平铺展示
 :::demo
 :::demo
 ```html
 ```html
@@ -552,6 +607,7 @@ export default {
 | show-title          | 是否在展示日历标题               | Boolean          | true |
 | show-title          | 是否在展示日历标题               | Boolean          | true |
 | show-sub-title          | 是否展示日期标题              | Boolean          | true |
 | show-sub-title          | 是否展示日期标题              | Boolean          | true |
 | to-date-animation          | 是否启动滚动动画              | Boolean          | true |
 | to-date-animation          | 是否启动滚动动画              | Boolean          | true |
+| first-day-of-week          | 设置周起始日              | 0-6          | 0 |
 
 
 ### Events
 ### Events
 
 

+ 7 - 0
src/packages/__VUE/calendar/index.taro.vue

@@ -30,6 +30,7 @@
       :show-title="showTitle"
       :show-title="showTitle"
       :show-sub-title="showSubTitle"
       :show-sub-title="showSubTitle"
       :to-date-animation="toDateAnimation"
       :to-date-animation="toDateAnimation"
+      :first-day-of-week="firstDayOfWeek"
     >
     >
       <template v-slot:btn v-if="showTopBtn">
       <template v-slot:btn v-if="showTopBtn">
         <slot name="btn"> </slot>
         <slot name="btn"> </slot>
@@ -64,6 +65,7 @@
     :show-sub-title="showSubTitle"
     :show-sub-title="showSubTitle"
     :to-date-animation="toDateAnimation"
     :to-date-animation="toDateAnimation"
     :show-today="showToday"
     :show-today="showToday"
+    :first-day-of-week="firstDayOfWeek"
   >
   >
     <template v-slot:btn v-if="showTopBtn">
     <template v-slot:btn v-if="showTopBtn">
       <slot name="btn"> </slot>
       <slot name="btn"> </slot>
@@ -151,6 +153,11 @@ export default create({
     endDate: {
     endDate: {
       type: String,
       type: String,
       default: Utils.getDay(365)
       default: Utils.getDay(365)
+    },
+    firstDayOfWeek: {
+      type: Number,
+      default: 0,
+      validator: (val: number) => val >= 0 && val <= 6
     }
     }
   },
   },
   emits: ['choose', 'close', 'update:visible', 'select'],
   emits: ['choose', 'close', 'update:visible', 'select'],

+ 7 - 0
src/packages/__VUE/calendar/index.vue

@@ -32,6 +32,7 @@
       :show-title="showTitle"
       :show-title="showTitle"
       :show-sub-title="showSubTitle"
       :show-sub-title="showSubTitle"
       :to-date-animation="toDateAnimation"
       :to-date-animation="toDateAnimation"
+      :first-day-of-week="firstDayOfWeek"
     >
     >
       <template v-slot:btn v-if="showTopBtn">
       <template v-slot:btn v-if="showTopBtn">
         <slot name="btn"> </slot>
         <slot name="btn"> </slot>
@@ -67,6 +68,7 @@
     :show-title="showTitle"
     :show-title="showTitle"
     :show-sub-title="showSubTitle"
     :show-sub-title="showSubTitle"
     :to-date-animation="toDateAnimation"
     :to-date-animation="toDateAnimation"
+    :first-day-of-week="firstDayOfWeek"
     ref="calendarRef"
     ref="calendarRef"
   >
   >
     <template v-slot:btn v-if="showTopBtn">
     <template v-slot:btn v-if="showTopBtn">
@@ -155,6 +157,11 @@ export default create({
     endDate: {
     endDate: {
       type: String,
       type: String,
       default: Utils.getDay(365)
       default: Utils.getDay(365)
+    },
+    firstDayOfWeek: {
+      type: Number,
+      default: 0,
+      validator: (val: number) => val >= 0 && val <= 6
     }
     }
   },
   },
   emits: ['choose', 'close', 'update:visible', 'select'],
   emits: ['choose', 'close', 'update:visible', 'select'],

+ 9 - 1
src/packages/__VUE/calendaritem/index.h5.vue

@@ -187,12 +187,18 @@ export default create({
     endDate: {
     endDate: {
       type: String,
       type: String,
       default: Utils.getDay(365)
       default: Utils.getDay(365)
+    },
+    firstDayOfWeek: {
+      type: Number,
+      default: 0
     }
     }
   },
   },
   emits: ['choose', 'update', 'close', 'select'],
   emits: ['choose', 'update', 'close', 'select'],
 
 
   setup(props, { emit, slots }) {
   setup(props, { emit, slots }) {
-    const weeks = ref(translate('weekdays'));
+    // 新增:自定义周起始日
+    const weekdays = translate('weekdays');
+    const weeks = ref([...weekdays.slice(props.firstDayOfWeek, 7), ...weekdays.slice(0, props.firstDayOfWeek)]);
     // element refs
     // element refs
     const scalePx = ref(2);
     const scalePx = ref(2);
     const months = ref<null | HTMLElement>(null);
     const months = ref<null | HTMLElement>(null);
@@ -398,6 +404,8 @@ export default create({
 
 
     // 获取日期状态
     // 获取日期状态
     const getDaysStatus = (days: number, type: string, dateInfo: Dateprop) => {
     const getDaysStatus = (days: number, type: string, dateInfo: Dateprop) => {
+      // 新增:自定义周起始日
+      days = days - props.firstDayOfWeek;
       // 修复:当某个月的1号是周日时,月份下方会空出来一行
       // 修复:当某个月的1号是周日时,月份下方会空出来一行
       let { year, month } = dateInfo;
       let { year, month } = dateInfo;
       if (type == 'prev' && days >= 7) {
       if (type == 'prev' && days >= 7) {

+ 9 - 1
src/packages/__VUE/calendaritem/index.taro.vue

@@ -178,12 +178,18 @@ export default create({
     endDate: {
     endDate: {
       type: String,
       type: String,
       default: Utils.getDay(365)
       default: Utils.getDay(365)
+    },
+    firstDayOfWeek: {
+      type: Number,
+      default: 0
     }
     }
   },
   },
   emits: ['choose', 'update', 'close', 'select'],
   emits: ['choose', 'update', 'close', 'select'],
 
 
   setup(props, { emit, slots }) {
   setup(props, { emit, slots }) {
-    const weeks = ref(translate('weekdays'));
+    // 新增:自定义周起始日
+    const weekdays = translate('weekdays');
+    const weeks = ref([...weekdays.slice(props.firstDayOfWeek, 7), ...weekdays.slice(0, props.firstDayOfWeek)]);
     // element refs
     // element refs
     const scalePx = ref(2);
     const scalePx = ref(2);
     const viewHeight = ref(0);
     const viewHeight = ref(0);
@@ -404,6 +410,8 @@ export default create({
     };
     };
     // 获取上一个月的最后一周天数,填充当月空白
     // 获取上一个月的最后一周天数,填充当月空白
     const getPreDaysStatus = (days: number, type: string, dateInfo: any, preCurrMonthDays: number) => {
     const getPreDaysStatus = (days: number, type: string, dateInfo: any, preCurrMonthDays: number) => {
+      // 新增:自定义周起始日
+      days = days - props.firstDayOfWeek;
       // 修复:当某个月的1号是周日时,月份下方会空出来一行
       // 修复:当某个月的1号是周日时,月份下方会空出来一行
       let { year, month } = dateInfo;
       let { year, month } = dateInfo;
       if (type == 'prev' && days >= 7) {
       if (type == 'prev' && days >= 7) {

+ 9 - 1
src/packages/__VUE/calendaritem/index.vue

@@ -185,12 +185,18 @@ export default create({
     endDate: {
     endDate: {
       type: String,
       type: String,
       default: Utils.getDay(365)
       default: Utils.getDay(365)
+    },
+    firstDayOfWeek: {
+      type: Number,
+      default: 0
     }
     }
   },
   },
   emits: ['choose', 'update', 'close', 'select'],
   emits: ['choose', 'update', 'close', 'select'],
 
 
   setup(props, { emit, slots }) {
   setup(props, { emit, slots }) {
-    const weeks = ref(translate('weekdays'));
+    // 新增:自定义周起始日
+    const weekdays = translate('weekdays');
+    const weeks = ref([...weekdays.slice(props.firstDayOfWeek, 7), ...weekdays.slice(0, props.firstDayOfWeek)]);
     // element refs
     // element refs
     const months = ref<null | HTMLElement>(null);
     const months = ref<null | HTMLElement>(null);
     const monthsPanel = ref<null | HTMLElement>(null);
     const monthsPanel = ref<null | HTMLElement>(null);
@@ -411,6 +417,8 @@ export default create({
     };
     };
     // 获取上一个月的最后一周天数,填充当月空白
     // 获取上一个月的最后一周天数,填充当月空白
     const getPreDaysStatus = (days: number, type: string, dateInfo: Dateprop, preCurrMonthDays: number) => {
     const getPreDaysStatus = (days: number, type: string, dateInfo: Dateprop, preCurrMonthDays: number) => {
+      // 新增:自定义周起始日
+      days = days - props.firstDayOfWeek;
       // 修复:当某个月的1号是周日时,月份下方会空出来一行
       // 修复:当某个月的1号是周日时,月份下方会空出来一行
       let { year, month } = dateInfo;
       let { year, month } = dateInfo;
       if (type == 'prev' && days >= 7) {
       if (type == 'prev' && days >= 7) {