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}