Parcourir la source

完成统计页面ui和功能

chenritian il y a 2 semaines
Parent
commit
f8497d17c6

+ 4 - 4
entry/src/main/ets/pages/tabs/HomeTab.ets

@@ -66,7 +66,7 @@ export struct HomeTab {
   }
 
   private saveItem(title: string, date: string, images: ResourceStr[]) {
-    const timestamp = new Date(date).getTime()
+    const timestamp = new Date().getTime()
     if (this.dialogEditingId) {
       // Edit
       const index = this.records.findIndex(v => v.id === this.dialogEditingId);
@@ -76,7 +76,7 @@ export struct HomeTab {
           title: title,
           images: images,
           date: date,
-          timestamp: timestamp // Keep original timestamp? Or update? Vue code updates time on save?
+          timestamp: timestamp//编辑时间每次都变化 // Keep original timestamp? Or update? Vue code updates time on save?
           // Vue code: sort by time. Let's update timestamp to bring to top if sorted by time, or keep original.
           // Vue code: list.sort((a, b) => b.time - a.time);
           // And Vue code sets time = Number(new Date()) on save. So yes, update timestamp.
@@ -121,10 +121,10 @@ export struct HomeTab {
 
         // List
         List({ space: 12 }) {
-          ForEach(this.records, (item: RecordItem) => {
+          ForEach(this.records, (item: RecordItem, index) => {
             ListItem() {
               this.RecordCardBuilder(item)
-            }.margin({ left: 16, right: 16 })
+            }.margin({ left: 16, right: 16, bottom: this.records.length - 1 == index ? YTAvoid.getBottom()! + 70 : 0 })
           })
           if (this.records.length === 0) {
             ListItem() {

+ 211 - 56
entry/src/main/ets/pages/tabs/StatisticsTab.ets

@@ -1,5 +1,11 @@
-import { RecordItem } from "../../model/Models";
-import { DateUtils } from "../../utils/DateUtils";
+import { RecordItem } from '../../model/Models';
+import { SelectType } from '../../pickers/date';
+import { YTDatePicker } from '../../pickers/date/YTDatePicker';
+import { TimeTypeEnum } from '../../pickers/time';
+import { DateUtils } from '../../utils/DateUtils';
+import { YTDate } from '../../utils/YTDate';
+import { fileUri } from '@kit.CoreFileKit';
+import { YTAvoid } from '../../utils/YTAvoid';
 
 
 @Component
@@ -9,29 +15,38 @@ export struct StatisticsTab {
   @State endTime: number = DateUtils.getEndOfDay(Date.now());
   @State showBeginPicker: boolean = false;
   @State showEndPicker: boolean = false;
+  @State list: string[] = []
+  @State groupedRecords: Record<string, RecordItem[]> = {};
 
-  get groupedRecords(): Record<string, RecordItem[]> {
+  getGroupedRecords(): Record<string, RecordItem[]> {
     // Filter
     const filtered = this.records.filter(item => {
-      return item.timestamp >= this.beginTime && item.timestamp <= this.endTime;
+      return DateUtils.getStartOfDay(new Date(item.date).getTime()) >= this.beginTime &&
+        DateUtils.getStartOfDay(new Date(item.date).getTime()) <= this.endTime;
     });
 
     // Group
     const grouped: Record<string, RecordItem[]> = {};
     filtered.forEach(item => {
-      const dateKey = item.date; // already YYYY-MM-DD
+      const dateKey = new YTDate(item.date).formatDate('-', true); // already YYYY-MM-DD
       if (!grouped[dateKey]) {
         grouped[dateKey] = [];
       }
       grouped[dateKey].push(item);
     });
-    
+
     // Sort keys descending? Object keys order is not guaranteed, but we can iterate sorted keys in build
+    this.groupedRecords = grouped;
     return grouped;
   }
 
-  get sortedDateKeys(): string[] {
-    return Object.keys(this.groupedRecords).sort((a, b) => new Date(b).getTime() - new Date(a).getTime());
+  aboutToAppear(): void {
+    this.getSortedDateKeys()
+  }
+
+  getSortedDateKeys() {
+    this.getGroupedRecords()
+    this.list = Object.keys(this.groupedRecords).sort((a, b) => new Date(b).getTime() - new Date(a).getTime());
   }
 
   build() {
@@ -43,24 +58,28 @@ export struct StatisticsTab {
 
       // Date Range Picker Triggers
       Row() {
-        Column() {
+        Column({ space: 8 }) {
           Text('开始时间').fontSize(12).fontColor('#797979').fontWeight(FontWeight.Medium)
           Text(DateUtils.formatTimestamp(this.beginTime, 'YYYY-MM-DD'))
-            .fontSize(16).margin({ top: 8 })
+            .fontSize(16)
         }
         .layoutWeight(1)
         .padding(16)
         .backgroundColor(Color.White)
         .borderRadius(16)
-        .alignItems(HorizontalAlign.Center)
+        .shadow({ radius: this.getUIContext().vp2px(12.5), color: '#1A000000' })
+        .alignItems(HorizontalAlign.Start)
         .onClick(() => {
-          DatePickerDialog.show({
-            start: new Date("2000-1-1"),
-            end: new Date("2100-12-31"),
-            selected: new Date(this.beginTime),
-            onAccept: (value: DatePickerResult) => {
-              const d = new Date(value.year!, value.month!, value.day!);
-              this.beginTime = DateUtils.getStartOfDay(d.getTime());
+          YTDatePicker.show({
+            date: new Date(this.beginTime),
+            type: SelectType.DATE_TIME,
+            timeUnitType: TimeTypeEnum.HH_MM_SS,
+            highlightStyle: {
+              backgroundColor: '#ff7252',
+            },
+            confirm: (date) => {
+              this.beginTime = DateUtils.getStartOfDay(date.getTime());
+              this.getSortedDateKeys()
             }
           })
         })
@@ -70,24 +89,29 @@ export struct StatisticsTab {
           .width(16)
           .height(1)
 
-        Column() {
+        Column({ space: 8 }) {
           Text('结束时间').fontSize(12).fontColor('#797979').fontWeight(FontWeight.Medium)
           Text(DateUtils.formatTimestamp(this.endTime, 'YYYY-MM-DD'))
-            .fontSize(16).margin({ top: 8 })
+            .fontSize(16)
         }
         .layoutWeight(1)
         .padding(16)
         .backgroundColor(Color.White)
         .borderRadius(16)
-        .alignItems(HorizontalAlign.Center)
+        .shadow({ radius: this.getUIContext().vp2px(12.5), color: '#1A000000' })
+        .alignItems(HorizontalAlign.Start)
         .onClick(() => {
-          DatePickerDialog.show({
-            start: new Date("2000-1-1"),
-            end: new Date("2100-12-31"),
-            selected: new Date(this.endTime),
-            onAccept: (value: DatePickerResult) => {
-              const d = new Date(value.year!, value.month!, value.day!);
-              this.endTime = DateUtils.getEndOfDay(d.getTime());
+
+          YTDatePicker.show({
+            date: new Date(this.beginTime),
+            type: SelectType.DATE_TIME,
+            timeUnitType: TimeTypeEnum.HH_MM_SS,
+            highlightStyle: {
+              backgroundColor: '#ff7252',
+            },
+            confirm: (date) => {
+              this.endTime = DateUtils.getStartOfDay(date.getTime());
+              this.getSortedDateKeys()
             }
           })
         })
@@ -97,25 +121,47 @@ export struct StatisticsTab {
       .margin({ bottom: 20 })
 
       // List
-      List() {
-        ForEach(this.sortedDateKeys, (dateKey: string) => {
-          ListItemGroup({ header: this.GroupHeader(dateKey, this.groupedRecords[dateKey].length) }) {
-            ForEach(this.groupedRecords[dateKey], (item: RecordItem) => {
-              ListItem() {
-                this.RecordItemView(item)
-              }.margin({ bottom: 12 })
+      List({ space: 12 }) {
+        ForEach(this.list, (dateKey: string, index) => {
+          ListItem() {
+            RecordItemView({
+              list: this.groupedRecords[dateKey],
+              date: dateKey
             })
           }
+          .margin({ bottom: this.list.length - 1 == index ? YTAvoid.getBottom()! + 70 : 0 })
+
+          //
+          // ListItemGroup({ header: this.GroupHeader(dateKey, this.groupedRecords[dateKey].length) }) {
+          //   ForEach(this.groupedRecords[dateKey], (item: RecordItem) => {
+          //     ListItem() {
+          //       this.RecordItemView(item)
+          //     }.margin({ bottom: this.list.length - 1 == index ? YTAvoid.getBottom()! + 70 : 0 })
+          //   })
+          // }
         })
       }
+      .scrollBar(BarState.Off)
       .width('100%')
       .layoutWeight(1)
-      .padding({ left: 16, right: 16 })
       .edgeEffect(EdgeEffect.Spring)
     }
     .width('100%')
     .height('100%')
-    .backgroundColor('#F5F7FA')
+    .linearGradient({
+      angle: 112,
+      colors: [
+        ['#FFF1EA', 0],
+        ['#E5E9FC', 0.34],
+        ['#FBE3EB', 0.74]
+      ]
+    })
+    .onVisibleAreaChange([0.0, 1.0], (isVisible: boolean, currentRatio: number) => {
+      console.info('IsaKit Test Text isVisible: ' + isVisible + ', currentRatio:' + currentRatio)
+      if (isVisible && currentRatio >= 1.0) {
+        this.getSortedDateKeys()
+      }
+    })
   }
 
   @Builder
@@ -132,31 +178,140 @@ export struct StatisticsTab {
     .justifyContent(FlexAlign.SpaceBetween)
   }
 
-  @Builder
-  RecordItemView(item: RecordItem) {
-    Column() {
-      Text('事件:' + item.title)
-        .fontSize(16).fontWeight(FontWeight.Medium).fontColor('#121212')
-      
-      if (item.images && item.images.length > 0) {
-        Scroll() {
-          Row() {
-            ForEach(item.images, (uri: string) => {
-              Image(uri).width(80).height(80).borderRadius(6).margin({ right: 10 }).objectFit(ImageFit.Cover)
+  // @Builder
+  // RecordItemView(item: RecordItem) {
+  //   Stack({ alignContent: Alignment.Top }) {
+  //     Row() {
+  //
+  //     }
+  //     .width('100%')
+  //     .height(52)
+  //     .borderRadius(16)
+  //     .backgroundColor('#FFF')
+  //
+  //     Column() {
+  //       Text('事件:' + item.title)
+  //         .fontSize(16).fontWeight(FontWeight.Medium).fontColor('#121212')
+  //
+  //       if (item.images && item.images.length > 0) {
+  //         Scroll() {
+  //           Row() {
+  //             ForEach(item.images, (uri: string) => {
+  //               Image(fileUri.getUriFromPath(uri))
+  //                 .width(80)
+  //                 .height(80)
+  //                 .borderRadius(6)
+  //                 .margin({ right: 10 })
+  //                 .objectFit(ImageFit.Cover)
+  //             })
+  //           }
+  //         }
+  //         .scrollable(ScrollDirection.Horizontal)
+  //         .scrollBar(BarState.Off)
+  //         .align(Alignment.Start)
+  //         .margin({ top: 15 })
+  //         .width('100%')
+  //       }
+  //     }
+  //     .padding(16)
+  //     .backgroundColor(Color.White)
+  //     .borderRadius(16)
+  //     .shadow({ radius: 10, color: '#00000008' })
+  //     .width('100%')
+  //     .alignItems(HorizontalAlign.Start)
+  //   }
+  // }
+}
+
+
+@Component
+struct RecordItemView {
+  @Prop list: RecordItem[] = []
+  @Prop date: string = ''
+  @State isShowChild: boolean = false
+  @State columnHeight: Length = 0
+
+  build() {
+    Stack({ alignContent: Alignment.Top }) {
+      Row() {
+        Text(this.date)
+          .fontColor('#FF797979')
+          .font({ size: 14, weight: 400 })
+
+        Row({ space: 4 }) {
+          Text(this.list.length.toString())
+            .fontSize(22).fontColor('#FD5F3E')
+          Text('条心得').fontSize(14).fontColor('#FD5F3E')
+          Image(this.isShowChild ? $r('app.media.icon_down') : $r('app.media.icon_right'))
+            .width(16)
+            .aspectRatio(1)
+        }
+
+      }
+      .justifyContent(FlexAlign.SpaceBetween)
+      .width('100%')
+      .shadow({ radius: this.getUIContext().vp2px(12.5), color: '#1A000000' })
+      .height(52)
+      .borderRadius(16)
+      .backgroundColor('#FFF')
+      .padding({ left: 16, right: 16 })
+      .onClick(() => {
+        this.getUIContext().animateTo({
+          duration: 300, onFinish: () => {
+            this.getUIContext().animateTo({ duration: 300 }, () => {
+              this.columnHeight = this.isShowChild ? 0 : ''
+
             })
           }
+        }, () => {
+          this.isShowChild = !this.isShowChild
+        })
+      })
+      .zIndex(100)
+
+      if (this.isShowChild) {
+        Column({ space: 16 }) {
+          ForEach(this.list, (item: RecordItem) => {
+            Column() {
+              Text('事件:' + item.title)
+                .fontSize(16).fontWeight(FontWeight.Medium).fontColor('#121212')
+
+              if (item.images && item.images.length > 0) {
+                Scroll() {
+                  Row() {
+                    ForEach(item.images, (uri: string) => {
+                      Image(fileUri.getUriFromPath(uri))
+                        .width(80)
+                        .height(80)
+                        .borderRadius(6)
+                        .margin({ right: 10 })
+                        .objectFit(ImageFit.Cover)
+                    })
+                  }
+                }
+                .scrollable(ScrollDirection.Horizontal)
+                .scrollBar(BarState.Off)
+                .align(Alignment.Start)
+                .margin({ top: 15 })
+                .width('100%')
+              }
+            }
+            .padding(16)
+            .backgroundColor(Color.White)
+            .borderRadius(16)
+            .shadow({ radius: 10, color: '#00000008' })
+            .width('100%')
+            .alignItems(HorizontalAlign.Start)
+          })
         }
-        .scrollable(ScrollDirection.Horizontal)
-        .scrollBar(BarState.Off)
-        .margin({ top: 15 })
         .width('100%')
+        .borderRadius(16)
+        .backgroundColor('#FFF')
+        .padding({ top: 52 })
       }
     }
-    .padding(16)
-    .backgroundColor(Color.White)
-    .borderRadius(16)
-    .shadow({ radius: 10, color: '#00000008' })
+    .clip(false)
     .width('100%')
-    .alignItems(HorizontalAlign.Start)
+    .padding({ left: 16, right: 16, top: 10 })
   }
 }

BIN
entry/src/main/resources/base/media/icon_down.png


BIN
entry/src/main/resources/base/media/icon_right.png