• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/**
2 *
3 * Copyright (c) 2025 Huawei Device Co., Ltd.
4 *
5 * All rights reserved.
6 * Redistribution and use in source and binary forms, with or without modification,
7 * are permitted provided that the following conditions are met:
8 *
9 * Redistributions of source code must retain the above copyright notice,this
10 * list of conditions and the following disclaimer.
11 *
12 * Redistributions in binary form must reproduce the above copyright notice,
13 * this list of conditions and the following disclaimer in the documentation
14 * and/or other materials provided with the distribution.
15 *
16 * THIS IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND ANY EXPRESS OR IMPLIED WARRANTIES,
17 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
21 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
22 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS,
23 *
24 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */
26import { DateModel } from '../components/DateModel';
27import { getRealTimeDate, getMonthDate } from '../components/GetDate';
28import promptAction from '@ohos.promptAction';
29import {
30  memo,
31  __memo_context_type,
32  __memo_id_type
33} from '@ohos.arkui.stateManagement'; // should be insert by ui-plugins
34import {
35  Text,
36  TextAttribute,
37  Column,
38  FlexAlign,
39  Component,
40  Button,
41  ButtonAttribute,
42  ClickEvent,
43  UserView,
44  List,
45  ListItem,
46  Image,
47  Tabs,
48  TabContent,
49  Row,
50  ButtonType,
51  Builder,
52  CustomDialogController,
53  DismissDialogAction,
54  DialogAlignment,
55  $r,
56  Resource,
57  Entry,
58  TextInput,
59  Scroller,
60  Flex,
61  HorizontalAlign,
62  SafeAreaType,
63  SafeAreaEdge,
64  FlexWrap,
65  TextAlign,
66  ForEach,
67  Scroll,
68  Color,
69  Span,
70  ItemAlign,
71  Margin
72} from '@ohos.arkui.component'; // TextAttribute should be insert by ui-plugins
73import { State, Link, StorageLink, Consume } from '@ohos.arkui.stateManagement'; // should be insert by ui-plugins
74import hilog from '@ohos.hilog';
75import { Context, UIContext } from '@ohos.arkui.UIContext';
76import { Month, MonthDataSource } from '../components/MonthDataSource';
77
78const ELEMENTS_MARGIN_L = 24;
79const ELEMENTS_MARGIN_M = 8;
80const TRANSITION_DURATION = 200;
81const MONDAY = '一';
82const TUESDAY = '二';
83const WEDNESDAY = '三';
84const THURSDAY = '四';
85const FRIDAY = '五';
86const SATURDAY = '六';
87const SUNDAY = '日';
88const WEEK: string[] = [SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY]; // 设置日历周,从周日开始
89const MONTH: string = '月';
90const YEAR: string = '年';
91const MONTHS = 12;
92const JANUARY = 1;
93const WEEK_NUMBER = 7;
94const MONTH_NUMBER = 35;
95const GRID_HEIGHT_L = 360;
96const GRID_HEIGHT_M = 300;
97const ELEMENTS_MARGIN = 12;
98
99@Entry
100@Component
101export struct CalendarView {
102  private week: string[] = ['日', '一', '二', '三', '四', '五', '六']; // 设置日历周,从周日开始
103  @State dateModel: DateModel = new DateModel(0, 0, 0, 0); // 初始化dateModel数据
104  @State flag: boolean = false;
105  @State contentData: MonthDataSource = new MonthDataSource(); // 列表数据
106  nowDate: Date = new Date();
107  currentMonth: number = this.nowDate.getMonth() + 1; // 当前月份
108  currentDay: number = this.nowDate.getDate(); // 当前日
109  currentYear: number = this.nowDate.getFullYear(); // 当前年份
110  currentWeekDay: number = new Date(this.currentYear, this.currentMonth - 1, this.currentDay).getDay(); // 当前周几
111  private scroller: Scroller = new Scroller(); // 二级列表Scroller对象
112  @State nextMonth: number = 1; // 初始化下一个月月份
113  @State nextYear: number = 1; // 初始化下一个月年份
114  @State nextMonthDay: number[] = new Array<number>(); // 初始化下一个月的日期排列数组
115  @State currentMonthDay: number[] = new Array<number>(); // 初始化当前月的日期排列数组
116
117  // 获取当前日期
118  aboutToAppear(): void {
119    this.dateModel = getRealTimeDate(); // 获取当前年月日信息
120    this.currentMonth = this.dateModel.month; // 获取当前月份
121    this.currentDay = this.dateModel.day; // 获取当前日
122    this.currentYear = this.dateModel.year; // 获取当前年份
123
124    this.currentMonthDay = getMonthDate(this.currentMonth, this.currentYear);
125    // 如果下个月是在下一年,则下个月是1月份,年份要+1
126    if (this.currentMonth === MONTHS) {
127      this.nextMonth = JANUARY;
128      this.nextYear = this.currentYear + 1;
129    } else {
130      this.nextMonth = this.currentMonth + 1;
131      this.nextYear = this.currentYear;
132    }
133    this.nextMonthDay = getMonthDate(this.nextMonth, this.nextYear);
134    // 获取当前月和下个月的日期数据
135    const months: Month =
136      {
137        month: `${this.currentYear}年 ${this.currentMonth}月`,
138        num: this.currentMonth,
139        days: this.currentMonthDay
140      }
141    const months2: Month =
142      {
143        month: `${this.nextYear}年 ${this.nextMonth}月`,
144        num: this.nextMonth,
145        days: this.nextMonthDay
146      }
147    this.contentData.pushData(months);
148    this.contentData.pushData(months2);
149  }
150
151  @State strss: string | Resource = $r('app.string.customcalendarpickerdialog_departure');
152
153  @Builder
154  calendarMainView() {
155    Column() {
156      Column() {
157        // 出发地和目的地显示
158        Row() {
159          Text($r('app.string.customcalendarpickerdialog_departure'))
160            .fontSize(20)
161          Image($r('app.media.app_icon'))
162            .height(20)
163            .width(20)
164          Text($r('app.string.customcalendarpickerdialog_destination'))
165            .fontSize(20)
166        }
167        .justifyContent(FlexAlign.SpaceBetween)
168        .width('100%')
169
170        // 当前日期显示
171        Row() {
172          Text(`${this.dateModel.month}月${this.dateModel.day}日`)
173            .fontSize(20)
174          Text(`星期${this.week[this.dateModel.week]}`)
175            .fontSize(20)
176        }
177        .id('calender_click')
178        .justifyContent(FlexAlign.Start)
179        .width('100%')
180        .margin(8)
181        .onClick((e: ClickEvent) => {
182          // 点击当前日期后打开自定义弹窗显示日历
183          hilog.info(0x0000, 'testTag', '查询车票按钮显示 onClick');
184          this.flag = !this.flag;
185        })
186
187        // 查询车票按钮显示
188        Button($r('app.string.customcalendarpickerdialog_check_ticket'))
189          .fontSize(20)
190          .width('100%')
191          .onClick((e: ClickEvent) => {
192          })
193      }
194      .margin(10)
195      .borderRadius($r('app.string.ohos_id_corner_radius_default_m'))
196
197      Flex({ wrap: FlexWrap.Wrap }) {
198        Text($r('app.string.customcalendarpickerdialog_departure_date'))
199          .fontSize(20)
200          .height(20).width('100%')
201          .textAlign(TextAlign.Center)
202        // 显示周信息,从周日开始到周六
203        ForEach(WEEK, (weekday: string) => {
204          Text(weekday)
205            .fontSize(20)
206            .width(50)
207            .height(30)
208            .fontColor(weekday === SUNDAY || weekday === SATURDAY ? Color.Red : Color.Black)
209            .borderRadius(10)
210            .textAlign(TextAlign.Center)
211            .layoutWeight(1)
212        })
213        List() {
214          ForEach(this.contentData.dataArray, (monthItem: Month) => {
215            ListItem() {
216              Flex({ wrap: FlexWrap.Wrap }) {
217                // 月份信息
218                Text(monthItem.month)
219                  .width('100%')
220                  .height(40)
221                  .fontSize(20)
222                  .fontColor(Color.Black)
223                  .backgroundColor($r('app.color.highlyloadedcomponentrender_color_year_background'))
224                  .textAlign(TextAlign.Center)
225                  .id('id_highly_loaded_component_render_title')
226                // 日期信息
227                ForEach(monthItem.days, (day: number, index: number) => {
228                  Text() {
229                    Span(JSON.stringify(day))
230                      .fontSize(20)
231                  }
232                  .height(50)
233                  .width(50)
234                  .opacity(day === 0 ? 0 : 1)
235                  .fontColor(day < this.currentDay && monthItem.num === this.currentMonth ? Color.Grey :
236                  Color.Black)
237                  .borderRadius(10)
238                  .textAlign(TextAlign.Center)
239                  .backgroundColor(day === this.currentDay && monthItem.num === this.currentMonth ?
240                  $r('app.color.ohos_id_color_palette9') : Color.Transparent)
241                  .onClick((e: ClickEvent) => {
242                    if (day >= this.currentDay || monthItem.num > this.currentMonth ||
243                      Number(monthItem.month.substring(0, 4)) > this.currentYear) {
244                      let weekIndex = monthItem.days.indexOf(day) % WEEK_NUMBER; // 将当前日转换成星期显示
245                      let dateModelTmp: DateModel = new DateModel(0, 0, 0, 0);
246                      dateModelTmp.day = day;
247                      dateModelTmp.week = weekIndex;
248                      dateModelTmp.month = monthItem.num;
249                      dateModelTmp.year = Number(monthItem.month.substring(0, 4));
250                      this.dateModel = dateModelTmp;
251                      if (this.flag == true) {
252                        this.flag = false;
253                      }
254                    }
255                  })
256                })
257              }.width('100%')
258            }
259          })
260        }
261        .width('100%')
262        .height('100%')
263        .backgroundColor($r('app.color.ohos_id_color_background'))
264        .expandSafeArea([SafeAreaType.SYSTEM], [SafeAreaEdge.BOTTOM])
265      }
266      .width('100%')
267      .height('60%')
268      .margin(10)
269      .opacity(this.flag === true ? 1 : 0)
270      .borderRadius($r('app.string.ohos_id_corner_radius_default_m'))
271    }.height('100%')
272  }
273
274  build() {
275    Column() {
276      this.calendarMainView();
277    }
278    .width('100%')
279    .height('100%')
280  }
281}