|
|
@@ -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 })
|
|
|
}
|
|
|
}
|