9afce6f6创建于 2025年5月7日历史提交
/*
 * Copyright (c) 2024 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import Constants from '../constant/Constants';
import { CalendarController, CalendarViewType } from '../components/CustomCalendar';
import { CalendarData, CalendarStyle, CalendarSwitch } from '../model/CalendarModel';
import { TimeUtils } from '../utils/TimeUtils';
import { WeekViewItem } from './WeekViewItem';
import CommonData from '../common/CommonData';

/**
 * 周视图
 */
@Component
export struct WeekView {
  // swiper当前显示的子组件索引
  @State swiperWeekIndex: number = 1;
  // 控制周视图每个WeekViewItem显示哪一周的数据
  @State weekNumOne: number = -1;
  @State weekNumTwo: number = 0;
  @State weekNumThree: number = 1;
  // 当前选中的日期
  @State @Watch('onSelectDayChange') currentSelectDate: string =
    Constants.TODAY_YEAR + '-' + Constants.TODAY_MONTH + '-' + Constants.TODAY + '-' + '0';
  // 当前显示的年份
  @State currentShowYear: number = Constants.TODAY_YEAR;
  // 当前显示的月份
  @State currentShowMonth: number = Constants.TODAY_MONTH;
  // 用于记录周视图每个WeekViewItem第一天(周日)的年月信息
  private weekYearOne: number = 0;
  private weekYearTwo: number = 0;
  private weekYearThree: number = 0;
  private weekMonthOne: number = 0;
  private weekMonthTwo: number = 0;
  private weekMonthThree: number = 0;
  // 记录swiper上一次显示的子组件索引。
  private oldWeekViewIndex: number = 1;
  // 添加日程后,重新刷新周视图的控制器
  private oneController = new CalendarController();
  private twoController = new CalendarController();
  private threeController = new CalendarController();
  // 自定义日历样式
  CalendarStyle: CalendarStyle = {};
  // 年、月、周视图切换场景的相关设置
  CalendarSwitch: CalendarSwitch = { isYearMonthHidden: false };
  // 日期点击回调
  onDateClick: (year: number, month: number, date: number) => void = () => {
  };
  // 年、月、周视图左右滑动切换回调
  onChangeYearMonth: (year: number, month: number) => void = () => {
  };
  /**
   * 用于年、月、周视图间切换场景下刷新日期数据
   */
  private swiperRefresh = (value: CalendarViewType) => {
    if (value === CalendarViewType.WEEK) {
      if (this.CalendarSwitch.currentSelectDay) {
        // 重置
        this.swiperWeekIndex = 1;
        this.oldWeekViewIndex = 1;
        this.currentSelectDate =
          this.CalendarSwitch.currentSelectDay.year + '-' + this.CalendarSwitch.currentSelectDay.month + '-' +
          this.CalendarSwitch.currentSelectDay.date;
        // 更新年月数据
        this.currentShowYear = this.CalendarSwitch.currentSelectDay.year;
        this.currentShowMonth = this.CalendarSwitch.currentSelectDay.month;
        const SELECT_DAY =
          new Date(this.CalendarSwitch.currentSelectDay.year, this.CalendarSwitch.currentSelectDay.month - 1,
            this.CalendarSwitch.currentSelectDay.date);
        // 计算目前选中的日期selectDay距离今天相差的周数
        const WEEKS_BETWEEN = TimeUtils.weeksBetweenDates(SELECT_DAY);
        this.weekNumOne = WEEKS_BETWEEN - 1; // 设置上一周
        this.weekNumTwo = WEEKS_BETWEEN; // 设置本周
        this.weekNumThree = WEEKS_BETWEEN + 1; // 设置下一周
      }
    }
  }

  /**
   * 日期选择改变
   */
  onSelectDayChange() {
    CommonData.CURRENT_SELECT_DATE = this.currentSelectDate;
    const PARTS: string[] = this.currentSelectDate.split('-');
    // 更新年月数据
    this.currentShowYear = Number(PARTS[0]);
    this.currentShowMonth = Number(PARTS[1]);
    this.onChangeYearMonth(this.currentShowYear, this.currentShowMonth);
  }

  /**
   * 用于添加日程后,重刷周视图数据
   */
  private schedulePointRefresh = () => {
    this.oneController.schedulePointRefresh();
    this.twoController.schedulePointRefresh();
    this.threeController.schedulePointRefresh();
  }

  aboutToAppear() {
    if (this.CalendarSwitch.controller) {
      // 给controller对应的方法赋值
      this.CalendarSwitch.controller.swiperRefresh = this.swiperRefresh;
      this.CalendarSwitch.controller.schedulePointRefresh = this.schedulePointRefresh;
    }
  }

  /**
   * 星期
   */
  @Builder
  weeks() {
    Row() {
      ForEach(Constants.WEEKS, (text: string, index: number) => {
        Text(text)
          .fontSize(Constants.WEEK_FONT_SIZE *
            (this.CalendarStyle.textScaling ? this.CalendarStyle.textScaling : Constants.FONT_MULTIPLIER))
          .fontColor((index === 0 || index === 6) ? Color.Grey : Color.Black)
          .width($r('app.integer.calendar_switch_size_forty'))
          .textAlign(TextAlign.Center)
      }, (text: string) => text)
    }
    .width(Constants.WEEK_VIEW_WIDTH)
    .justifyContent(FlexAlign.SpaceBetween)
    .margin({ bottom: $r('app.integer.calendar_switch_size_ten') })
  }

  build() {
    // 月视图
    Column() {
      if (!this.CalendarSwitch.isYearMonthHidden) {
        // 年月信息标题
        Text(`${this.currentShowYear}年${this.currentShowMonth}月`)
          .fontSize(Constants.YEAR_MONTH_FONT_SIZE *
            (this.CalendarStyle.textScaling ? this.CalendarStyle.textScaling : Constants.FONT_MULTIPLIER))
          .fontWeight(Constants.FONT_WEIGHT_FIVE_HUNDRED)
          .width($r('app.string.calendar_switch_full_size'))
          .padding({ left: $r('app.integer.calendar_switch_size_ten') })
          .margin({ bottom: $r('app.integer.calendar_switch_size_ten') })
      }
      // 星期
      this.weeks()

      Swiper() {
        // 周视图子组件
        WeekViewItem({
          weekNum: this.weekNumOne,
          currentSelectDate: this.currentSelectDate,
          onWeekSwitch: (item: CalendarData) => {
            // 周视图获取第一天(周日)日期数据
            this.weekYearOne = item.year;
            this.weekMonthOne = item.month;
          },
          onDateClick: (year: number, month: number, date: number) => {
            this.onDateClick(year, month, date);
          },
          CalendarStyle: {
            textScaling: this.CalendarStyle.textScaling,
            backgroundColor: this.CalendarStyle.backgroundColor,
            monthDayColor: this.CalendarStyle.monthDayColor,
            lunarColor: this.CalendarStyle.lunarColor
          },
          controller: this.oneController
        })
        WeekViewItem({
          weekNum: this.weekNumTwo,
          currentSelectDate: this.currentSelectDate,
          onWeekSwitch: (item: CalendarData) => {
            // 周视图获取第一天(周日)日期数据
            this.weekYearTwo = item.year;
            this.weekMonthTwo = item.month;
          },
          onDateClick: (year: number, month: number, date: number) => {
            this.onDateClick(year, month, date);
          },
          CalendarStyle: {
            textScaling: this.CalendarStyle.textScaling,
            backgroundColor: this.CalendarStyle.backgroundColor,
            monthDayColor: this.CalendarStyle.monthDayColor,
            lunarColor: this.CalendarStyle.lunarColor
          },
          controller: this.twoController
        })
        WeekViewItem({
          weekNum: this.weekNumThree,
          currentSelectDate: this.currentSelectDate,
          onWeekSwitch: (item: CalendarData) => {
            // 周视图获取第一天(周日)日期数据
            this.weekYearThree = item.year;
            this.weekMonthThree = item.month;
          },
          onDateClick: (year: number, month: number, date: number) => {
            this.onDateClick(year, month, date);
          },
          CalendarStyle: {
            textScaling: this.CalendarStyle.textScaling,
            backgroundColor: this.CalendarStyle.backgroundColor,
            monthDayColor: this.CalendarStyle.monthDayColor,
            lunarColor: this.CalendarStyle.lunarColor
          },
          controller: this.threeController
        })
      }
      .id('weekView')
      .onAnimationStart((index: number, targetIndex: number, extraInfo: SwiperAnimationEvent) => {
        // 判断是否右滑切换周
        const IS_RIGHT_SLIDE: boolean = (index === 1 && targetIndex === 0) || (index === 0 && targetIndex === 2) ||
          (index === 2 && targetIndex === 1);
        // 记录子组件索引
        this.oldWeekViewIndex = targetIndex;
        // 切换周时,刷新当前周视图第一天(周日)对应的年月信息
        this.currentShowYear =
          (this.oldWeekViewIndex === 0) ? this.weekYearOne :
            ((this.oldWeekViewIndex === 1) ? this.weekYearTwo : this.weekYearThree);
        this.currentShowMonth =
          ((this.oldWeekViewIndex === 0) ? this.weekMonthOne :
            ((this.oldWeekViewIndex === 1) ? this.weekMonthTwo : this.weekMonthThree));
        this.onChangeYearMonth(this.currentShowYear, this.currentShowMonth);
        // 右滑切换周
        if (IS_RIGHT_SLIDE) {
          if (targetIndex === 0) {
            // swiper索引右滑到0时,修改swiper索引2的周为当前周(索引0)的上一周。
            this.weekNumThree = this.weekNumOne - 1;
          } else if (targetIndex === 1) {
            // swiper索引右滑到1时,修改swiper索引0的周为当前周(索引1)的上一周。
            this.weekNumOne = this.weekNumTwo - 1;
          } else if (targetIndex === 2) {
            // swiper索引右滑到2时,修改swiper索引1的周为当前周(索引2)的上一周。
            this.weekNumTwo = this.weekNumThree - 1;
          }
        } else {
          // 左滑切换周
          if (targetIndex === 0) {
            // swiper索引左滑到0时,修改swiper索引1的周为当前周(索引0)的下一周。
            this.weekNumTwo = this.weekNumOne + 1;
          } else if (targetIndex === 1) {
            // swiper索引左滑到1时,修改swiper索引2的周为当前周(索引1)的下一周。
            this.weekNumThree = this.weekNumTwo + 1;
          } else if (targetIndex === 2) {
            // swiper索引右滑到2时,修改swiper索引0的周为当前周(索引2)的下一周。
            this.weekNumOne = this.weekNumThree + 1;
          }
        }
      })
      .indicator(false)
      .loop(true)
      .index($$this.swiperWeekIndex)
    }
    .width(Constants.WEEK_VIEW_WIDTH)
    .height(Constants.WEEK_VIEW_HEIGHT)
  }
}