• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (c) 2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16import Constants from '../constant/Constants';
17import { CalendarController, CalendarViewType, DayInfo } from '../components/CustomCalendar';
18import { CalendarStyle, Day } from '../model/CalendarModel';
19import { StyleUtils } from '../utils/StyleUtils';
20import { TimeUtils } from '../utils/TimeUtils'; // 时间计算工具类
21
22/**
23 * 月视图子组件
24 */
25@Component
26export struct MonthViewItem {
27  // 月视图日期数据
28  @State monthDays: Day[][] = [];
29  // 年月信息
30  @Link @Watch('updateMonthData') yearMonth: string;
31  // 当前选中的日期
32  @State currentSelectDay: DayInfo =
33    new DayInfo(new Date().getFullYear(), new Date().getMonth() + 1, new Date().getDate(), 0); // 当前选中的日期
34  // 当前选中的日期,格式'year-month-date-week'
35  @Link @Watch('OnChangeSelectDate') currentSelectDate: string;
36  private year: number = Constants.TODAY_YEAR;
37  private month: number = Constants.TODAY_MONTH;
38  // 自定义日历样式
39  calendarStyle: CalendarStyle = {};
40  // 日期点击回调
41  onDateClick: (year: number, month: number, date: number) => void = () => {
42  };
43  // 日历控制器。这里用于控制添加日程后月视图数据刷新
44  controller?: CalendarController;
45
46  /**
47   * 日期选择监听
48   */
49  OnChangeSelectDate() {
50    const PARTS: string[] = this.currentSelectDate.split('-');
51    this.currentSelectDay.year = Number(PARTS[0]);
52    this.currentSelectDay.month = Number(PARTS[1]);
53    this.currentSelectDay.date = Number(PARTS[2]);
54  }
55
56  /**
57   * 获取指定月份数据
58   */
59  getMonthViewData(year: number, month: number) {
60    this.monthDays = [...TimeUtils.byMonthDayForYear(year, month)];
61  }
62
63  /**
64   * 更新月数据
65   */
66  updateMonthData() {
67    const PARTS: string[] = this.yearMonth.split('-');
68    this.year = Number(PARTS[0]);
69    this.month = Number(PARTS[1]);
70    this.getMonthViewData(this.year, this.month);
71  }
72
73  /**
74   * 刷新日程点数据
75   */
76  private schedulePointRefresh = () => {
77    this.updateMonthData();
78  }
79
80  aboutToAppear() {
81    if (this.controller) {
82      this.controller.schedulePointRefresh = this.schedulePointRefresh;
83    }
84    const PARTS: string[] = this.yearMonth.split('-');
85    this.year = Number(PARTS[0]);
86    this.month = Number(PARTS[1]);
87    this.getMonthViewData(this.year, this.month);
88  }
89
90  /**
91   * 月视图点击上个月或下个月日期切换月份
92   * @param is true为下月,false为上一月
93   */
94  nextMouth(is: boolean) {
95    if (is) {
96      this.year =
97        (this.month + 1 > 12) ? this.year + 1 : this.year;
98      this.month = (this.month + 1 > 12) ? 1 : this.month + 1;
99    } else {
100      this.year =
101        (this.month - 1 < 1) ? this.year - 1 : this.year;
102      this.month = (this.month - 1 < 1) ? 12 : this.month - 1;
103    }
104    this.yearMonth = this.year + '-' + this.month;
105  }
106
107  /**
108   * 月视图一天的子组件
109   * @param day 日期
110   * @param week 月视图周信息。0上个月,1当前月,2下个月
111   */
112  @Builder
113  monthDayBuilder(day: Day, week: number) {
114    Column() {
115      Text(day.dayNum + '')
116        .fontColor(StyleUtils.getColor(day, this.month, this.currentSelectDay, CalendarViewType.MONTH,
117          this.calendarStyle))
118        .fontSize(Constants.DAY_FONT_SIZE *
119          (this.calendarStyle.textScaling ? this.calendarStyle.textScaling : Constants.FONT_MULTIPLIER))
120        .fontWeight(FontWeight.Medium)
121      Text(day.lunarDay)
122        .fontColor(StyleUtils.getLunarDayColor(day, this.month, this.currentSelectDay, CalendarViewType.MONTH,
123          this.calendarStyle))
124        .fontSize(Constants.LUNAR_DAY_FONT_SIZE *
125          (this.calendarStyle.textScaling ? this.calendarStyle.textScaling : Constants.FONT_MULTIPLIER))
126    }
127    .width($r('app.integer.calendar_switch_size_forty'))
128    .height($r('app.integer.calendar_switch_size_forty'))
129    .borderRadius($r('app.integer.calendar_switch_size_forty'))
130    .borderColor($r('app.color.calendar_switch_border_color'))
131    .borderWidth(StyleUtils.getBorderWidth(day, this.month, this.currentSelectDay, CalendarViewType.MONTH))
132    .backgroundColor(StyleUtils.getBackgroundColor(day, this.currentSelectDay, this.calendarStyle))
133    .justifyContent(FlexAlign.Center)
134    .alignItems(HorizontalAlign.Center)
135    .onClick(() => {
136      this.onDateClick(day.dayInfo.year, day.dayInfo.month, day.dayInfo.date);
137      // 月视图需要拼接day.dayInfo.week
138      this.currentSelectDate =
139        day.dayInfo.year + '-' + day.dayInfo.month + '-' + day.dayInfo.date + '-' + day.dayInfo.week;
140      this.currentSelectDay.year = day.dayInfo.year;
141      this.currentSelectDay.month = day.dayInfo.month;
142      this.currentSelectDay.date = day.dayInfo.date;
143      // 必须记录点击日期的week值。CalendarSwitch的onSelectDayChange监听中需要根据week值点击的是上个月还是下个月的日期,从而进行相应的月份切换
144      this.currentSelectDay.week = day.dayInfo.week;
145      // 选中了上个月的日期,切换到上个月。1表示月视图第一周
146      if (week == 1 && day.dayNum > Constants.DAYS_IN_WEEK) {
147        this.nextMouth(false);
148      }
149      // 选中了下个月的日期,切换到下个月。2表示月视图第二周
150      if (week > 2 && day.dayNum < Constants.DAYS_IN_WEEK) {
151        this.nextMouth(true);
152      }
153    })
154  }
155
156  build() {
157    Column() {
158      ForEach(this.monthDays, (items: Day[], index: number) => {
159        Row() {
160          ForEach(items, (item: Day) => {
161            Column() {
162              this.monthDayBuilder(item, index + 1)
163              if (item.isShowSchedulePoint) {
164                // 日程点
165                Circle({ width: Constants.SCHEDULE_POINT_DIAMETER, height: Constants.SCHEDULE_POINT_DIAMETER })
166                  .fill($r('app.color.calendar_switch_schedule_point_color'))
167                  .margin({ top: $r('app.integer.calendar_switch_size_one') })
168              }
169            }
170            .height($r('app.integer.calendar_switch_size_forty_six'))
171          }, (item: Day, index: number) => {
172            return item.dayNum + '' + index + item.isShowSchedulePoint;
173          })
174        }
175        .width($r('app.string.calendar_switch_full_size'))
176        .justifyContent(FlexAlign.SpaceBetween)
177      }, (item: Day[], index: number) => {
178        return item.reduce((item1, item2) => {
179          return item1 + item2.dayInfo.year + item2.dayInfo.month + item2.dayInfo.date + item2.isShowSchedulePoint
180        }, '') + index
181      })
182    }.width($r('app.string.calendar_switch_full_size'))
183  }
184}