浏览代码

feat: 修改在日记页面弹出的日历样式, 优化了部分UI和交互逻辑

YuJing 2 月之前
父节点
当前提交
86aa2a363c

+ 191 - 0
features/feature/src/main/ets/components/DiaryCalendarPicker.ets

@@ -0,0 +1,191 @@
+import { DateInfo } from "../models/DateInfo";
+import { DateUtils, WEEK_MAP } from "../utils/DateUtils";
+
+@Component
+@CustomDialog
+export struct DiaryCalendarPicker {
+  // 年月
+  @State year: number = 2025;
+  @State month: number = 8;
+  // 开始是星期几
+  @State weekStart: number = 1;
+  // 本月的天数
+  @State daysInMonth: number = 31;
+  // 渲染用的月份数组
+  @State monthArray: DateInfo[] = [];
+  @State showDatePickerMenu: boolean = false
+  @State selectDay: Date = new Date()
+
+  private declare range: TextCascadePickerRangeContent[]
+  private years = Array.from<number, number>({ length: new Date().getFullYear() - 1970 + 1 }, (_: number, i: number) => 1970 + i)
+  //当前年月选择的下标
+  private selectedIndex: number[] = [new Date().getFullYear() - 1970, new Date().getMonth()]
+  private linearInfo: LinearGradientOptions = {
+    colors: [['#B9FD2A', 0.01], ['#F5FD6D', 1]],
+    angle: 110
+  }
+
+  // 取消
+  @Require onCancel: () => void = () => {}
+  // 确定
+  @Require onConfirm: (date: Date) => void = () => {}
+  @Require dateList: string[] = []
+
+  controll?: CustomDialogController
+
+  // 更改月份
+  changeMonth(year: number, month: number) {
+    // 1. 获取当前月份的天数
+    this.daysInMonth = DateUtils.getDaysInMonth(year, month);
+
+    // 2. 获取当月的第一天是星期几
+    this.weekStart = new Date(year, month - 1, 1).getDay() + 1;
+
+    // 3. 初始化月份数组
+    this.monthArray = [...new Array(this.weekStart - 1).fill({} as DateInfo),
+      ...DateUtils.generateBackwardDateArray(new Date(year, month - 1, 1), this.daysInMonth, false)];
+
+    return this.monthArray
+  }
+
+  aboutToAppear(): void {
+    this.changeMonth(2025, 8);
+
+    const monthsRange =
+      Array.from<number, number>({ length: 12 }, (_: number, i: number) => 1 + i).map(month => {
+        return { text: month.toString() } as TextCascadePickerRangeContent
+      })
+    this.range = this.years.map(year => {
+      return { text: year.toString(), children: monthsRange } as TextCascadePickerRangeContent
+    })
+  }
+
+  build() {
+    Column({space: 20}) {
+      Row() {
+        // 时间选择
+        Row({ space: 8 }) {
+          Text(`${this.year}-${this.month.toString().padStart(2, '0')}`)
+            .fontSize(16)
+            .fontWeight(600)
+
+          Image($r('app.media.Diary_DateOpen'))
+            .width(14)
+            .height(8)
+        }
+        .onClick(() => {
+          this.showDatePickerMenu = true
+        })
+        .bindMenu(this.showDatePickerMenu, this.dateSelectMenu, {
+          onDisappear: () => {
+            this.showDatePickerMenu = false
+            this.year = this.range[this.selectedIndex[0]].text.valueOf() as number
+            this.month = this.range[this.selectedIndex[0]].children![this.selectedIndex[1]].text.valueOf() as number
+            this.changeMonth(this.year, this.month)
+          },
+          placement: Placement.Bottom
+        })
+
+        // 确认和取消
+        Row({ space: 14 }) {
+          Text("取消")
+            .borderRadius(36)
+            .backgroundColor('#F6F6F6')
+            .padding({left: 20, top: 5, right: 20, bottom: 5})
+            .onClick(this.onCancel)
+          Text("确认")
+            .borderRadius(36)
+            .linearGradient(this.linearInfo)
+            .padding({left: 20, top: 5, right: 20, bottom: 5})
+            .onClick(() => {
+              this.onConfirm(this.selectDay)
+            })
+        }
+      }
+      .width("100%")
+      .alignItems(VerticalAlign.Center)
+      .justifyContent(FlexAlign.SpaceBetween)
+
+      Row() {
+        ForEach(WEEK_MAP, (item: string, index: number) => {
+          Text(item)
+        })
+      }
+      .width("100%")
+      .justifyContent(FlexAlign.SpaceBetween)
+
+      Grid() {
+        ForEach(this.monthArray, (item: DateInfo, index: number) => {
+          GridItem() {
+            Column({space: 3}) {
+              if (item.id) {
+                Row() {
+                  Text(item.day + '')
+                    .fontSize(12)
+                    .fontColor(DateUtils.isSameDay(item.id, this.selectDay) ? Color.Black : '#979797')
+                }
+                .width(32)
+                .aspectRatio(1)
+                .borderRadius(8)
+                .linearGradient(DateUtils.isSameDay(item.id, this.selectDay) ? this.linearInfo : {
+                  colors: [['#F6F6F6', 1]],
+                })
+                .alignItems(VerticalAlign.Center)
+                .justifyContent(FlexAlign.Center)
+                .onClick(() => {
+                  this.selectDay = item.id
+                })
+
+                  Text()
+                    .width(4)
+                    .aspectRatio(1)
+                    .borderRadius(2)
+                    .linearGradient(this.dateList.indexOf(DateUtils.formatDateToCustomString(item.id, false)) !== -1 ? this.linearInfo : null)
+              } else {
+                Text('')
+                Text('')
+              }
+            }
+            .width(49)
+            .aspectRatio(1)
+            .alignItems(HorizontalAlign.Center)
+            .justifyContent(FlexAlign.Center)
+          }
+        })
+      }
+      .columnsTemplate('repeat(7, 1fr)')
+      .width("100%")
+    }
+    .width("100%")
+    .height(400)
+    .backgroundColor(Color.White)
+    .padding({left: 15, right: 15, top: 20, bottom: 4})
+  }
+
+  @Builder
+  private dateSelectMenu() {
+    Stack({ alignContent: Alignment.Center }) {
+      TextPicker({ range: this.range, selected: this.selectedIndex })
+        .selectedTextStyle({ color: '#FF353C46', font: { weight: 500, size: 16 } })
+        .defaultPickerItemHeight(36)
+        .divider(null)
+        .onScrollStop((value, index) => {
+          console.log(`testLog ${value} ${index}`)
+          this.selectedIndex = index as number[]
+        })
+
+      //自定义选择遮罩
+      Column() {
+
+      }
+      .width('100%')
+      .height(36)
+      .backgroundColor('#52D9D9D9')
+      .borderRadius(8)
+    }
+    .height(140)
+    .width(160)
+    .padding(12)
+    .borderRadius(8)
+  }
+}

+ 1 - 0
features/feature/src/main/ets/components/DiaryTimePicker.ets

@@ -38,6 +38,7 @@ export struct DiaryTimePicker {
           this.selectedHour = hour;
           this.selectedMinute = minute;
 
+          // 保证swiper组件已经渲染
           setTimeout(() => {
             this.hourController.changeIndex(hour);
             this.minuteController.changeIndex(minute);

+ 2 - 2
features/feature/src/main/ets/pages/IncreaseDiaryPage.ets

@@ -353,6 +353,7 @@ struct IncreaseDiaryPage {
               .padding({top: 12})
               .layoutWeight(1)
               .width("100%")
+              .scrollBar(BarState.Off)
 
               Column({space: 32}){
                 // 图片显示器
@@ -510,8 +511,7 @@ struct IncreaseDiaryPage {
     }
     .hideTitleBar(true)
     .onBackPressed(() => {
-      console.log("返回"+this.pageReadOnly)
-      return this.onRouterBack.bind(this)
+      return this.onRouterBack()
     })
   }
 }

+ 18 - 3
features/feature/src/main/ets/utils/DateUtils.ets

@@ -1,7 +1,7 @@
 import { DateInfo } from "../models/DateInfo";
 
 // 星期中文映射表
-const WEEK_MAP = ['日', '一', '二', '三', '四', '五', '六'];
+export const WEEK_MAP = ['日', '一', '二', '三', '四', '五', '六'];
 
 /**
  * 创建一个日期信息对象
@@ -38,6 +38,20 @@ export class DateUtils {
     return result;
   }
 
+  // 获取指定月份的天数
+  static getDaysInMonth(year: number, month: number): number {
+    return new Date(year, month, 0).getDate();
+  }
+
+  // 是否为同一天
+  static isSameDay(date1: Date, date2: Date): boolean {
+    return (
+      date1.getFullYear() === date2.getFullYear() &&
+      date1.getMonth() === date2.getMonth() &&
+      date1.getDate() === date2.getDate()
+    );
+  }
+
   /**
    * 生成从指定日期开始向前的连续日期数组
    * @param startDate 起始日期(默认当前日期)
@@ -72,7 +86,8 @@ export class DateUtils {
    */
   static generateBackwardDateArray(
     startDate: Date = new Date(),
-    count: number = 7
+    count: number = 7,
+    isCheck: boolean = true
   ): DateInfo[] {
     const dateArray: DateInfo[] = [];
 
@@ -88,7 +103,7 @@ export class DateUtils {
 
     for (let i = 0; i < count; i++) {
       // 检查当前日期是否超过今天
-      if (currentDate > today) {
+      if (isCheck && currentDate > today) {
         break;
       }
 

+ 18 - 10
features/feature/src/main/ets/view/DiaryView.ets

@@ -1,4 +1,5 @@
 import { IBestToast, userInfo, UserInfo, YTAvoid, yTRouter, yTToast } from "basic"
+import { DiaryCalendarPicker } from "../components/DiaryCalendarPicker"
 import { DiaryTitleItem } from "../components/DiaryTitleItem"
 import { DoubleConfirm } from "../components/DoubleConfirm"
 import { LoginComponent } from "../components/LoginComponent"
@@ -76,14 +77,21 @@ export struct DiaryView {
    * 打开日期选择器
    */
   openDatePicker(){
-    CalendarPickerDialog.show({
-      selected: new Date(),
-      start: new Date('1970-01-10'),
-      end: new Date(DateUtils.formatDateToCustomString(new Date(), false)),
-      onAccept: (value) => {
-        this.toDiaryHead(value)
-      }
+    let controll: CustomDialogController = new CustomDialogController({
+      builder: DiaryCalendarPicker({
+        dateList: this.Vm.dateList,
+        onConfirm: (value) => {
+          this.toDiaryHead(value)
+          controll.close()
+        },
+        onCancel: () => {
+          controll.close()
+        }
+      }),
+      alignment: DialogAlignment.Center,
     })
+
+    controll.open()
   }
 
   /**
@@ -213,15 +221,15 @@ export struct DiaryView {
           // 增加日记按钮
           Row() {
             Image($r("app.media.add_Img"))
-              .width(40)
+              .width(50)
               .aspectRatio(1)
           }
           .onClick(() => {
             this.routerDiaryPage()
           })
-          .width(40)
+          .width(50)
           .aspectRatio(1)
-          .borderRadius(20)
+          .borderRadius(30)
           .margin({ bottom: 16 })
           .alignItems(VerticalAlign.Center)
           .justifyContent(FlexAlign.Center)

+ 2 - 3
features/feature/src/main/ets/view/RecodView.ets

@@ -1,11 +1,10 @@
-import { AppStorageKeyCollect, IBestToast, userInfo, UserInfo, YTAvoid, yTRouter } from 'basic'
+import { IBestToast, userInfo, UserInfo, YTAvoid, yTRouter } from 'basic'
 import { DateInfo } from '../models/DateInfo'
 import { RecodeViewModel } from '../viewModels/RecodeViewModel'
 import { DiaryDatePicker } from '../components/DiaryDatePicker'
 import { DiaryTimePicker } from '../components/DiaryTimePicker'
 import { DateUtils } from '../utils/DateUtils'
 import { DiaryData, PageStatus } from '../models'
-import { CollaborationCameraStateDialog } from '@hms.collaboration.camera'
 import { LoginComponent } from '../components/LoginComponent'
 
 /**
@@ -402,7 +401,7 @@ export struct RecodView {
               .onClick(() => {
                 this.routerAddNote()
               })
-              .width(40)
+              .width(50)
               .aspectRatio(1)
               .borderRadius(20)
               .margin({ bottom: 16 })