Pārlūkot izejas kodu

git界面静态模板完成

XUYangWei 2 mēneši atpakaļ
vecāks
revīzija
eb61b28240
53 mainītis faili ar 4567 papildinājumiem un 346 dzēšanām
  1. 1 1
      AppScope/app.json5
  2. 14 14
      build-profile.json5
  3. 18 0
      commons/basic/src/main/ets/apis/YTUserRequest.ets
  4. 2 1
      commons/basic/src/main/ets/components/ToastBuilders/YtDoubleConfirm.ets
  5. 1 0
      features/feature/Index.ets
  6. 118 0
      features/feature/src/main/ets/api/DiaryApi.ets
  7. 75 0
      features/feature/src/main/ets/components/fourcomponent/DiaryDatePicker.ets
  8. 179 0
      features/feature/src/main/ets/components/fourcomponent/DiaryTimePicker.ets
  9. 33 0
      features/feature/src/main/ets/components/maincomponent/BuilderHeader.ets
  10. 105 0
      features/feature/src/main/ets/components/maincomponent/DiaryDatePicker.ets
  11. 167 0
      features/feature/src/main/ets/components/maincomponent/DiaryTimePicker.ets
  12. 32 0
      features/feature/src/main/ets/components/maincomponent/SwiperCom.ets
  13. 68 0
      features/feature/src/main/ets/components/maincomponent/TimeLineNode.ets
  14. 0 0
      features/feature/src/main/ets/constants/index.ets
  15. 24 0
      features/feature/src/main/ets/data/index.ets
  16. 0 0
      features/feature/src/main/ets/models/ApiParams.ets
  17. 119 0
      features/feature/src/main/ets/models/BasicDataSource.ets
  18. 8 0
      features/feature/src/main/ets/models/DateInfo.ets
  19. 8 0
      features/feature/src/main/ets/models/GreenPlant.ets
  20. 30 0
      features/feature/src/main/ets/models/Second.ets
  21. 35 0
      features/feature/src/main/ets/models/index.ets
  22. 956 0
      features/feature/src/main/ets/pages/EditGreenPlantPage.ets
  23. 105 0
      features/feature/src/main/ets/pages/GrowInfoPage.ets
  24. 535 0
      features/feature/src/main/ets/pages/IncreaseDiaryPage.ets
  25. 138 0
      features/feature/src/main/ets/utils/DateUtils.ets
  26. 146 0
      features/feature/src/main/ets/view/DiaryViewModel.ets
  27. 478 0
      features/feature/src/main/ets/view/FourView.ets
  28. 595 46
      features/feature/src/main/ets/view/MainView.ets
  29. 228 0
      features/feature/src/main/ets/view/RecodeViewModel.ets
  30. 237 197
      features/feature/src/main/ets/view/SecondView.ets
  31. 2 85
      features/feature/src/main/ets/view/ThirdView.ets
  32. 26 0
      features/feature/src/main/ets/viewmodels/EditGreenPlantPageModel.ets
  33. 26 0
      features/feature/src/main/ets/viewmodels/MainViewModel.ets
  34. 6 0
      features/feature/src/main/ets/viewmodels/SecondViewModel.ets
  35. 1 0
      features/feature/src/main/resources/base/media/Diary_DateOpen.svg
  36. BIN
      features/feature/src/main/resources/base/media/Diary_Entry.png
  37. BIN
      features/feature/src/main/resources/base/media/Diary_cancel.png
  38. 4 0
      features/feature/src/main/resources/base/media/Diary_close.svg
  39. BIN
      features/feature/src/main/resources/base/media/RecodeTitle.png
  40. BIN
      features/feature/src/main/resources/base/media/add_Img.png
  41. BIN
      features/feature/src/main/resources/base/media/calendar.png
  42. BIN
      features/feature/src/main/resources/base/media/close.png
  43. BIN
      features/feature/src/main/resources/base/media/icon_message.png
  44. BIN
      features/feature/src/main/resources/base/media/main_icon_delete.png
  45. BIN
      features/feature/src/main/resources/base/media/main_icon_edit.png
  46. BIN
      features/feature/src/main/resources/base/media/main_icon_maintenance.png
  47. BIN
      features/feature/src/main/resources/base/media/main_icon_select_plant.png
  48. BIN
      features/feature/src/main/resources/base/media/main_icon_unselect_plant.png
  49. 12 0
      features/feature/src/main/resources/base/media/photoAlbum.svg
  50. BIN
      features/feature/src/main/resources/base/media/startIcon.png
  51. 15 0
      features/feature/src/main/resources/base/profile/router_map.json
  52. 8 1
      products/entry/src/main/ets/pages/Index.ets
  53. 12 1
      products/entry/src/main/resources/base/profile/router_map.json

+ 1 - 1
AppScope/app.json5

@@ -1,6 +1,6 @@
 {
   "app": {
-    "bundleName": "com.ytpm.ltlab",
+    "bundleName": "com.ytpm.lzyhzs",
     "vendor": "example",
     "versionCode": 1000000,
     "versionName": "1.0.0",

+ 14 - 14
build-profile.json5

@@ -1,19 +1,19 @@
 {
   "app": {
-    "signingConfigs": [
-      {
-        "name": "default",
-        "material": {
-          "storeFile": "sign/basic.p12",
-          "storePassword": "000000181F0EECD983295AB4504A961E19D1B5914CB198FA414395A09865788F96EFF93C84981A55",
-          "keyAlias": "yt112233",
-          "keyPassword": "0000001871572C6DAC842AAE8EF9A99F0F746307476E0F0ACF919CC12B0F81467CF5B0CCDBF97E2D",
-          "signAlg": "SHA256withECDSA",
-          "profile": "sign/聊天恋爱宝调试证书.p7b",
-          "certpath": "sign/调试证书.cer"
-        }
-      }
-    ],
+//    "signingConfigs": [
+//      {
+//        "name": "default",
+//        "material": {
+//          "storeFile": "sign/basic.p12",
+//          "storePassword": "000000181F0EECD983295AB4504A961E19D1B5914CB198FA414395A09865788F96EFF93C84981A55",
+//          "keyAlias": "yt112233",
+//          "keyPassword": "0000001871572C6DAC842AAE8EF9A99F0F746307476E0F0ACF919CC12B0F81467CF5B0CCDBF97E2D",
+//          "signAlg": "SHA256withECDSA",
+//          "profile": "sign/聊天恋爱宝调试证书.p7b",
+//          "certpath": "sign/调试证书.cer"
+//        }
+//      }
+//    ],
     "products": [
       {
         "name": "default",

+ 18 - 0
commons/basic/src/main/ets/apis/YTUserRequest.ets

@@ -191,6 +191,24 @@ export class YTUserRequest extends YTRequest {
       })
   }
 
+  //上传文件
+  static uploadUserFile(context: Context, fullpath: string, success: (url: string) => void) {
+    const formData = new FormData()
+    formData.append('file', fullpath)
+    YTUserRequest.upPost<ReqString, FormData>('/common/upload', formData, {
+      headers: { 'Content-Type': 'multipart/form-data' },
+      context,
+      onUploadProgress: (progressEvent: AxiosProgressEvent): void => {
+        YTLog.info(progressEvent && progressEvent.loaded && progressEvent.total ?
+          Math.ceil(progressEvent.loaded / progressEvent.total * 100) + '%' : '0%', 'uploadFile');
+      }
+    })
+      .then(res => {
+        const url = res['url']
+        success(url)
+      })
+  }
+
 
   //账号注销/warehouseApUser/logout
   static logout(result?: ResultCallBack<undefined>) {

+ 2 - 1
commons/basic/src/main/ets/components/ToastBuilders/YtDoubleConfirm.ets

@@ -21,7 +21,8 @@ export function yTDoubleConfirm(item: BasicType<undefined>) {
           btHeight: 37,
           btFontSize: 12,
           click: item.click,
-          btLinearGradient: { angle: 92, colors: [['#FF4597F7', 0.023], ['#FF6B6DF7', 1.081]] },
+          bgc:"#206D43"
+          // btLinearGradient: { angle: 92, colors: [['#FF4597F7', 0.023], ['#FF6B6DF7', 1.081]] },
         }
       )
       YTButton(

+ 1 - 0
features/feature/Index.ets

@@ -3,6 +3,7 @@ export { MainView } from './src/main/ets/view/MainView';
 export { SecondView } from './src/main/ets/view/SecondView';
 
 export { ThirdView } from './src/main/ets/view/ThirdView';
+export {FourView} from './src/main/ets/view/FourView'
 
 export { add } from './src/main/ets/utils/Calc';
 

+ 118 - 0
features/feature/src/main/ets/api/DiaryApi.ets

@@ -0,0 +1,118 @@
+import { YTRequest } from "basic";
+import { data } from "../data";
+import { DiaryData } from "../models";
+export class DiaryApi {
+  /**
+   * 删除日记
+   * @param id 日记id
+   * @returns
+   */
+  // static deleteDiaryLog(id: number): Promise<boolean> {
+  //
+  //   // return YTRequest.delete<boolean>(ApiUrl.DELETE_DIARY_LOG + '?id=' + id)
+  // }
+
+  /**
+   * 新增日记
+   * @param params 日记数据结构
+   * @returns
+   */
+  // static saveDiaryLog(params: DiaryData): Promise<boolean> {
+  //   // return YTRequest.post<boolean, DiaryData>(ApiUrl.LOG_SAVE, params)
+  // }
+
+  /**
+   * 返回对应 id 的日记详情
+   * @param id 日记id
+   * @returns
+   */
+  // static queryDiaryLogById(id: number): Promise<DiaryData> {
+  //   // return YTRequest.get<DiaryData>(ApiUrl.QUERY_DIARY_LOG_BY_ID + '?id=' + id)
+  // }
+
+  /**
+   * 查询日记列表
+   * @param nowTime 当前时间
+   * @returns 日记列表
+   */
+  // static queryDiaryLogList(nowTime: string): Promise<DiaryData[]> {
+  //   // return YTRequest.post<DiaryData[], number>(ApiUrl.QUERY_DIARY_LOG_LIST + '?nowTime=' + nowTime)
+  // }
+
+  /**
+   * 日记搜索
+   * @param keyword 标题关键字
+   * @returns 日记列表
+   */
+  // static diaryLogSearch(keyword: string): Promise<DiaryData[]> {
+  //   // return YTRequest.get<DiaryData[]>(ApiUrl.DIARY_LOG_SEARCH + '?keyword=' + keyword)
+  // }
+
+  /**
+   * 修改日记
+   * @param params 日记数据结构
+   * @returns
+   */
+  // static updateDiaryLog(params: DiaryData): Promise<boolean> {
+  //   // return YTRequest.post<boolean, DiaryData>(ApiUrl.UPDATE_DIARY_LOG, params)
+  // }
+
+  /**
+   * 删除生活小记录
+   * @param id 生活小记录id
+   * @returns
+   */
+  static deleteNote(id: number): Promise<boolean> {
+    // return YTRequest.delete<boolean>(ApiUrl.DELETE_NOTE + '?id=' + id)
+    // const a=true
+    return Promise.resolve(true)
+  }
+
+  /**
+   * 添加生活小记录
+   * @param params 生活小记录数据结构
+   * @returns
+   */
+  // static saveNote(params: DiaryData): Promise<boolean> {
+  //   // return YTRequest.post<boolean, DiaryData>(ApiUrl.NOTE_SAVE, params)
+  // }
+
+  /**
+   * 查询生活小记录
+   * @param nowTime 当前选中的时间
+   * @returns 生活小记录列表
+   */
+  static queryNoteList(nowTime: string): Promise<DiaryData[]> {
+    return Promise.resolve(data as DiaryData[]);
+    // return YTRequest.get<DiaryData[]>(ApiUrl.QUERY_BY_NOTE_LIST + '?nowTime=' + nowTime)
+  }
+
+  /**
+   * 查询生活小记录对象
+   * @param id 生活小记录id
+   * @returns
+   */
+  // static queryNoteById(id: number): Promise<DiaryData> {
+  //   // return YTRequest.get<DiaryData>(ApiUrl.QUERY_NOTE_BY_ID + '?id=' + id)
+  // }
+
+  /**
+   * 编辑生活小记录
+   * @param params 生活小记录数据结构
+   * @returns
+   */
+  // static updateNote(params: DiaryData): Promise<boolean> {
+  //   // return YTRequest.post<boolean, DiaryData>(ApiUrl.UPDATE_NOTE, params)
+  // }
+
+  /**
+   * 修改生活小记录时间
+   * @param params 生活小记录数据结构
+   * @returns
+   */
+  static updateNoteTime(params: DiaryData): Promise<boolean> {
+
+    return Promise.resolve(true)
+    // return YTRequest.post<boolean, DiaryData>(ApiUrl.UPDATE_NOTE_TIME, params)
+  }
+}

+ 75 - 0
features/feature/src/main/ets/components/fourcomponent/DiaryDatePicker.ets

@@ -0,0 +1,75 @@
+
+// 日期选择器
+@Component
+export struct DiaryDatePicker {
+  @State selectedDate: Date = new Date();
+
+  private linearInfo: LinearGradientOptions = {
+    colors: [['#EAF3F2',1]],
+    angle: 150
+  }
+
+  selectDateBack: (date: Date) => void = (date: Date) => {
+    console.log("选择的日期" + date.toLocaleString())
+  }
+
+  build() {
+    Column({space: 10}){
+      Row(){
+        Text("今天")
+          .fontSize(18)
+          .fontWeight(500)
+          .fontColor('#206D43')
+          .onClick(() => {
+            this.selectedDate = new Date()
+          })
+        Text("确认")
+          .fontSize(16)
+          .fontWeight(500)
+          .borderRadius(32)
+          .backgroundColor('#206D43')
+          // .linearGradient(this.linearInfo)
+          .padding({ left: 16, right: 16, top: 4, bottom: 4})
+          .onClick(() => {
+            this.selectDateBack(this.selectedDate)
+          })
+      }
+      .width("100%")
+      .justifyContent(FlexAlign.SpaceBetween)
+      .padding({ left: 16, right: 16, top: 16, bottom: 16})
+
+
+      Stack({alignContent: Alignment.Center}){
+        Row()
+          .width("100%")
+          .height(36)
+          .linearGradient(this.linearInfo)
+
+        DatePicker({
+          end: new Date(),
+          selected: this.selectedDate,
+        })
+          .selectedTextStyle({
+            color: '#498552',
+            font: {size:13}
+          })
+          .textStyle({
+            color:'#3A3A3A',
+            font: {size:13}
+          })
+          .onDateChange((date: Date) => {
+            this.selectedDate = date
+          })
+      }
+      .padding({ left: 12, right: 12})
+    }
+    .width("100%")
+    .borderRadius(12)
+    .backgroundColor(Color.White)
+    .shadow({
+      radius: 10,
+      type: ShadowType.COLOR,
+      color: Color.Black
+    })
+  }
+}

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

@@ -0,0 +1,179 @@
+import { DateUtils } from "../../utils/DateUtils"
+
+@Component
+export struct DiaryTimePicker {
+  @State selectedHour: number = 0
+  @State selectedMinute: number = 0
+  private hourController: SwiperController = new SwiperController()
+  private minuteController: SwiperController = new SwiperController()
+  iwidth= 160
+  timeStr: String = DateUtils.formatDateToCustomString(new Date(), true).split(' ')[1]
+
+  // 回调函数
+  onConfirm?: (time: string) => void = (time: string) => {
+    console.log('onConfirm' + time)
+  }
+
+  onCancel?: () => void
+
+  private linearInfo: LinearGradientOptions = {
+    colors: [ ['#B9FD2A', 0.01], ['#F5FD6D', 1] ],
+    angle: 150
+  }
+
+  aboutToAppear(): void {
+    if (this.timeStr) {
+      // 解析时间字符串 'hh:mm'
+      const timeParts = this.timeStr.split(':');
+      if (timeParts.length >= 2) {
+        let hour = parseInt(timeParts[0], 10) - 1;
+        let minute = parseInt(timeParts[1], 10) - 1;
+
+        if (hour < 0) hour = 23
+        if (minute < 0) minute = 59
+
+        // 验证时间有效性
+        if (!isNaN(hour) && !isNaN(minute) && hour >= 0 && hour < 24 && minute >= 0 && minute < 60) {
+          this.selectedHour = hour;
+          this.selectedMinute = minute;
+
+          // 保证swiper组件已经渲染
+          setTimeout(() => {
+            this.hourController.changeIndex(hour);
+            this.minuteController.changeIndex(minute);
+          }, 0)
+        }
+      }
+    }
+  }
+
+  build() {
+    Column() {
+
+      Row(){
+        Row(){
+          Image($r('app.media.Diary_cancel'))
+            .width(24)
+            .aspectRatio(1)
+        }
+        .borderRadius(36)
+        .backgroundColor('#F5F5F7')
+        .padding({left: 10, right:10})
+        .alignItems(VerticalAlign.Center)
+        .justifyContent(FlexAlign.Center)
+        .onClick(() => {
+          this.onCancel?.()
+        })
+
+        Row(){
+          Image($r('app.media.Diary_Entry'))
+            .width(24)
+            .aspectRatio(1)
+        }
+        .alignItems(VerticalAlign.Center)
+        .justifyContent(FlexAlign.Center)
+        .padding({left: 10, right:10})
+        .borderRadius(36)
+        .linearGradient(this.linearInfo)
+        .onClick(() => {
+          const formattedHour = ((this.selectedHour+1)%24).toString().padStart(2, '0');
+          const formattedMinute = ((this.selectedMinute+1)%60).toString().padStart(2, '0');
+          const formattedTime = `${formattedHour}:${formattedMinute}`;
+          this.onConfirm?.(formattedTime);
+        })
+      }
+      .width("100%")
+      .justifyContent(FlexAlign.SpaceBetween)
+      .padding({ left: 15, right: 15, top: 17})
+
+      Stack({alignContent: Alignment.Center}){
+        Row()
+          .height(50)
+          .width("100%")
+          .linearGradient(this.linearInfo)
+
+        // 时间选择区域
+        Row() {
+          // 小时选择器
+          Column() {
+            Swiper(this.hourController) {
+              ForEach(new Array(24).fill(0), (item: number, index: number) => {
+                Text(`${index.toString().padStart(2, '0')}`)
+                  .fontWeight(FontWeight.Bold)
+                  .fontSize(index === (this.selectedHour+1)%24 ? 16 : 14)
+                  .width('100%')
+                  .height(30)
+                  .fontColor(index === (this.selectedHour+1)%24 ? '#212245' : '#757575')
+                  .textAlign(TextAlign.Center)
+                  .alignSelf(ItemAlign.Center)
+                  .borderRadius(8)
+              })
+            }
+            .borderColor(Color.Transparent)
+            .loop(true)
+            .displayCount(3)
+            .curve(Curve.Linear)
+            .indicator(false)
+            .vertical(true)
+            .nextMargin(1)
+            .prevMargin(1)
+            .onChange((index: number) => {
+              this.selectedHour = index
+            })
+            .align(Alignment.Center)  // 关键:确保选中项居中
+          }
+          .borderColor(Color.Transparent)
+          .layoutWeight(1)
+          .height(150)
+
+          // 分隔符
+          Text(':')
+            .fontSize(24)
+            .fontWeight(FontWeight.Bold)
+            .fontColor('#333333')
+            .alignSelf(ItemAlign.Center)
+
+          // 分钟选择器
+          Column() {
+            Swiper(this.minuteController) {
+              ForEach(new Array(60).fill(0), (item: number, index: number) => {
+                Text(`${index.toString().padStart(2, '0')}`)
+                  .fontSize(index === (this.selectedMinute+1)%60 ? 16 : 14)
+                  .fontWeight(FontWeight.Bold)
+                  .fontColor(index === (this.selectedMinute+1)%60 ? '#212245' : '#757575')
+                  .width('100%')
+                  .height(30)
+                  .textAlign(TextAlign.Center)
+                  .alignSelf(ItemAlign.Center)
+                  .borderRadius(8)
+              })
+            }
+            .loop(true)
+            .displayCount(3)
+            .curve(Curve.Linear)
+            .indicator(false)
+            .vertical(true)
+            .nextMargin(1)
+            .prevMargin(1)
+            .onChange((index: number) => {
+              this.selectedMinute = index
+            })
+            .align(Alignment.Center)  // 关键:确保选中项居中
+          }
+          .layoutWeight(1)
+          .height(150)
+        }
+        .width('100%')
+        .padding({ left: 12, right: 12 })
+      }
+    }
+    .width(this.iwidth)
+    .backgroundColor(Color.White)
+    .borderRadius(20)
+    .shadow({
+      radius: 10,
+      type: ShadowType.COLOR,
+      color: Color.Black
+    })
+  }
+}

+ 33 - 0
features/feature/src/main/ets/components/maincomponent/BuilderHeader.ets

@@ -0,0 +1,33 @@
+
+@ComponentV2
+export struct BuilderHeader{
+  @Param leftTitle:string=""
+  @Param centerTitle:string=""
+  @Param rightTitle:string=""
+  // @Event d:(swiper:SwiperController,index:number)=>void=(swiper:SwiperController,index:number)=>{}
+  @Event leftClick:()=>void=()=>{}
+  @Event rightClick:()=>void=()=>{}
+  build() {
+    Row(){
+      Text(this.leftTitle)
+        .fontColor('#B3333333')
+        .fontSize(18)
+        .fontWeight(500)
+        .onClick(()=>{
+        this.leftClick()
+      })
+      Text(this.centerTitle)
+        .fontColor('#FF333333')
+        .fontSize(18)
+        .fontWeight(600)
+      Text(this.rightTitle)
+        .fontColor('#FF206D43')
+        .fontSize(18)
+        .fontWeight(500)
+        .onClick(()=>{
+        this.rightClick()
+      })
+    }.width('100%')
+    .justifyContent(FlexAlign.SpaceBetween)
+  }
+}

+ 105 - 0
features/feature/src/main/ets/components/maincomponent/DiaryDatePicker.ets

@@ -0,0 +1,105 @@
+import { BuilderHeader } from "./BuilderHeader";
+
+
+// 日期选择器
+@Component
+export struct DiaryDatePicker {
+  @State selectedDate: Date = new Date();
+
+  private linearInfo: LinearGradientOptions = {
+    colors: [['#EAF3F2',1]],
+    angle: 150
+  }
+
+  selectDateBack: (date: Date) => void = (date: Date) => {
+    console.log("选择的日期" + date.toLocaleString())
+  }
+  back:()=>void=()=>{
+
+  }
+
+  build() {
+    Column(){
+      Column(){
+
+      }.layoutWeight(1)
+      .width('100%')
+      .backgroundColor(Color.Transparent)
+      Row(){
+        BuilderHeader({
+          leftTitle:'取消',
+          centerTitle:"选择日期",
+          rightTitle:"确定",
+          leftClick:()=>{
+            this.selectedDate = new Date()
+            this.back()
+          },
+          rightClick:()=>{
+            this.selectDateBack(this.selectedDate)
+          }
+        })
+
+      }.width("100%")
+      .backgroundColor(Color.White)
+      .padding({top:19,left:16,right:16})
+      .borderRadius({topLeft:20,topRight:20})
+      Stack({alignContent: Alignment.Center}){
+        Row()
+          .width("100%")
+          .height(50)
+          .borderRadius(12)
+          .linearGradient(this.linearInfo)
+
+        DatePicker({
+          end: new Date(),
+          selected: this.selectedDate,
+        })
+          .selectedTextStyle({
+            color: '#498552',
+            font: {size:22}
+          })
+          .textStyle({
+            color:'#3A3A3A',
+            font: {size:18}
+          })
+          .onDateChange((date: Date) => {
+            this.selectedDate = date
+          })
+
+      }
+      .backgroundColor(Color.White)
+      .layoutWeight(1)
+      .padding({ left: 12, right: 12})
+    }
+    .width("100%")
+    .height('100%')
+    .borderRadius(12)
+  }
+}
+/**
+ *    Row(){
+ Text("取消")
+ .fontSize(18)
+ .fontWeight(500)
+ .fontColor('#206D43')
+ .onClick(() => {
+
+ })
+ Text('选择日期')
+ Text("确定")
+ .fontSize(16)
+ .fontWeight(500)
+ .borderRadius(32)
+ .backgroundColor('#206D43')
+ // .linearGradient(this.linearInfo)
+ .padding({ left: 16, right: 16, top: 4, bottom: 4})
+ .onClick(() => {
+
+ })
+ }
+ .width("100%")
+ .justifyContent(FlexAlign.SpaceBetween)
+ .padding({ left: 16, right: 16, top: 16, bottom: 16})
+ .backgroundColor(Color.White)
+ .borderRadius({topLeft:20,topRight:20})
+ */

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

@@ -0,0 +1,167 @@
+import { DateUtils } from "../../utils/DateUtils"
+
+@Component
+export struct DiaryTimePicker {
+  @State selectedHour: number = 0
+  @State selectedMinute: number = 0
+  private hourController: SwiperController = new SwiperController()
+  private minuteController: SwiperController = new SwiperController()
+  iwidth= 160
+  timeStr: String = DateUtils.formatDateToCustomString(new Date(), true).split(' ')[1]
+
+  // 回调函数
+  onConfirm?: (time: string) => void = (time: string) => {
+    console.log('onConfirm' + time)
+  }
+
+  onCancel?: () => void
+
+
+
+  aboutToAppear(): void {
+    if (this.timeStr) {
+      // 解析时间字符串 'hh:mm'
+      const timeParts = this.timeStr.split(':');
+      if (timeParts.length >= 2) {
+        let hour = parseInt(timeParts[0], 10) - 1;
+        let minute = parseInt(timeParts[1], 10) - 1;
+
+        if (hour < 0) hour = 23
+        if (minute < 0) minute = 59
+
+        // 验证时间有效性
+        if (!isNaN(hour) && !isNaN(minute) && hour >= 0 && hour < 24 && minute >= 0 && minute < 60) {
+          this.selectedHour = hour;
+          this.selectedMinute = minute;
+
+          // 保证swiper组件已经渲染
+          setTimeout(() => {
+            this.hourController.changeIndex(hour);
+            this.minuteController.changeIndex(minute);
+          }, 0)
+        }
+      }
+    }
+  }
+
+  build() {
+    Column() {
+
+      Row(){
+        Row(){
+          Text('取消')
+        }
+        .borderRadius(36)
+        .backgroundColor('#F5F5F7')
+        .padding({left: 10, right:10})
+        .alignItems(VerticalAlign.Center)
+        .justifyContent(FlexAlign.Center)
+        .onClick(() => {
+          this.onCancel?.()
+        })
+
+        Row(){
+          Text('确定')
+        }
+        .alignItems(VerticalAlign.Center)
+        .justifyContent(FlexAlign.Center)
+        .padding({left: 10, right:10})
+        .borderRadius(36)
+        .onClick(() => {
+          const formattedHour = ((this.selectedHour+1)%24).toString().padStart(2, '0');
+          const formattedMinute = ((this.selectedMinute+1)%60).toString().padStart(2, '0');
+          const formattedTime = `${formattedHour}:${formattedMinute}`;
+          this.onConfirm?.(formattedTime);
+        })
+      }
+      .width("100%")
+      .justifyContent(FlexAlign.SpaceBetween)
+      .padding({ left: 15, right: 15, top: 17})
+
+      Stack({alignContent: Alignment.Center}){
+        Row()
+          .height(50)
+          .width("100%")
+          .backgroundColor('#EAF3F2')
+
+        // 时间选择区域
+        Row() {
+          // 小时选择器
+          Column() {
+            Swiper(this.hourController) {
+              ForEach(new Array(24).fill(0), (item: number, index: number) => {
+                Text(`${index.toString().padStart(2, '0')}`)
+                  .fontWeight(FontWeight.Bold)
+                  .fontSize(index === (this.selectedHour+4)%24 ? 16 : 14)
+                  .width('100%')
+                  .height(30)
+                  .fontColor(index === (this.selectedHour+4)%24 ? '#212245' : '#757575')
+                  .textAlign(TextAlign.Center)
+                  .alignSelf(ItemAlign.Center)
+                  .borderRadius(9)
+              })
+            }
+            .borderColor(Color.Transparent)
+            .loop(true)
+            .displayCount(9)
+            .curve(Curve.Linear)
+            .indicator(false)
+            .vertical(true)
+            .nextMargin(1)
+            .prevMargin(1)
+            .onChange((index: number) => {
+              this.selectedHour = index
+            })
+            .align(Alignment.Center)  // 关键:确保选中项居中
+          }
+          .borderColor(Color.Transparent)
+          .layoutWeight(1)
+          .height(450)
+
+          // 分隔符
+          Text(':')
+            .fontSize(24)
+            .fontWeight(FontWeight.Bold)
+            .fontColor('#333333')
+            .alignSelf(ItemAlign.Center)
+
+          // 分钟选择器
+          Column() {
+            Swiper(this.minuteController) {
+              ForEach(new Array(60).fill(0), (item: number, index: number) => {
+                Text(`${index.toString().padStart(2, '0')}`)
+                  .fontSize(index === (this.selectedMinute+4)%60 ? 16 : 14)
+                  .fontWeight(FontWeight.Bold)
+                  .fontColor(index === (this.selectedMinute+4)%60 ? '#212245' : '#757575')
+                  .width('100%')
+                  .height(30)
+                  .textAlign(TextAlign.Center)
+                  .alignSelf(ItemAlign.Center)
+                  .borderRadius(8)
+              })
+            }
+            .loop(true)
+            .displayCount(9)
+            .curve(Curve.Linear)
+            .indicator(false)
+            .vertical(true)
+            .nextMargin(1)
+            .prevMargin(1)
+            .onChange((index: number) => {
+              this.selectedMinute = index
+            })
+            .align(Alignment.Center)  // 关键:确保选中项居中
+          }
+          .layoutWeight(1)
+          .height(450)
+        }
+        .width('100%')
+        .padding({ left: 12, right: 12 })
+      }
+    }
+    .width('100%')
+    .height('100%')
+    .backgroundColor(Color.White)
+    .borderRadius(20)
+  }
+}

+ 32 - 0
features/feature/src/main/ets/components/maincomponent/SwiperCom.ets

@@ -0,0 +1,32 @@
+@ComponentV2
+export struct SwiperCom{
+  // @Local vm:models=new models()
+  @Param @Require
+  swiperComController:SwiperController
+  @BuilderParam swiperBuilder1?: () => void
+  @BuilderParam swiperBuilder2?: () => void
+  @BuilderParam swiperBuilder3?: () => void
+  @BuilderParam swiperBuilder4?: () => void
+  build() {
+    Swiper(this.swiperComController){
+      if(this.swiperBuilder1){
+        this.swiperBuilder1()
+      }
+      if(this.swiperBuilder2){
+        this.swiperBuilder2()
+      }
+      if(this.swiperBuilder3){
+        this.swiperBuilder3()
+      }
+      if(this.swiperBuilder4){
+        this.swiperBuilder4()
+      }
+    }.width('100%')
+    .height('100%')
+    .autoPlay(false)
+    .indicator(false)
+    .disableSwipe(true)
+    .curve(Curve.EaseIn)
+    .duration(100)
+  }
+}

+ 68 - 0
features/feature/src/main/ets/components/maincomponent/TimeLineNode.ets

@@ -0,0 +1,68 @@
+export class OrderDetailBean {
+  nodeName?: string //节点名称
+  nodeTime?: string //节点时间
+  nodeMessage?:string //信息
+  nodeImg?:ResourceStr //图片
+  nodeState?:number //0 父节点 1 子节点
+}
+
+@Component
+export struct TimeLineNode {
+  @Prop bean: OrderDetailBean = new OrderDetailBean()
+  @Prop index: number = 0
+  @Prop totalSize: number = 0
+  @Prop minHeight: number = 54
+
+  build() {
+    Row() {
+      Row({space:22}) {
+        Text(this.bean.nodeState==0?'今天':'17:18')
+          .fontSize(14)
+          .textAlign(TextAlign.Center)
+          .backgroundColor(this.bean.nodeState==0?'#EAF3F2':Color.Transparent)
+          .width(50)
+          .borderRadius(5)
+          .padding(this.bean.nodeState==0?{left:10,right:10,top:4,bottom:4}:0)
+        Column() {
+          // 时间轴节点
+          Row()
+            .width(this.bean.nodeState==0?12:8)
+            .height(this.bean.nodeState==0?12:8)
+            .backgroundColor(this.bean.nodeState==0?'#206D43':'#B2D8C3')
+            .borderRadius('50%')
+          // 时间轴
+          if (this.index != this.totalSize - 1) {
+            Column()
+              .width(2)
+              .height(this.bean.nodeState==0?'20':this.minHeight)
+              .backgroundColor('#206D43')
+          }
+        }.width(12)
+        .alignItems(HorizontalAlign.Center)
+        .justifyContent(FlexAlign.Center)
+        .margin({ right: 16 })
+      }.alignItems(VerticalAlign.Top)
+      .justifyContent(FlexAlign.Center)
+
+      // 内容区域
+      Column() {
+        Text(this.bean.nodeName)
+          .fontSize(14)
+          .fontColor('#000')
+          .fontWeight(FontWeight.Medium)
+
+        Text(this.bean.nodeMessage)
+          .fontSize(12)
+          .fontWeight(FontWeight.Regular)
+          .fontColor('#000')
+          .margin({ top: 2 })
+      }
+      .alignItems(HorizontalAlign.Start)
+      .width('84%')
+      .translate({ y: 2 })
+    }
+    .alignItems(VerticalAlign.Top)
+    .justifyContent(FlexAlign.Center)
+    .width('100%')
+  }
+}

+ 0 - 0
features/feature/src/main/ets/constants/index.ets


+ 24 - 0
features/feature/src/main/ets/data/index.ets

@@ -0,0 +1,24 @@
+import { DiaryData } from "../models";
+
+export let data:DiaryData[]=[
+  {
+    id: 690,
+    userId: 4146,
+    title: "1",
+    content: "哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈",
+    noteTime: "2025-10-11 14:34:00",
+    imageUrls: []
+  },
+  {
+    id: 691,
+    userId: 4146,
+    title: "嘿",
+    content: "耶耶耶",
+    noteTime: "2025-10-11 14:35:00",
+    imageUrls: [
+      "https://hm-static.ytpm.net/upload/20251011/77976a0b-e88f-4330-b363-4997b74ac8b0-1760164579584.jpeg",
+      "https://hm-static.ytpm.net/upload/20251011/455fa5ca-6bb7-49f4-998b-483f5b09c62a-1760164579584.jpeg"
+    ]
+  }
+
+]

+ 0 - 0
features/feature/src/main/ets/models/ApiParams.ets


+ 119 - 0
features/feature/src/main/ets/models/BasicDataSource.ets

@@ -0,0 +1,119 @@
+// 《记录》页面中日历使用的懒加载数据源
+export class BasicDataSource<T> implements IDataSource {
+  private listeners: DataChangeListener[] = [];
+  private dataArray: T[] = [];
+
+
+  // =============================================================
+  // ===================  框架侧调用  ==============================
+  // ===============  接口内部需实现的方法  ==========================
+  // =============================================================
+
+  // 该方法为框架侧调用,为LazyForEach组件向其数据源处添加listener监听
+  registerDataChangeListener(listener: DataChangeListener): void {
+    if (this.listeners.indexOf(listener) < 0) {
+      console.info('add listener');
+      this.listeners.push(listener);
+    }
+  }
+
+  // 该方法为框架侧调用,为对应的LazyForEach组件在数据源处去除listener监听
+  unregisterDataChangeListener(listener: DataChangeListener): void {
+    const pos = this.listeners.indexOf(listener);
+    if (pos >= 0) {
+      console.info('remove listener');
+      this.listeners.splice(pos, 1);
+    }
+  }
+
+  // =============================================================
+  // ===================  程序调用  ===============================
+  // =========== 整合 DataChangeListener 内部的方法 ================
+  // =============================================================
+
+  // 通知LazyForEach组件需要重载所有子组件
+  notifyDataReload(): void {
+    this.listeners.forEach(listener => {
+      listener.onDataReloaded();
+    })
+  }
+
+  // 通知LazyForEach组件需要在index对应索引处添加子组件
+  notifyDataAdd(index: number): void {
+    this.listeners.forEach(listener => {
+      listener.onDataAdd(index);
+    })
+  }
+
+  // 通知LazyForEach组件在index对应索引处数据有变化,需要重建该子组件
+  notifyDataChange(index: number): void {
+    this.listeners.forEach(listener => {
+      listener.onDataChange(index);
+    })
+  }
+
+  // 通知LazyForEach组件需要在index对应索引处删除该子组件
+  notifyDataDelete(index: number): void {
+    this.listeners.forEach(listener => {
+      listener.onDataDelete(index);
+    })
+  }
+
+  // 通知LazyForEach组件将from索引和to索引处的子组件进行交换
+  notifyDataMove(from: number, to: number): void {
+    this.listeners.forEach(listener => {
+      listener.onDataMove(from, to);
+    })
+  }
+
+
+  // =============================================================
+  // ======================  修改数据源  ===========================
+  // ======================== 外部调用 =============================
+  // =============================================================
+  public totalCount(): number {
+    return this.dataArray.length;
+  }
+
+  public getData(index: number): T {
+    return this.dataArray[index];
+  }
+
+  // 在指定的索引处添加一个元素
+  public addData(index: number, data: T): void {
+    this.dataArray.splice(index, 0, data);
+    this.notifyDataAdd(index);
+  }
+
+  // 往监听列表内部添加元素
+  public pushData(data: T): void {
+    this.dataArray.push(data);
+    this.notifyDataAdd(this.dataArray.length - 1);
+  }
+
+  // 往监听列表内部添加元素
+  public unshiftData(data: T): void {
+    this.dataArray.unshift(data);
+    this.notifyDataAdd(0);
+  }
+
+  // 所有数据进行重新赋值
+  public init(data: T[]) {
+    this.dataArray = data
+    this.notifyDataReload()
+  }
+
+  // 传入一个数组, 初始化监听列表 - 在数组尾部追加数据
+  public reloadDataPush(datas: T[]) {
+    datas.forEach(i => {
+      this.pushData(i)
+    })
+  }
+
+  // 传入一个数组, 初始化监听列表
+  public reloadDataUnshift(datas: T[]) {
+    datas.forEach(i => {
+      this.unshiftData(i)
+    })
+  }
+}

+ 8 - 0
features/feature/src/main/ets/models/DateInfo.ets

@@ -0,0 +1,8 @@
+// 日期信息接口定义
+export interface DateInfo {
+  year: number;   // 年份
+  month: number;  // 月份(1-12)
+  day: number;    // 日期(1-31)
+  week: string;   // 星期(中文)
+  id: Date ;    // 唯一标识
+}

+ 8 - 0
features/feature/src/main/ets/models/GreenPlant.ets

@@ -0,0 +1,8 @@
+
+interface GreenPlant{
+  id:number,
+  img:ResourceStr,
+  plantName:string,
+  a:'xxxxx',
+  b:'xxxxx'
+}

+ 30 - 0
features/feature/src/main/ets/models/Second.ets

@@ -0,0 +1,30 @@
+interface TaskItemInterface{
+  isShowClose:boolean
+  src: ResourceStr
+  text: string
+  message: string
+  click: () => void
+}
+@ObservedV2
+export class TaskItem{
+  @Trace
+  isShowClose:boolean
+  src: ResourceStr
+  text: string
+  message: string
+  click: () => void
+  constructor(item:TaskItemInterface) {
+    this.isShowClose=item.isShowClose
+    this.src=item.src
+    this.text=item.text
+    this.message=item.message
+    this.click=item.click
+  }
+}
+
+//成长明细
+export interface GrowInfo{
+  text:string,
+  date:string,
+  value:string
+}

+ 35 - 0
features/feature/src/main/ets/models/index.ets

@@ -0,0 +1,35 @@
+/**
+ * 日记详细数据模型
+ */
+export interface DiaryData{
+  // 富文本正文
+  content?: string
+  // 日记日期
+  diaryDate?: string
+  // 日记id
+  id?: number
+  // 图片地址集合
+  imageUrls?: string[]
+  // 日记标题
+  title?: string
+  // 用户id
+  userId?: number
+  // 时间
+  noteTime?: string
+}
+
+export enum PageStatus{
+  DIARY,
+  RECODE
+}
+
+// 常量
+export enum Constant{
+  // 历史搜索记录 key 值
+  HistoricalSearchRecords = 'HISTORICAL_SEARCH_RECORDS'
+}
+
+// 变量
+export class Variable{
+  static pageReadOnly: boolean = false;
+}

+ 956 - 0
features/feature/src/main/ets/pages/EditGreenPlantPage.ets

@@ -0,0 +1,956 @@
+import { RouterPage, YTHeader, yTRouter } from "basic"
+import { BuilderHeader } from "../components/maincomponent/BuilderHeader"
+import { SwiperCom } from "../components/maincomponent/SwiperCom"
+import { OrderDetailBean, TimeLineNode } from "../components/maincomponent/TimeLineNode"
+import { DateFrequency, EditGreenPlantPageModel } from "../viewmodels/EditGreenPlantPageModel"
+import { LengthMetrics } from "@kit.ArkUI"
+import { DiaryTimePicker } from "../components/maincomponent/DiaryTimePicker"
+import { DiaryDatePicker } from "../components/maincomponent/DiaryDatePicker"
+
+
+@ComponentV2
+@RouterPage
+struct EditGreenPlantPage{
+  @Local title:string=""
+  @Local currentSelectIndex:number=0
+  @Local timeLineList: OrderDetailBean[] = [
+    {
+      nodeTime:'2025/06/30',
+      nodeState:0
+    },
+    {
+      nodeName:'扣款',
+      nodeMessage:'xxxxxx',
+      nodeTime:'17:18',
+      nodeImg:$r('app.media.app_icon'),
+      nodeState:1
+    },
+    {
+      nodeName:'扣款',
+      nodeMessage:'xxxxxx',
+      nodeTime:'17:18',
+      nodeImg:$r('app.media.app_icon'),
+      nodeState:1
+    },
+    {
+      nodeTime:'2025/06/29',
+      nodeState:0
+    },
+    {
+      nodeName:'扣款',
+      nodeMessage:'xxxxxx',
+      nodeTime:'17:18',
+      nodeImg:$r('app.media.app_icon'),
+      nodeState:1
+    },
+    {
+      nodeName:'扣款',
+      nodeMessage:'xxxxxx',
+      nodeTime:'17:18',
+      nodeImg:$r('app.media.app_icon'),
+      nodeState:1
+    },
+    {
+      nodeTime:'2025/06/01',
+      nodeState:0
+    },
+    {
+      nodeName:'扣款',
+      nodeMessage:'xxxxxx',
+      nodeTime:'17:18',
+      nodeImg:$r('app.media.app_icon'),
+      nodeState:1
+    },
+    {
+      nodeName:'扣款',
+      nodeMessage:'xxxxxx',
+      nodeTime:'17:18',
+      nodeImg:$r('app.media.app_icon'),
+      nodeState:1
+    },
+  ]
+  @Local totalSize: number = 9
+  private frequencyList:string[]=['仅提醒一次','每天','每周','每月','自定义间隔天数']
+  private weekList:string[]=['周一','周二','周三','周四','周五','周六','周日']
+  private monthList:string[]=['1号','2号','3号','4号','5号','6号','7号','8号','9号','10号',
+    '11号','12号','13号','14号','15号','16号','17号','18号','19号','20号',
+    '21号','22号','23号','24号','25号','26号','27号','28号','29号','30号']
+  private currentSelectFrequencyIndex:number=0
+  private currentSelectWeekIndex:number=0
+  private currentSelectMonthIndex:number=0
+  @Local vm:EditGreenPlantPageModel=new EditGreenPlantPageModel()
+  //提醒设置
+  @Local isShowRemindClockBuilder:boolean=false
+  aboutToAppear(): void {
+    this.title=yTRouter.getParamByName('EditGreenPlantPage').pop() as string
+
+  }
+  onBackPressUpdateData(ans:string='false'){
+    yTRouter.pop(ans,true)
+  }
+  build() {
+    NavDestination(){
+      Column({space:20}) {
+        YTHeader({
+          leftComp: () => {
+            this.leftComBuilder()
+          },
+          title: this.title,
+
+          rightComp: () => {
+            this.rightBuilder()
+          }
+
+        })
+        Column(){
+          Row(){
+            Text('基本信息').fontSize(14).fontColor('#333333')
+          }.width('100%')
+          .justifyContent(FlexAlign.Start)
+
+          Row(){
+            Image($r('app.media.startIcon'))
+          }.width(106)
+          .height(136)
+          .padding(12)
+          .backgroundColor('#E8EBF0')
+          .borderRadius(12)
+
+          Row(){
+            Text('名称').fontSize(14).fontColor('#333333')
+            Text('龟背竹').fontSize(14).fontColor('#206D43')
+
+          }.width('100%')
+          .justifyContent(FlexAlign.SpaceBetween)
+          .padding({right:16})
+
+        }.width('100%')
+        .borderRadius(12)
+        .height(195)
+        .padding({top:9,bottom:5,left:13})
+        .backgroundColor(Color.White)
+        .shadow({
+          // 模糊半径
+          radius: 10,
+          // 阴影类型
+          type: ShadowType.COLOR,
+          // 阴影颜色
+          color: '#1A000000',
+          // X 轴偏移
+          offsetX: 1,
+          // Y 轴偏移
+          offsetY: 1,
+          // 是否内部填充,值为布尔型,默认为flase
+          fill: false
+        })
+        Row(){
+          Column(){
+            Text('养护记录').fontSize(this.currentSelectIndex==0?16:14)
+            Row()
+              .width(20)
+              .height(3)
+              .backgroundColor(this.currentSelectIndex==0?'#206d43':Color.Transparent)
+          }.margin({right:22}).onClick(()=>{
+            this.currentSelectIndex=0
+          })
+          Column(){
+            Text('提醒设置').fontSize(this.currentSelectIndex==1?16:14)
+            Row()
+              .width(20)
+              .height(3)
+              .backgroundColor(this.currentSelectIndex==1?'#206d43':Color.Transparent)
+          }.onClick(()=>{
+            this.currentSelectIndex=1
+
+          })
+        }.width('100%')
+        Column() {
+          if (this.currentSelectIndex == 0) {
+            List() {
+              ForEach(this.timeLineList, (item: object, index: number) => {
+                TimeLineNode({ bean: item, index: index, totalSize: this.totalSize })
+              }, (item: object) => JSON.stringify(item))
+            }.margin({ left: 30 }).scrollBar(BarState.Off)
+          }else{
+            Column(){
+              Row(){
+
+                Column({space:6}){
+                  Image($r('app.media.app_icon')).width(50)
+                  Text('xxx')
+                }
+                Blank()
+
+                Column({space:17}){
+                  Row({space:15}){
+                    Text('下次提醒')
+                      .fontSize(14)
+                      .fontWeight(500)
+                      .fontColor('#206D43')
+                    Text('2023-09-11 15:30')
+                      .fontSize(12)
+                  }
+                  Row({space:15}){
+                    Text('提醒间隔')
+                      .fontSize(14)
+                      .fontWeight(500)
+                      .fontColor('#206D43')
+                    Text('每天')
+                      .fontSize(12)
+                  }
+                }.height('100%')
+                .justifyContent(FlexAlign.Start)
+                .alignItems(HorizontalAlign.Start)
+                .margin({top:20,right:15})
+
+                Column(){
+
+                }.width(45)
+                .height(20)
+                .backgroundColor(Color.Gray)
+
+              }.width('100%')
+              .height(100)
+              .padding({left:15,right:15,top:11,bottom:11})
+              .backgroundColor('#fff')
+              .borderRadius(12)
+
+              Button('xxxx').onClick(()=>{
+                this.isShowRemindClockBuilder=!this.isShowRemindClockBuilder
+
+              })
+
+            }
+            .backgroundColor(Color.Pink)
+
+          }
+        }
+        .layoutWeight(1)
+        .bindSheet($$this.isShowRemindClockBuilder,this.RemindClockBuilder(),{
+          height:530,
+          showClose:false,
+          backgroundColor:Color.Transparent
+        })
+
+
+      }.padding({left:16,right:16}).backgroundColor('#FAFAFA')
+
+    }.hideTitleBar(true)
+
+  }
+  @Builder
+  leftComBuilder(){
+    Image($r('app.media.startIcon')).width(18).height(18).onClick(()=>{
+      this.onBackPressUpdateData()
+    })
+
+  }
+  @Builder
+  rightBuilder(){
+    Text('确认').fontSize(16).fontColor('#206D43').onClick(()=>{
+    })
+
+  }
+
+  @Builder
+  RemindClockBuilder(){
+    Column(){
+      Swiper(this.vm.swiperController){
+        Column(){
+          Column(){
+
+            Row(){
+              Text('取消').fontColor('#333333')
+              Text('提醒设置')
+              Text('设置').fontColor('#206D43')
+
+            }.width('100%')
+            .justifyContent(FlexAlign.SpaceBetween)
+            .margin({bottom:16})
+
+            Column({space:20}) {
+              Column() {
+
+                Row() {
+                  Text('提醒事项')
+                  Image($r('app.media.startIcon')).width(18)
+                }.width('100%')
+                .justifyContent(FlexAlign.SpaceBetween)
+                .padding({ top: 16, bottom: 16 })
+                .onClick(()=>{
+                  this.vm.swiperController.changeIndex(1,true)
+                })
+
+                Row() {
+                  Text('提醒植物')
+                  Image($r('app.media.startIcon')).width(18)
+                }.width('100%')
+                .justifyContent(FlexAlign.SpaceBetween)
+                .padding({ top: 16, bottom: 16 })
+                .onClick(()=>{
+                  this.vm.swiperController.changeIndex(2,true)
+
+                })
+              }.backgroundColor('#F8F8F8')
+              .padding({left:10,right:10})
+              .borderRadius(12)
+
+              Column() {
+
+                Row() {
+                  Text('多久提醒一次')
+                  Image($r('app.media.startIcon')).width(18)
+                }.width('100%')
+                .justifyContent(FlexAlign.SpaceBetween)
+                .padding({ top: 16, bottom: 16 })
+                .onClick(()=>{
+                  this.vm.swiperController.changeIndex(3,true)
+                })
+
+                if(this.vm.frequency==DateFrequency.DAY){
+                  Row() {
+                    Text('时间')
+                    Image($r('app.media.startIcon')).width(18)
+                  }.width('100%')
+                  .justifyContent(FlexAlign.SpaceBetween)
+                  .padding({ top: 16, bottom: 16 })
+                  .onClick(()=>{
+                    this.vm.swiperController.changeIndex(4,true)
+                  })
+                }else{
+                  Row() {
+                    if(this.vm.frequency==DateFrequency.NONE){
+                      Text('日期')
+                    }else if(this.vm.frequency==DateFrequency.WEEK){
+                      Text('每周几提醒')
+                    }else if(this.vm.frequency==DateFrequency.MONTH){
+                      Text('每月几号提醒')
+                    }else{
+                      Text('间隔天数')
+                    }
+
+                    Image($r('app.media.startIcon')).width(18)
+                  }.width('100%')
+                  .justifyContent(FlexAlign.SpaceBetween)
+                  .padding({ top: 16, bottom: 16 })
+                  .onClick(()=>{
+                    this.vm.swiperController.changeIndex(4,true)
+                  })
+
+                  Row() {
+                    Text('时间')
+                    Image($r('app.media.startIcon')).width(18)
+                  }.width('100%')
+                  .justifyContent(FlexAlign.SpaceBetween)
+                  .padding({ top: 16, bottom: 16 })
+                  .onClick(()=>{
+                    this.vm.swiperController.changeIndex(5,true)
+                  })
+                }
+              }.backgroundColor('#F8F8F8')
+              .padding({left:10,right:10})
+              .borderRadius(12)
+              .onClick(()=>{
+                this.vm.swiperController.changeIndex(4,true)
+
+              })
+            }.width('100%')
+
+
+          }.width('100%')
+          .height(530)
+          .padding({top:16,left:16,right:16})
+          .backgroundColor(Color.White)
+          .borderRadius({topLeft:20,topRight:20})
+        }.width('100%').height('100%')
+        //打卡事项swiper
+        SwiperCom({
+          swiperBuilder1:()=>{
+            this.SelectRemindTask()
+          },
+          swiperBuilder2:()=>{this.CreateRemindTask()},
+          swiperBuilder3: () => {this.SelectRemindTaskIcon()},
+          swiperComController:this.vm.swiperComController[0]
+        })
+
+        SwiperCom({
+          swiperBuilder1:()=>{
+            //选择打卡植物
+            this.SelectRemindGreenPlant()
+          },
+          swiperComController:this.vm.swiperComController[1]
+        })
+        SwiperCom({
+          swiperBuilder1:()=>{
+            //选择打卡频率
+            this.SelectRemindFrequency()
+          },
+          swiperComController:this.vm.swiperComController[2]
+        })
+        if(this.vm.frequency==DateFrequency.DAY){
+          //如果时每天的话,那就只有一个时间
+          SwiperCom({
+            swiperBuilder1:()=>{
+              //时间
+              this.SelectRemindTime()
+            },
+            swiperComController:this.vm.swiperComController[3]
+          })
+        }else if(this.vm.frequency==DateFrequency.FREE){
+          //如果是自定义,第一行就是自定义
+          SwiperCom({
+            swiperBuilder1:()=>{
+              //自定义
+              //自定义
+              this.FreeDay()
+            },
+            swiperBuilder2:()=>{
+              //日期
+              this.SelectRemindDate()
+            },
+            swiperComController:this.vm.swiperComController[3]
+          })
+          //第二行就是时间
+          SwiperCom({
+            swiperBuilder1:()=>{
+              //时间
+              this.SelectRemindTime()
+            },
+            swiperComController:this.vm.swiperComController[4]
+          })
+
+
+        }else{
+
+          if(this.vm.frequency==DateFrequency.NONE){
+            SwiperCom({
+              swiperBuilder1:()=>{
+                this.SelectRemindDate()
+              },
+              swiperComController:this.vm.swiperComController[3]
+            })
+          }else if (this.vm.frequency==DateFrequency.WEEK){
+            SwiperCom({
+              swiperBuilder1:()=>{
+                //周
+                this.SelectRemindWeek()
+              },
+              swiperComController:this.vm.swiperComController[3]
+            })
+          }else if(this.vm.frequency==DateFrequency.MONTH){
+            SwiperCom({
+              swiperBuilder1:()=>{
+                //月
+                this.SelectRemindMonth()
+              },
+              swiperComController:this.vm.swiperComController[3]
+            })
+          }
+          SwiperCom({
+            swiperBuilder1:()=>{
+              //时间
+              this.SelectRemindTime()
+            },
+            swiperComController:this.vm.swiperComController[4]
+          })
+
+        }
+      }
+      .width('100%')
+      .height(530)
+      .autoPlay(false)
+      .indicator(false)
+      .disableSwipe(true)
+      .curve(Curve.EaseIn)
+      .duration(100)
+
+
+    }.width('100%').backgroundColor(Color.Transparent)
+
+  }
+  //选择提醒事项
+  @Builder
+  SelectRemindTask(){
+    Column({space:24}){
+      BuilderHeader({
+        leftTitle:'取消',
+        centerTitle:'选择提醒事项',
+        rightTitle:'确定',
+        leftClick:()=>{
+          //取消就返回到swiper[0]
+          this.vm.swiperController.changeIndex(0,true)
+        },
+        rightClick:()=>{
+          //确定也需要返回,不过打卡事项确定了
+          this.vm.swiperController.changeIndex(0,true)
+        }
+      })
+
+      Column({space:24}) {
+        Row() {
+          Text('基本事项')
+        }.width('100%')
+        .justifyContent(FlexAlign.Start)
+
+        Scroll() {
+          Grid() {
+            ForEach([1, 2, 3, 4, 5, 6,7,8,8,8], () => {
+              GridItem() {
+                Column({space:16}) {
+                  Image($r('app.media.startIcon')).width(45).height(45)
+                  Text('xxxx').fontSize(14)
+                }
+              }
+            })
+          }.height('100%').columnsTemplate('1fr 1fr 1fr').scrollBar(BarState.Off)
+        }.layoutWeight(1).scrollBar(BarState.Off)
+      }.height(300)
+
+      Column({space:24}) {
+        Row() {
+          Text('自定义')
+        }.width('100%')
+        .justifyContent(FlexAlign.Start)
+        Scroll() {
+          Grid() {
+            ForEach([1], () => {
+              GridItem() {
+                Column() {
+                  Image($r('app.media.startIcon')).width(45).height(45)
+                  Text('xxxx')
+                }.onClick(()=>{
+                  this.vm.swiperComController[0].changeIndex(1,true)
+                })
+              }
+            })
+          }.columnsTemplate('1fr 1fr 1fr')
+        }.layoutWeight(1).scrollBar(BarState.Off)
+      }.layoutWeight(1)
+
+
+
+
+    }.width('100%')
+    .height(530)
+    .padding({top:16,left:16,right:16})
+    .backgroundColor(Color.White)
+    .borderRadius({topLeft:20,topRight:20})
+  }
+
+  //创建事项
+  @Builder
+  CreateRemindTask(){
+    Column(){
+      Column(){
+
+        BuilderHeader({
+          leftTitle:'上一步',
+          centerTitle:'创建提醒事项',
+          rightTitle:'确定',
+          leftClick:()=>{
+            this.vm.swiperComController[0].changeIndex(0,true)
+          },
+          rightClick:()=>{
+            this.vm.swiperComController[0].changeIndex(0,true)
+            //确定之后也返回,创建打卡事项成功
+          }
+        })
+
+        Column(){
+
+        }.width(123)
+        .height(123)
+        .backgroundColor(Color.Green)
+        .onClick(()=>{
+          //选择图标
+          this.vm.swiperComController[0].changeIndex(2,true)
+        })
+      }.width('100%')
+      .height(530)
+      .padding({top:16,left:16,right:16})
+      .backgroundColor(Color.White)
+      .borderRadius({topLeft:20,topRight:20})
+    }.width('100%')
+    .height('100%')
+    .justifyContent(FlexAlign.Center)
+
+  }
+  @Builder
+  SelectRemindTaskIcon(){
+    Column(){
+      BuilderHeader({
+        leftTitle:'上一步',
+        centerTitle:'选择事项图标',
+        rightTitle:'确定',
+        leftClick:()=>{
+          this.vm.swiperComController[0].changeIndex(1,true)
+        },
+        rightClick:()=>{
+          this.vm.swiperComController[0].changeIndex(1,true)
+          //选择事项图标成功,返回
+        }
+      })
+      Column({space:24}) {
+        Scroll() {
+          Grid() {
+            ForEach([1,1,1,1,1,1,1,1,1,1,1,1,1], () => {
+              GridItem() {
+                Column() {
+                  Image($r('app.media.startIcon')).width(45).height(45)
+                  Text('xxxx')
+                }
+              }
+            })
+          }.columnsTemplate('1fr 1fr 1fr')
+        }.layoutWeight(1).scrollBar(BarState.Off)
+      }.layoutWeight(1)
+
+    }.width('100%')
+    .height(530)
+    .padding({top:16,left:16,right:16})
+    .backgroundColor(Color.White)
+    .borderRadius({topLeft:20,topRight:20})
+
+  }
+  @Builder
+  SelectRemindGreenPlant(){
+
+    Column(){
+
+      BuilderHeader({
+        leftTitle:'上一步',
+        centerTitle:'选择提醒植物',
+        rightTitle:'确定',
+        leftClick:()=>{
+          this.vm.swiperController.changeIndex(0,true)
+        },
+        rightClick:()=>{
+          this.vm.swiperController.changeIndex(0,true)
+          //选择植物成功,返回
+        }
+      })
+
+      Search({ value:"", placeholder: '搜索植物' })
+        .searchIcon({
+          src: $r('sys.media.ohos_ic_public_search_filled')
+        })
+        .cancelButton({
+          style: CancelButtonStyle.CONSTANT,
+          icon: {
+            src: $r('sys.media.ohos_ic_public_cancel_filled')
+          }
+        })
+        .width('100%')
+        .height(48)
+        .maxLength(20)
+        .border({
+          width:1,
+          color:"#1A000000"
+        })
+        .borderRadius(12)
+        .backgroundColor('#fff')
+        .placeholderColor(Color.Grey)
+        .placeholderFont({ size: 16, weight: 400 })
+        .textFont({ size: 16, weight: 400 })
+        .onSubmit((value: string) => {
+
+        })
+        .onChange((value: string) => {
+
+        })
+
+      Grid(){
+        ForEach([1,2,3,4,5,6],()=>{
+          GridItem(){
+            Column({space:9}){
+              Column(){
+                Image($r('app.media.app_icon')).width(63).height(92)
+
+              }.width(88)
+              .height(113)
+              .justifyContent(FlexAlign.Center)
+              .backgroundColor('#FFE8EBF0')
+              .borderRadius(12)
+              Text('龟背竹').fontSize(14)
+            }.width(107)
+            .height(155)
+            .justifyContent(FlexAlign.Center)
+            .border({
+              width:1,
+              color:'#FF206D43'
+            })
+            .borderRadius(12)
+            .backgroundColor(Color.White)
+          }
+        })
+
+
+
+      }.width('100%')
+      .layoutWeight(1)
+      .scrollBar(BarState.Off)
+      .columnsTemplate('1fr 1fr 1fr')
+      .rowsGap(10)
+
+
+
+
+
+    }.width('100%')
+    .height(530)
+    .padding({top:19,left:8,right:8})
+    .backgroundColor(Color.White)
+    .borderRadius({topLeft:20,topRight:20})
+
+  }
+  @Builder
+  SelectRemindFrequency(){
+    Column({space:24}){
+      BuilderHeader({
+        leftTitle:'上一步',
+        centerTitle:'提醒频率',
+        rightTitle:'确定',
+        leftClick:()=>{
+          this.vm.swiperController.changeIndex(0,true)
+        },
+        rightClick:()=>{
+          this.vm.swiperController.changeIndex(0,true)
+          //选择植物成功,返回
+          //应该再这里赋值的
+        }
+      })
+      Stack() {
+        Row(){}.width('100%').height(44).backgroundColor('#EAF3F2').borderRadius(12)
+        TextPicker({ range: this.frequencyList,columnWidths: [LengthMetrics.percent(100)]})
+          .width('100%')
+          .layoutWeight(1)
+          .selectedIndex(0)
+          .textStyle({
+            color:'#9C9898',
+            font:{size:16,weight:600}
+          })
+          .selectedTextStyle({
+            color:'#206D43',
+            font:{size:20,weight:600}
+          })
+          .borderRadius(0) //设置平角
+          .divider(null)
+          .gradientHeight(30)
+          .onChange((value,index)=>{
+            if(index==0){
+              this.vm.frequency=DateFrequency.NONE
+            }else if(index==1){
+              this.vm.frequency=DateFrequency.DAY
+            }else if(index==2){
+              this.vm.frequency=DateFrequency.WEEK
+            }else if(index==3){
+              this.vm.frequency=DateFrequency.MONTH
+            }else{
+              this.vm.frequency=DateFrequency.FREE
+            }
+
+          })
+
+      }.width('100%')
+    }.width('100%')
+    .height(530)
+    .padding({top:19,left:8,right:8})
+    .backgroundColor(Color.White)
+    .borderRadius({topLeft:20,topRight:20})
+  }
+
+  @Builder
+  SelectRemindTime(){
+    //时间
+    Column() {
+      DiaryTimePicker({
+        onCancel:()=>{
+          this.vm.swiperController.changeIndex(0,true)
+        },
+        onConfirm:()=>{
+          this.vm.swiperController.changeIndex(0,true)
+        }
+
+      })
+    }.width('100%')
+    .height(530)
+    .backgroundColor(Color.White)
+    .borderRadius({topLeft:20,topRight:20})
+
+  }
+  @Builder
+  SelectRemindDate(){
+    //日期
+    Column(){
+      DiaryDatePicker({
+        back:()=>{
+          this.vm.swiperController.changeIndex(0,true)
+
+        },
+        selectDateBack:(date: Date)=>{
+          //需要带参数确定
+          this.vm.swiperController.changeIndex(0,true)
+        }
+      })
+    }.width('100%')
+    .height(530)
+    .borderRadius({topLeft:20,topRight:20})
+  }
+  @Builder
+  SelectRemindWeek(){
+    //周
+    Column({space:24}){
+      BuilderHeader({
+        leftTitle:'上一步',
+        centerTitle:'选择时间',
+        rightTitle:'确定',
+        leftClick:()=>{
+          this.vm.swiperController.changeIndex(0,true)
+        },
+        rightClick:()=>{
+          this.vm.swiperController.changeIndex(0,true)
+          //选择植物成功,返回
+          //应该再这里赋值的
+        }
+      })
+      Stack() {
+        Row(){}.width('100%').height(44).backgroundColor('#EAF3F2').borderRadius(12)
+        TextPicker({ range:this.weekList ,columnWidths: [LengthMetrics.percent(100)]})
+          .width('100%')
+          .layoutWeight(1)
+          .selectedIndex(0)
+          .textStyle({
+            color:'#9C9898',
+            font:{size:16,weight:600}
+          })
+          .selectedTextStyle({
+            color:'#206D43',
+            font:{size:20,weight:600}
+          })
+          .borderRadius(0) //设置平角
+          .divider(null)
+          .gradientHeight(30)
+          .onChange((value,index)=>{
+          })
+
+      }.width('100%')
+    }.width('100%')
+    .height(350)
+    .padding({top:19,left:8,right:8})
+    .backgroundColor(Color.White)
+    .borderRadius({topLeft:20,topRight:20})
+  }
+  @Builder
+  SelectRemindMonth(){
+    //月
+    Column({space:24}){
+      BuilderHeader({
+        leftTitle:'上一步',
+        centerTitle:'选择时间',
+        rightTitle:'确定',
+        leftClick:()=>{
+          this.vm.swiperController.changeIndex(0,true)
+        },
+        rightClick:()=>{
+          this.vm.swiperController.changeIndex(0,true)
+          //选择植物成功,返回
+          //应该再这里赋值的
+        }
+      })
+      Stack() {
+        Row(){}.width('100%').height(44).backgroundColor('#EAF3F2').borderRadius(12)
+        TextPicker({ range: this.monthList,columnWidths: [LengthMetrics.percent(100)]})
+          .width('100%')
+          .layoutWeight(1)
+          .selectedIndex(0)
+          .textStyle({
+            color:'#9C9898',
+            font:{size:16,weight:600}
+          })
+          .selectedTextStyle({
+            color:'#206D43',
+            font:{size:20,weight:600}
+          })
+          .borderRadius(0) //设置平角
+          .divider(null)
+          .gradientHeight(30)
+          .onChange((value,index)=>{
+          })
+
+      }.width('100%')
+    }.width('100%')
+    .height(530)
+    .padding({top:19,left:8,right:8})
+    .backgroundColor(Color.White)
+    .borderRadius({topLeft:20,topRight:20})
+  }
+
+  @Builder
+  FreeDay(){
+    Column({space:24}){
+      BuilderHeader({
+        leftTitle:'上一步',
+        centerTitle:'自定义',
+        rightTitle:'确定',
+        leftClick:()=>{
+          this.vm.swiperController.changeIndex(0,true)
+        },
+        rightClick:()=>{
+          this.vm.swiperController.changeIndex(0,true)
+          //选择植物成功,返回
+          //应该再这里赋值的
+        }
+      })
+
+      Row({space:30}){
+        Text('自')
+        Text('2029-12-12')
+          .fontColor('#206D43')
+          .fontSize(20)
+          .fontWeight(500)
+          .backgroundColor('#EAF3F2')
+          .padding({left:14,right:14,top:13,bottom:13})
+          .borderRadius(20)
+          .onClick(()=>{
+            this.vm.swiperComController[3].changeIndex(1,true)
+          })
+        Text('起')
+
+      }.width('100%')
+      .justifyContent(FlexAlign.Center)
+      .margin({bottom:40})
+      Row({space:30}){
+        Text('每隔')
+        TextInput({text:"12"})
+          .width(80)
+          .maxLength(2)
+          .textAlign(TextAlign.Center)
+          .fontColor('#206D43')
+          .fontSize(20)
+          .fontWeight(500)
+          .backgroundColor('#EAF3F2')
+          .padding({left:14,right:14,top:13,bottom:13})
+          .borderRadius(20)
+          .onChange(()=>{
+            //
+          })
+        Text('天')
+
+      }.width('100%')
+      .justifyContent(FlexAlign.Center)
+
+
+    }.width('100%')
+    .height(530)
+    .padding({top:19,left:8,right:8})
+    .backgroundColor(Color.White)
+    .borderRadius({topLeft:20,topRight:20})
+  }
+
+
+
+}
+@Builder
+function EditGreenPlantBuilder() {
+  EditGreenPlantPage()
+}

+ 105 - 0
features/feature/src/main/ets/pages/GrowInfoPage.ets

@@ -0,0 +1,105 @@
+import { RouterPage, YTHeader } from 'basic'
+import { GrowInfo } from '../models/Second'
+import { SecondViewModel } from '../viewmodels/SecondViewModel'
+
+@ComponentV2
+@RouterPage
+struct GrowInfoPage {
+  @Local vm:SecondViewModel=new SecondViewModel()
+  @Local growInfoList:GrowInfo[]=[
+    {
+      text:"签到",
+      date:"2021.2.9",
+      value:'1'
+    },
+    {
+      text:"签到",
+      date:"2021.2.9",
+      value:'1'
+    },
+    {
+      text:"签到",
+      date:"2021.2.9",
+      value:'1'
+    },
+    {
+      text:"签到",
+      date:"2021.2.9",
+      value:'1'
+    },
+    {
+      text:"签到",
+      date:"2021.2.9",
+      value:'1'
+    },
+  ]
+  build() {
+    NavDestination(){
+      Column({space:35}){
+        YTHeader({title:'成长点明细查询'})
+        Text(this.vm.value.toString()).fontSize(40).fontWeight(500).fontColor('#333333')
+        //成长明细列表
+
+        Column(){
+          Row() {
+            Text('成长点明细')
+              .fontSize(25)
+              .fontColor('#206D43')
+            Row(){
+              Text('本月获取230')
+                .fontSize(10)
+                .fontColor('#9C9898')
+            }
+
+          }.width('100%')
+          .justifyContent(FlexAlign.SpaceBetween)
+          .padding({left:16,right:26})
+          .height(53)
+
+          List({space:9}){
+            ForEach(this.growInfoList,(item:GrowInfo,index:number)=>{
+              ListItem(){
+                Row({space:17}){
+                  Column({space:5}){
+                    Text(item.text).fontColor('#333333').fontWeight(500)
+                    Text(item.date).fontSize(12).fontColor('#9C9898')
+                  }.alignItems(HorizontalAlign.Start)
+
+                  Text('+'+item.value).fontColor('#206D43').fontWeight(500)
+                }.width('100%')
+                .height(70)
+                .justifyContent(FlexAlign.SpaceBetween)
+                .backgroundColor(Color.White)
+                .padding({left:13,right:13})
+                .borderRadius(12)
+
+              }
+            })
+          }.layoutWeight(1)
+          .scrollBar(BarState.Off)
+          .padding(6)
+          .align(Alignment.Top)
+
+
+        }.width('90%')
+        .borderRadius({topLeft:20,topRight:20})
+        .backgroundColor('#F8F8F8')
+      }
+      .width('100%')
+      .height('100%')
+      .linearGradient({
+        angle:180,
+        colors:[
+          ['#FEFFFF',-0.2],
+          ['#7CBE9A',1]
+        ]
+      })
+    }
+    .hideTitleBar(true)
+  }
+}
+
+@Builder
+function GrowInfoBuilder() {
+  GrowInfoPage()
+}

+ 535 - 0
features/feature/src/main/ets/pages/IncreaseDiaryPage.ets

@@ -0,0 +1,535 @@
+import { IBestToast, RouterPage, YTAvoid, yTRouter, yTToast } from 'basic';
+import { photoAccessHelper } from '@kit.MediaLibraryKit';
+import { Context } from '@ohos.abilityAccessCtrl';
+import { DiaryData, PageStatus, Variable } from '../models';
+import { DiaryDatePicker } from '../components/fourcomponent/DiaryDatePicker';
+import { DiaryTimePicker } from '../components/fourcomponent/DiaryTimePicker';
+import { DateUtils } from '../utils/DateUtils';
+import { DiaryViewModel } from '../view/DiaryViewModel';
+import { RecodeViewModel } from '../view/RecodeViewModel';
+
+/**
+ * 新增/编辑 日记
+ */
+@RouterPage
+@Component
+struct IncreaseDiaryPage {
+  @StorageProp(YTAvoid.SAFE_TOP_KEY) safeTop: number = 0
+  // 页面编辑中的状态 - 默认为可编辑
+  @State pageReadOnly: boolean = false
+  // 时间选择器 开启控制
+  @State showTimePicker: boolean = false
+  // 日期选择器 开启控制
+  @State showDatePicker: boolean = false
+  // 日记详细数据
+  @State diaryData: DiaryData = {};
+  // 页面状态, 默认为日记
+  @State pageStatus: PageStatus = PageStatus.DIARY
+
+  // private linearInfo: LinearGradientOptions = {
+  //   colors: [ ['#B9FD2A', 0.01], ['#F5FD6D', 1] ],
+  //   angle: 150
+  // }
+  private conText: Context = this.getUIContext().getHostContext() as Context
+
+  /**
+   * 选择图片
+   */
+  async photoSelect(){
+    let PhotoSelectOptions = new photoAccessHelper.PhotoSelectOptions();
+    PhotoSelectOptions.MIMEType = photoAccessHelper.PhotoViewMIMETypes.IMAGE_TYPE;
+    PhotoSelectOptions.maxSelectNumber = 1;
+    let photoPicker = new photoAccessHelper.PhotoViewPicker();
+
+    let photoSelectResult: photoAccessHelper.PhotoSelectResult = await photoPicker.select(PhotoSelectOptions);
+    let photoList = photoSelectResult.photoUris;
+    if (photoList.length > 0) {
+      if(!this.diaryData.imageUrls) this.diaryData.imageUrls = [];
+      this.diaryData.imageUrls = [...this.diaryData.imageUrls, ...photoList];
+    }
+  }
+
+  /**
+   * 点击 完成 按钮
+   */
+  async onComplete() {
+    if(this.pageReadOnly) {
+      this.pageReadOnly = false;
+      Variable.pageReadOnly = false
+      return;
+    }
+
+    if(!this.diaryData.title || !this.diaryData.content) {
+      IBestToast.show({ message: '请填写标题和内容' })
+      return;
+    }
+
+    // 浅拷贝
+    let diaryData = JSON.parse(JSON.stringify(this.diaryData)) as DiaryData
+    // 统一时间格式
+
+    // 图片上传逻辑
+    if (diaryData.imageUrls && diaryData.imageUrls.length != 0) {
+      console.log("图片上传中" + JSON.stringify(diaryData.imageUrls))
+
+      // 使用map创建Promise数组,然后用Promise.all等待所有上传完成
+      const uploadPromises = diaryData.imageUrls?.map(async (url: string) => {
+        if(url?.split(':')?.[0] === 'file') {
+          console.log("开始上传图片 " + url)
+          let _url = await DiaryViewModel.uploadImage(this.conText, url)
+          return _url
+        }
+        return url
+      })
+
+      // 等待所有上传完成
+      const imageUrl = await Promise.all(uploadPromises)
+      console.log("图片上传结果" + JSON.stringify(imageUrl))
+
+      // 将处理后的URL赋值回diaryData
+      diaryData.imageUrls = imageUrl
+    }
+
+
+    // 判断是否是新增日记 - 有 id 时为 修改日记
+    if(!this.diaryData.id) {
+      diaryData.diaryDate += ':00'
+      this.onSubmit(diaryData)
+    } else {
+      this.onUpdate(diaryData)
+    }
+  }
+
+  // 新建 日记、小记录
+  async onSubmit(data: DiaryData) {
+    let ans: boolean = false
+    console.log("保存")
+
+    if(this.pageStatus === PageStatus.DIARY) {
+      // ans = await DiaryViewModel.saveDiaryLog(data)
+      console.log("日记-保存结果" + JSON.stringify(ans))
+    } else {
+      data.noteTime = data.diaryDate
+      // ans = await RecodeViewModel.saveNote(data)
+      console.log("小记录-保存结果" + JSON.stringify(ans))
+    }
+
+    if(ans) {
+      IBestToast.show({ message: '保存成功' })
+      yTRouter.routerBack()
+    } else {
+      IBestToast.show({ message: '保存失败' })
+    }
+  }
+
+  // 修改日记、小记录
+  async onUpdate(data: DiaryData) {
+    let ans: boolean = false
+    console.log("修改")
+    if(this.pageStatus === PageStatus.DIARY) {
+      let time = DateUtils.formatDateToCustomString(new Date()).split(' ')[1]
+      data.diaryDate = data.diaryDate?.split(' ')[0] + ' ' +time
+      // ans = await DiaryViewModel.updateDiaryLog(data)
+      console.log("日记-修改结果" + ans)
+    } else {
+      data.noteTime = data.diaryDate + ':00'
+      // ans = await RecodeViewModel.updateNote(data)
+      console.log("小记录-修改结果" + JSON.stringify(ans))
+    }
+
+    if(ans) {
+      IBestToast.show({ message: '保存成功' })
+      yTRouter.routerBack()
+    } else {
+      IBestToast.show({ message: '保存失败' })
+    }
+  }
+
+  /**
+   * 清空相册
+   */
+  clearPhoto() {
+    this.diaryData.imageUrls = []
+  }
+
+  /**
+   * 删除图片
+   * @param index
+   */
+  delPhotoItem(index: number){
+    let temp = [...this.diaryData.imageUrls!]
+    temp?.splice(index, 1)
+    this.diaryData.imageUrls = temp
+    console.log("点击了删除" + JSON.stringify(this.diaryData.imageUrls))
+  }
+
+  /**
+   * 重写返回逻辑 - 拦截返回手势
+   * @returns
+   */
+  onRouterBack(): boolean {
+    if(!Variable.pageReadOnly) {
+      yTToast.doubleConfirm({
+        text: "是否确认退出编辑",
+        click: async () => {
+          yTToast.hide()
+          yTRouter.routerBack()
+        }
+      })
+    } else {
+      yTRouter.routerBack()
+    }
+    return true;
+  }
+
+  // 路由参数解析
+  async getRouterParams(){
+    // 获取路由参数
+    const params = yTRouter.getParamByName("IncreaseDiaryPage").pop() as Record<string, boolean | number>;
+
+    // 获取参数
+    this.pageStatus = (params?.PageStatus ?? PageStatus.DIARY) as PageStatus
+
+    let date = (params?.nowDate ?? -1)as number
+
+    if(date != -1){
+      this.diaryData.diaryDate = DateUtils.formatDateToCustomString(new Date(date), true, false)
+      console.log("参数" + this.diaryData.diaryDate)
+    }
+
+    // 获取参数
+    let id = (params?.id ?? -1) as number;
+    if (id != -1) {
+      this.pageReadOnly = true
+      Variable.pageReadOnly = true
+      if(this.pageStatus == PageStatus.DIARY) {
+        // this.diaryData = await DiaryViewModel.queryDiaryLogById(id)
+      } else {
+        // this.diaryData = await RecodeViewModel.queryNoteById(id)
+        this.diaryData.diaryDate = this.diaryData.noteTime
+      }
+      try{
+        let time = this.diaryData.diaryDate?.split(' ')?.[1]
+        let time1 = time?.split(':')
+        time1?.pop()
+        this.diaryData.diaryDate = this.diaryData.diaryDate?.split(' ')?.[0] + ' ' + time1?.join(':')
+      } catch (e){
+        console.log("时间解析错误")
+      }
+    }
+  }
+
+  async aboutToAppear(): Promise<void> {
+    this.diaryData.diaryDate = DateUtils.formatDateToCustomString(new Date(), true, false)
+    this.getRouterParams()
+  }
+
+  build() {
+    NavDestination() {
+      Column() {
+        // 标题区
+        Stack({alignContent: Alignment.Center}) {
+          Row(){
+            Image($r("app.media.close"))
+              .width(20)
+              .aspectRatio(1)
+              .onClick(this.onRouterBack)
+
+            Text(this.pageReadOnly ? "编辑" : "完成")
+              .fontSize(14)
+              .fontWeight(500)
+              .borderRadius(16)
+              .backgroundColor(Color.White)
+              .onClick(() => {
+                this.onComplete()
+              })
+          }
+          .width("100%")
+          .justifyContent(FlexAlign.SpaceBetween)
+          // 日期选择
+          Row({space:10}){
+            Row({space: 8}){
+              Text(this.diaryData.diaryDate?.split(' ')[0])
+                .fontSize(16)
+                .fontWeight(600)
+
+              Image($r('app.media.Diary_DateOpen'))
+                .width(14)
+                .height(8)
+            }
+            .onClick(() => {
+              if(!this.pageReadOnly){
+                this.showDatePicker = true
+              }
+            })
+
+            // 时间选择
+            Row({space: 8}){
+              if(this.pageStatus == PageStatus.RECODE) {
+                Text(this.diaryData.diaryDate?.split(' ')[1])
+                  .fontSize(16)
+                  .fontWeight(600)
+
+                Image($r('app.media.Diary_DateOpen'))
+                  .width(14)
+                  .height(8)
+              }
+            }
+            .onClick(() => {
+              if(!this.pageReadOnly) {
+                this.showTimePicker = true
+              }
+            })
+          }
+        }
+        .width("100%")
+        .padding({ top: this.safeTop + 5, left: 20, right: 20})
+        .margin({bottom:25}) //30=5+25
+
+        // 内容区
+        Column() {
+            // 主要内容
+            Column(){
+              // 标题栏
+              Row() {
+                if(!this.pageReadOnly) {
+                  TextInput({ text: $$this.diaryData.title, placeholder: "输入标题会更受欢迎!" })
+                    .padding(0)
+                    .fontSize(16)
+                    .fontWeight(500)
+                    .maxLength(20)
+                    .height('100%')
+                    .layoutWeight(1)
+                    .borderRadius(0)
+                    .placeholderColor("#BFBFBF")
+                    .backgroundColor(Color.Transparent)
+                    .caretColor('app.color.main_ac_color_dark')
+                    .placeholderFont({ size: 14 })
+                } else {
+                  Text(this.diaryData.title)
+                    .fontSize(16)
+                    .fontWeight(500)
+                    .layoutWeight(1)
+                }
+
+
+                Row(){
+                  if(this.diaryData.title && !this.pageReadOnly){
+                    Image($r('app.media.Diary_close'))
+                      .width(24)
+                      .height(24)
+                      .borderRadius(12)
+                      .onClick(() => {
+                        this.diaryData.title = ''
+                      })
+                  }
+                }
+                .width(24)
+                .margin({right: 15})
+
+                Text(`${20 - (this.diaryData.title ? this.diaryData.title.length : 0) }`)
+                  .fontColor("#BFBFBF")
+              }
+              .height(50)
+              .border({
+                width: {
+                  bottom: 0.1
+                },
+                color: 20 - (this.diaryData.title ? this.diaryData.title.length : 0) === 0 ? Color.Red : "#BFBFBF"
+              })
+
+              // 内容栏
+              List(){
+                ListItem(){
+                  if(!this.pageReadOnly) {
+                    TextArea({ text: $$this.diaryData.content, placeholder: "记录此刻" })
+                      .padding(0)
+                      .fontSize(14)
+                      .width("100%")
+                      .height("100%")
+                      .borderRadius(0)
+                      .fontWeight(400)
+                      .placeholderColor("#BFBFBF")
+                      .placeholderFont({ size: 16 })
+                      .backgroundColor(Color.Transparent)
+                      .caretColor('app.color.main_ac_color_dark')
+                  } else {
+                    Text(this.diaryData.content)
+                      .width("100%")
+                      .fontSize(14)
+                      .fontWeight(400)
+                  }
+                }
+              }
+              .padding({top: 12})
+              .layoutWeight(1)
+              .width("100%")
+              .scrollBar(BarState.Off)
+
+              Column({space: 32}){
+                // 图片显示器
+                Scroll(){
+                  Row({space: 5}){
+                    ForEach(this.diaryData.imageUrls, (item: string, index: number) => {
+                      Stack({alignContent: Alignment.TopEnd}){
+                        Image(item)
+                          .width(100)
+                          .height(108)
+                        if(!this.pageReadOnly) {
+                          Image($r('app.media.Diary_close'))
+                            .width(24)
+                            .aspectRatio(1)
+                            .offset({
+                              x: -2, y: -2
+                            })
+                            .onClick(() => {
+                              this.delPhotoItem(index)
+                            })
+                        }
+                      }
+                    })
+                  }
+                }
+                .height(108)
+                .scrollable(ScrollDirection.Horizontal)
+                .align(Alignment.TopStart)
+
+                // 图片选择器
+                Row(){
+                  // 清空
+                  Row(){
+                    if(!this.pageReadOnly){
+                      Text('清空')
+                        .fontSize(18)
+                        .fontWeight(400)
+                        .fontColor('#979797')
+                    }
+                  }
+                  .borderRadius(20)
+                  .backgroundColor('#F0F0F0')
+                  .alignItems(VerticalAlign.Center)
+                  .justifyContent(FlexAlign.Center)
+                  .padding({ top: 6, right: 18, bottom: 6, left: 18})
+                  .onClick(() => {
+                    this.diaryData.content = ''
+                  })
+
+                  // 相册
+                  Row({space: 5}){
+                    Image($r('app.media.photoAlbum'))
+                      .width(20)
+                      .aspectRatio(1)
+
+                    Text("相册")
+                      .fontSize(18)
+                      .fontWeight(500)
+                  }
+                  .borderRadius(18)
+                  // .linearGradient(this.linearInfo)
+                  .padding({ top: 12, right: 16, bottom: 12, left: 16})
+                  .onClick(()=>{
+                    if(!this.pageReadOnly) {
+                      this.photoSelect()
+                    }
+                  })
+                }
+                .width("100%")
+                .alignItems(VerticalAlign.Center)
+                .justifyContent(FlexAlign.SpaceBetween)
+              }
+              .padding({bottom: 64})
+            }
+            .width("100%")
+            .height("100%")
+        }
+        .width("100%")
+        .layoutWeight(1)
+        .alignItems(HorizontalAlign.Start)
+        .justifyContent(FlexAlign.Start)
+        .padding({ left: 20, right: 20 })
+        .bindSheet($$this.showTimePicker,this.TimePickerBuilder(),{
+          width:'100%',
+          height:400,
+          showClose:false
+
+        })
+      }
+      .width("100%")
+      .height("100%")
+      .bindSheet($$this.showDatePicker,this.DatePickerBuilder(),{
+        width:'100%',
+        height:300,
+        showClose:false
+
+      })
+
+
+      // .linearGradient(this.linearInfo)
+    }
+    .hideTitleBar(true)
+    .onBackPressed(() => {
+      return this.onRouterBack()
+    })
+  }
+  @Builder
+  DatePickerBuilder(){
+    // if(this.showDatePicker) {
+    //   Column(){
+        DiaryDatePicker({
+          selectedDate: new Date(this.diaryData.diaryDate ?? new Date().toISOString()),
+          selectDateBack: (date: Date) => {
+            this.showDatePicker = false
+            let result = DateUtils.formatDateToCustomString(date, false)
+            console.log("选择的日期" + result)
+            try {
+              let temp = this.diaryData.diaryDate?.split(' ')[1]
+              this.diaryData.diaryDate = result + ' ' + temp
+            } catch (e) {
+
+            }
+          }
+        })
+          .width("100%")
+          .height('100%')
+      // }
+      // .width("100%")
+      // .height("100%")
+      // .alignItems(HorizontalAlign.Start)
+      // .justifyContent(FlexAlign.Start)
+      // .onClick(() => {
+      //   this.showDatePicker = false
+      // })
+
+    }
+
+  // }
+  @Builder
+  TimePickerBuilder(){
+    // if(this.showTimePicker){
+      Column(){
+        DiaryTimePicker({
+          timeStr: (this.diaryData.diaryDate ?? DateUtils.formatDateToCustomString(new Date(), true)).split(' ')[1],
+          onConfirm: (time: string) => {
+            this.showTimePicker = false
+            console.log("选择的时间 " + time)
+            this.diaryData.diaryDate = this.diaryData.diaryDate?.split(' ')[0] + ' ' + time
+          }
+        })
+      }
+      .width("100%")
+      .height("100%")
+      .alignItems(HorizontalAlign.End)
+      .justifyContent(FlexAlign.Start)
+      .onClick(() => {
+        this.showTimePicker = false
+      })
+    }
+
+  // }
+
+}
+
+@Builder
+function IncreaseDiaryBuilder() {
+  IncreaseDiaryPage()
+}

+ 138 - 0
features/feature/src/main/ets/utils/DateUtils.ets

@@ -0,0 +1,138 @@
+import { DateInfo } from "../models/DateInfo";
+
+// 星期中文映射表
+export const WEEK_MAP = ['日', '一', '二', '三', '四', '五', '六'];
+
+
+
+export class DateUtils {
+  /**
+   * 格式化日期对象为自定义字符串
+   * @param date 日期对象
+   * @param needTime 是否需要时间 ( 时、分、秒 )
+   * @param needSecond 是否需要秒
+   * @returns
+   */
+  static formatDateToCustomString(date: Date, needTime: boolean = true, needSecond: boolean = true): string {
+    // 转换为 YY-MM-DD HH:mm:ss 格式
+    const year = date.getFullYear().toString();
+    const month = (date.getMonth() + 1).toString().padStart(2, '0');
+    const day = date.getDate().toString().padStart(2, '0');
+    const hours = date.getHours().toString().padStart(2, '0');
+    const minutes = date.getMinutes().toString().padStart(2, '0');
+    const seconds = date.getSeconds().toString().padStart(2, '0');
+
+    const result = `${year}-${month}-${day}` + (needTime ? ` ${hours}:${minutes}` + (needSecond ? `:${seconds}` : '') : '');
+    return result;
+  }
+
+  /**
+   * 获取指定月份的天数
+   * @param year 年
+   * @param month 月份
+   * @returns 当月的天数
+   */
+  static getDaysInMonth(year: number, month: number): number {
+    return new Date(year, month, 0).getDate();
+  }
+
+  /**
+   * 判断两个 Date 对象是否为同一天
+   * @param date1
+   * @param date2
+   * @returns
+   */
+  static isSameDay(date1: Date, date2: Date): boolean {
+    return (
+      date1.getFullYear() === date2.getFullYear() &&
+      date1.getMonth() === date2.getMonth() &&
+      date1.getDate() === date2.getDate()
+    );
+  }
+
+  /**
+   * 生成从指定日期开始向前的连续日期数组
+   * @param startDate 起始日期(默认当前日期)
+   * @param count 生成的日期数量(默认7天)
+   * @returns 日期对象数组
+   */
+  static generateForwardDateArray(
+    startDate: Date = new Date(),
+    count: number = 7
+  ): DateInfo[] {
+    const dateArray: DateInfo[] = [];
+
+    // 复制起始日期,避免修改原对象
+    const currentDate = new Date(startDate);
+
+    for (let i = 0; i < count; i++) {
+      // 添加日期信息到数组
+      dateArray.push(DateUtils.createDateInfo(currentDate));
+
+      // 日期减1天(向前)
+      currentDate.setDate(currentDate.getDate() - 1);
+    }
+
+    return dateArray;
+  }
+
+  /**
+   * 生成从指定日期开始向后的连续日期数组,可以包含今天但不能超过今天
+   * @param startDate 起始日期(默认当前日期)
+   * @param count 生成的日期数量(默认7天)
+   * @returns 日期对象数组,包含今天但不包含超过今天的日期
+   */
+  static generateBackwardDateArray(
+    startDate: Date = new Date(),
+    count: number = 7,
+    isCheck: boolean = true
+  ): DateInfo[] {
+    const dateArray: DateInfo[] = [];
+
+    // 复制起始日期,避免修改原对象
+    const currentDate = new Date(startDate);
+
+    // 获取今天的日期
+    // 获取今天的日期并设置时间为23:59:59:999,便于比较
+    const today = new Date();
+    today.setHours(0, 0, 0, 0);
+    today.setDate(today.getDate() + 1);
+    today.setTime(today.getTime() - 1); // 设置为今天的最后一毫秒
+
+    for (let i = 0; i < count; i++) {
+      // 检查当前日期是否超过今天
+      if (isCheck && currentDate > today) {
+        break;
+      }
+
+      // 添加日期信息到数组
+      dateArray.push(DateUtils.createDateInfo(currentDate));
+
+      // 日期加1天(向后)
+      currentDate.setDate(currentDate.getDate() + 1);
+    }
+
+    return dateArray;
+  }
+
+  /**
+   * 创建一个日期信息对象
+   * @param date 日期对象
+   * @returns DateInfo 对象
+   */
+  static createDateInfo(date: Date): DateInfo {
+    const year = date.getFullYear();
+    const month = date.getMonth() + 1;
+    const day = date.getDate();
+    const week = WEEK_MAP[date.getDay()];
+
+    return {
+      year: year,
+      month: month,
+      day: day,
+      week: week,
+      id: new Date(date)
+    };
+  }
+}
+

+ 146 - 0
features/feature/src/main/ets/view/DiaryViewModel.ets

@@ -0,0 +1,146 @@
+import { YTLog, YTUserRequest } from "basic"
+import { DiaryData } from "../models"
+import { util } from "@kit.ArkTS"
+import { fileIo as fs } from "@kit.CoreFileKit"
+import { image } from "@kit.ImageKit"
+import { faceDetector } from "@kit.CoreVisionKit"
+
+
+export class DiaryViewModel{
+  // 日记列表
+  diaryDataList: DiaryData[] = []
+  // 时间列表
+  dateList: string[] = []
+  // 列表控制器
+  scroller: ListScroller = new ListScroller()
+
+  /**
+   * 删除日记
+   * @param id 日记 id
+   */
+  async deleteDiaryLog(id: number) {
+    // const result = await DiaryApi.deleteDiaryLog(id)
+    // YTLog.info(`删除日记结果 ${result}`)
+    // return result
+  }
+
+  /**
+   * 查询日记列表
+   * @param nowTime 当前选中时间
+   * @returns 日记列表
+   */
+  async queryDiaryLogList(nowTime: string){
+    // const result: DiaryData[] = await DiaryApi.queryDiaryLogList(nowTime)
+    // YTLog.info(`查询日记列表结果 ${JSON.stringify(result)}`)
+    // this.diaryDataList = result
+    //
+    // let dateList: string[] = [result[0].diaryDate!]
+    // result.forEach(item => {
+    //   if(dateList.indexOf(item.diaryDate!) === -1){
+    //     dateList.push(item.diaryDate!)
+    //   }
+    // })
+    // this.dateList = dateList
+    // console.log('title_List ' + JSON.stringify(this.dateList))
+  }
+
+  /**
+   * 日记搜索
+   * @param keyWord 日记标题关键字
+   * @returns
+   */
+  // static async diaryLogSearch(keyWord: string): Promise<DiaryData[]> {
+  //   // let encode = encodeURIComponent(keyWord)
+  //   // const result: DiaryData[] = await DiaryApi.diaryLogSearch(encode)
+  //   // YTLog.info(`查询日记搜索结果 ${JSON.stringify(result)}`)
+  //   // return await result as DiaryData[]
+  // }
+
+  /**
+   * 修改日记
+   * @param params 日记数据结构
+   * @returns
+   */
+  static async updateDiaryLog(params: DiaryData) {
+    let ans = params.diaryDate?.split(' ')[1]
+    if(!ans) {
+      params.diaryDate += ' 00:00:01'
+    }
+    // const result = await DiaryApi.updateDiaryLog(params)
+    // YTLog.info(`修改日记结果 ${result}`)
+    // return result
+  }
+
+  /**
+   * 查询日记详情
+   * @param id
+   * @returns
+   */
+  static async queryDiaryLogById(id: number) {
+    // const result: DiaryData = await DiaryApi.queryDiaryLogById(id)
+    // YTLog.info(`查询日记结果 ${JSON.stringify(result)}`)
+    // return result
+  }
+
+  /**
+   * 新增日记
+   * @param params 日记数据结构
+   * @returns
+   */
+  static async saveDiaryLog(params: DiaryData) {
+    // const result = await DiaryApi.saveDiaryLog(params)
+    // YTLog.info(`新增日记结果 ${result}`)
+    // return result
+  }
+
+  // 上传图片
+  static async uploadImage(conText: Context, filePath: string) {
+    const promise = new Promise<string>(async (resolve, reject) => {
+      let uri = DiaryViewModel.copyToSync(conText, filePath) as string
+      uri = await DiaryViewModel.manualCompression(uri, conText)
+      console.log("uri " + uri)
+      YTUserRequest.uploadUserFile(conText, uri, (url) => {
+        resolve(url)
+      })
+    })
+    const url = await promise
+    return url
+  }
+
+  // 图片处理
+  static copyToSync(conText: Context, uri: string) {
+    // 切割图片路径
+    let temp: string[] = uri.split("/")
+
+    // 使用时间戳拼接文件名 ( 仅仅是为了获取文件后缀名 )
+    let fileName: string = Date.now() + "." + temp[temp.length-1].split(".")[1]
+
+    // 根据上下文对象获取 cache 文件的路径,将其于 filename 进行拼接
+    let filePath: string = conText.cacheDir + "/" + fileName
+
+    // 获取图片路径的文件指针,模式设置为只读
+    const file = fs.openSync(uri, fs.OpenMode.READ_ONLY)
+
+    // 将文件拷贝至 cache 的路径
+    fs.copyFileSync(file.fd, filePath)
+
+    // 需要拿到复制到 Cache 中的文件名
+    return filePath;
+  }
+
+  /**
+   * 手动压缩图片
+   */
+  static async manualCompression(filePath: string, context: Context) {
+    const imageSourceApi: image.ImageSource = image.createImageSource(filePath);
+    let packOpts: image.PackingOption = { format: "image/jpeg", quality: 20 };
+    const imagePackerApi = image.createImagePacker()
+    const buffer = await imagePackerApi.packing(imageSourceApi, packOpts)
+    const imagePath = context.cacheDir + '/' + util.generateRandomUUID() + '.jpeg'
+    const file = fs.openSync(imagePath, fs.OpenMode.CREATE | fs.OpenMode.READ_WRITE)
+    fs.writeSync(file.fd, buffer)
+    fs.closeSync(file)
+    fs.unlinkSync(filePath)
+    return imagePath
+  }
+}

+ 478 - 0
features/feature/src/main/ets/view/FourView.ets

@@ -0,0 +1,478 @@
+import { IBestToast, userInfo, UserInfo, YTAvoid, yTRouter } from 'basic'
+import { DateInfo } from '../models/DateInfo'
+import { DateUtils } from '../utils/DateUtils'
+import { DiaryData, PageStatus } from '../models'
+import { DiaryTimePicker } from '../components/fourcomponent/DiaryTimePicker'
+import { DiaryDatePicker } from '../components/fourcomponent/DiaryDatePicker'
+import { RecodeViewModel } from './RecodeViewModel'
+
+/**
+ * 记录页面
+ */
+@Component
+export struct FourView {
+  @StorageProp(YTAvoid.SAFE_BOTTOM_KEY) bottom: number = 0
+  @StorageProp(YTAvoid.SAFE_TOP_KEY) safeTop: number = 0
+  @State Vm: RecodeViewModel = new RecodeViewModel()
+  @State heightList: number[] = []
+  // 去登录界面
+  @State ShowLoginDialog: boolean = false
+
+
+  private linearInfo: LinearGradientOptions = {
+    colors: [['#EAF3F2',1]],
+    angle: 110
+  }
+
+  //点击日期,刷新数据
+  selectDateChange = (index: number) => {
+    this.Vm.selectedDate = index
+    this.Vm.changeDataByIndex()
+    console.log('改变了选择的日期')
+  }
+  // 加载小记录数据列表
+  async loadDataList(targetDate: string) {
+      this.Vm.queryNoteList(targetDate)
+      this.ShowLoginDialog = true
+  }
+
+  /**
+   * 更新小记录时间
+   * @param index
+   * @param time
+   */
+  async updateNoteTime(index: number, time: string) {
+    let currentNote: DiaryData = this.Vm.recodeList[index]
+    currentNote.noteTime = currentNote.noteTime?.split(' ')[0] + ' ' + time + ':00'
+    let ans = await this.Vm.updateNoteTime(currentNote)
+    if(ans) {
+      //TODO:请求后端刷新数据
+      // this.Vm.changeDataByIndex()
+      IBestToast.show('更改成功')
+    } else {
+      IBestToast.show('更改失败')
+    }
+  }
+
+  /**
+   * 跳转至添加小记录页面
+   * @param id
+   */
+  routerAddNote(id?: number) {
+    // 产品要求:
+    // 1. 日期需要和上一级页面选择的日期保持一致。
+    let date: string = this.Vm.getSelectedDate().split(' ')[0]
+    // 2. 时间需要和当前时间保持一致。
+    let time: string = DateUtils.formatDateToCustomString(new Date(), true, false).split(' ')[1]
+    let ans: string = date + ' ' + time
+
+    yTRouter.pushPathByName("IncreaseDiaryPage", {
+      'id': id,
+      'PageStatus': PageStatus.RECODE,
+      'nowDate': new Date(ans).getTime(),
+    } as Record<string, boolean | number | string>);
+  }
+
+  aboutToAppear(): void {
+    this.Vm.selectedDateChange = this.selectDateChange
+    this.loadDataList(DateUtils.formatDateToCustomString(new Date(), false))
+  }
+
+  build() {
+    Stack(){
+      Column(){
+        Row(){
+          Image($r("app.media.RecodeTitle"))
+            .width(140)
+            .height(44)
+
+          Image($r("app.media.calendar"))
+            .width(30)
+            .aspectRatio(1)
+            .onClick(() => {
+              animateToImmediately({
+                duration: 200
+              }, () => {
+                if(this.Vm.showDatePicker) {
+                  this.Vm.showDatePicker = false
+                } else {
+                  this.Vm.showDatePicker = true
+                  this.Vm.showTimePicker = -1
+                }
+              })
+            })
+        }
+        .width("100%")
+        .height(76)
+        .justifyContent(FlexAlign.SpaceBetween)
+        .alignItems(VerticalAlign.Center)
+        .padding({ left: 17, right: 17, bottom: 17, top: 17})
+        .onClick(() => {
+          this.Vm.showTimePicker = -1
+          this.Vm.showDatePicker = false
+        })
+
+        // 时间选择器 - 使用区域变换实现
+        if(this.Vm.showTimePicker != -1) {
+          DiaryTimePicker({
+            timeStr: this.Vm.getTime(this.Vm.showTimePicker),
+            onConfirm: (time: string) => {
+              this.updateNoteTime(this.Vm.showTimePicker, time)
+              this.Vm.showTimePicker = -1
+            },
+            onCancel: () => {
+              this.Vm.showTimePicker = -1
+            }
+          })
+            .position({
+              // x: 5,
+              // y: 35
+              x: this.Vm.getPostion('x'),
+              y: this.Vm.getPostion('y')
+            })
+            .zIndex(100)
+        }
+
+        // 主体内容
+        Stack({alignContent: Alignment.TopEnd}){
+          Column(){
+            // 日期选择
+            Swiper(this.Vm.swiperController){
+              LazyForEach(this.Vm.weekLoop, (item: DateInfo, index: number) => {
+                Column({space: 2}) {
+                  Column({space: 15}){
+                    Text(item.week)
+                    // ${item.month}-
+                    Text(`${item.day}`)
+                  }
+                  .width("100%")
+                  .padding({ top: 5, bottom: 5 })
+                  .borderRadius(10)
+                  .linearGradient(this.Vm.selectedDate === index ? this.linearInfo : null)
+
+                  // TODO 表示某天有数据 - 暂无接口,待定
+                  if(false) {
+                    Row()
+                      .width(6)
+                      .height(6)
+                      .borderRadius(3)
+                      .backgroundColor('#BAFE2B')
+                  }
+                }
+                .width(50)
+                .height(80)
+                .padding({
+                  left: 7,
+                  right: 7,
+                  top: 9,
+                })
+                .onClick(() => {
+                  this.selectDateChange(index)
+                })
+              }, (item: DateInfo, index: number) => { return item.id.toString() })
+            }
+            .loop(false)
+            .displayCount(7)
+            .indicator(false)
+            .direction(Direction.Rtl)
+            .onChange((index: number) => {
+              this.Vm.swiperOnChange(index)
+            })
+
+            // 记录内容主体
+            Stack({alignContent: Alignment.BottomEnd}){
+              List({space: 10}) {
+                ListItem()
+                  .height(20)
+                  .onClick(() => {
+                    this.Vm.showTimePicker = -1
+                    this.Vm.showDatePicker = false
+                  })
+
+                ForEach(this.Vm.recodeList, (item: DiaryData, index: number) => {
+                  ListItem(){
+                    Row({space: 20}){
+                      // 时间 和 分隔线
+                      Column({space: 5}){
+                        Row(){
+                          Text(this.Vm.getTime(index))
+                            .fontSize(14)
+                            .padding({
+                              top: 5,
+                              left: 8,
+                              right: 8,
+                              bottom: 5
+                            })
+                            .fontWeight(400)
+                            .borderRadius(8)
+                            .fontColor(Color.Black)
+                            .linearGradient(this.linearInfo)
+                        }
+                        .width(54)
+                        .height(30)
+                        .alignItems(VerticalAlign.Center)
+                        .justifyContent(FlexAlign.Center)
+                        .onClick(() => {
+                          if(this.Vm.showTimePicker === index) {
+                            this.Vm.showTimePicker = -1
+                          } else {
+                            this.Vm.showTimePicker = index
+                            this.Vm.showDatePicker = false
+                          }
+                        })
+
+                        // 分隔线
+                        Column(){
+                          Row() {
+                            Row()
+                              .width(7)
+                              .aspectRatio(1)
+                              .borderRadius(4)
+                              .backgroundColor('#206D43')
+                          }
+                          .width(10)
+                          .aspectRatio(1)
+                          .borderRadius(5)
+                          .backgroundColor('#B2D8C3')
+                          .alignItems(VerticalAlign.Center)
+                          .justifyContent(FlexAlign.Center)
+
+                          Row()
+                            .width(1)
+                            .backgroundColor('#206D43')
+                            .layoutWeight(1)
+
+                          Row() {
+                            Row()
+                              .width(7)
+                              .aspectRatio(1)
+                              .borderRadius(4)
+                              .backgroundColor('#206D43')
+                          }
+                          .width(10)
+                          .aspectRatio(1)
+                          .borderRadius(5)
+                          .backgroundColor('#B2D8C3')
+                          .alignItems(VerticalAlign.Center)
+                          .justifyContent(FlexAlign.Center)
+                        }
+                        .width(30)
+                        .height(this.heightList[index] + 15)
+                      }
+                      // .layoutWeight(1)
+
+                      // 标题 和 内容
+                      Column({space: 5}){
+                        // 标题
+                        Row(){
+                          Text(item.title)
+                            .fontSize(14)
+                            .fontWeight(600)
+                            .fontColor('#206D43')
+                            .padding({
+                              top: 5,
+                              left: 8,
+                              right: 8,
+                              bottom: 5
+                            })
+                            .maxLines(1)
+                            .textOverflow ({overflow: TextOverflow.Ellipsis})
+                        }
+                        .height(30)
+                        .alignItems(VerticalAlign.Center)
+                        .justifyContent(FlexAlign.Center)
+
+                        // 内容
+                        Column({space: 8}){
+                          Text(item.content)
+                            .fontSize(12)
+                            .fontColor('#333333')
+                            .opacity(0.5)
+                            .maxLines(2)
+                            .textOverflow ({overflow: TextOverflow.Ellipsis})
+
+                          // 图片显示
+                          Scroll(){
+                            Row({space: 5}){
+                              ForEach(item.imageUrls, (url: string, index: number) => {
+                                Image(url)
+                                  .width(100)
+                                  .height(150)
+                                  .borderRadius(12)
+                              })
+                            }
+                          }
+                          .scrollable(ScrollDirection.Horizontal)
+                          .scrollBar(BarState.Off)
+
+                        }
+                        .alignItems(HorizontalAlign.Start)
+                        .justifyContent(FlexAlign.Start)
+                        .onAreaChange((_o: Area, _n: Area) => {
+                          this.heightList[index] = _n.height as number
+                        })
+
+                        Blank().height(15)
+                      }
+                      .layoutWeight(1)
+                      .alignItems(HorizontalAlign.Start)
+                      .justifyContent(FlexAlign.Start)
+                      .onClick(() => {
+                        this.routerAddNote(item.id!)
+                        this.Vm.showDatePicker = false
+                        this.Vm.showTimePicker = -1
+                      })
+                      .gesture(
+                        LongPressGesture()
+                          .onAction(() => {
+                            console.log("长按了哦")
+                            this.Vm.onDelRecode(item.id!)
+                          })
+                      )
+                    }
+                    .onClick(() => {
+                      this.Vm.showTimePicker = -1
+                      this.Vm.showDatePicker = false
+                    })
+                    .onAreaChange((_o: Area, _n: Area) => {
+                      console.log('位置信息' + JSON.stringify(_n.globalPosition))
+                      let postion = this.Vm.postionList
+                      postion[index] = _n.globalPosition
+                      this.Vm.postionList = postion
+                    })
+                  }
+                })
+
+                // 空数据页面
+                if(this.Vm.recodeList.length === 0) {
+                  ListItem(){
+                    Column({space: 12}){
+                      Row({space: 8}){
+                        Text("+")
+                        Text("去添加")
+                      }
+                      .borderRadius(8)
+                      .linearGradient(this.linearInfo)
+                      .alignItems(VerticalAlign.Center)
+                      .justifyContent(FlexAlign.Center)
+                      .border({width: 1, color: Color.Black})
+                      .padding({ left: 16, top: 12, right: 16, bottom: 12})
+                      .onClick(() => {
+                        this.routerAddNote()
+                      })
+
+                      Text("暂无记录~")
+                        .fontSize(14)
+                        .fontWeight(400)
+                    }
+                    .width("100%")
+                    .height("100%")
+                    .alignItems(HorizontalAlign.Center)
+                    .padding({ top: '30%'})
+                    // .justifyContent(FlexAlign.Center)
+                  }
+                  .layoutWeight(1)
+                  .width("100%")
+                }
+              }
+              .width("100%")
+              .height("100%")
+              .scrollBar(BarState.Off)
+              .padding({top: 10})
+              .onScrollIndex(() => {
+                this.Vm.showTimePicker = -1
+              })
+
+              // 增加日记按钮
+              Row() {
+                Image($r("app.media.add_Img"))
+                  .width(35)
+                  .aspectRatio(1)
+              }
+              .onClick(() => {
+                this.routerAddNote()
+              })
+              .width(60)
+              .aspectRatio(1)
+              .borderRadius(30)
+              .alignItems(VerticalAlign.Center)
+              .justifyContent(FlexAlign.Center)
+              .backgroundColor('#206D43')
+            }
+            .width("100%")
+            .layoutWeight(1)
+            .padding({
+              bottom: 20, left: 24, right: 24
+            })
+
+            // 记录内容主体
+            // Stack({ alignContent: Alignment.BottomEnd }){
+            //
+            //   // 增加日记按钮
+            //   Row() {
+            //     Image($r("app.media.add"))
+            //       .width(20)
+            //       .aspectRatio(1)
+            //   }
+            //   .onClick(() => {
+            //     this.routerAddNote()
+            //   })
+            //   .width(40)
+            //   .aspectRatio(1)
+            //   .borderRadius(20)
+            //   .padding(8)
+            //   // .border({ width: 1 })
+            //   .margin({ bottom: 16 })
+            //   // .backgroundColor(Color.White)
+            //   .alignItems(VerticalAlign.Center)
+            //   .justifyContent(FlexAlign.Center)
+            //   .linearGradient(this.linearInfo)
+            // }
+            // .width("100%")
+            // .layoutWeight(1)
+          }
+          // 日期选择器
+          if(this.Vm.showDatePicker) {
+            DiaryDatePicker({
+              selectedDate: this.Vm.weekLoop.getData(this.Vm.swiperCurrentIndex).id,
+              selectDateBack: (date: Date) => {
+                this.Vm.showDatePicker = false
+                this.Vm.jumpToDate(date)
+              }
+            })
+              .width(267)
+              .height(300)
+          }
+        }
+        .width("100%")
+        .layoutWeight(1)
+        .backgroundColor(Color.Transparent)
+        .borderRadius({
+          topLeft: 20,
+          topRight: 20
+        })
+      }
+      .width("100%")
+      .height("100%")
+      .padding({ top: this.safeTop})
+      .linearGradient({
+        colors: [ ['#CEFFD2', -0.708], ['#FFFFFF', 0.2135],['#FFFFFF', 1.044] ],
+        angle: 171
+      })
+      .onVisibleAreaChange([0, 1], (isExpanding: boolean, currentRatio: number) => {
+        if(isExpanding) {
+          console.log("组件出来了")
+
+          this.loadDataList(this.Vm.getSelectedDate())
+        } else {
+          console.log("组件退了")
+        }
+      })
+    }
+    .width("100%")
+    .height("100%")
+
+
+  }
+}
+

+ 595 - 46
features/feature/src/main/ets/view/MainView.ets

@@ -1,64 +1,613 @@
 import { BackgroundPageModifier, DateOption, YTAddressSelectorDialog,
   YTCalendarPicker,
-  YTDateUtil, yTRouter } from 'basic'
+  YTDateUtil,
+  YTHeader,
+  yTRouter } from 'basic'
 import { UnitType } from 'basic/src/main/ets/datepicker/DatePickerEnums'
 import { promptAction } from '@kit.ArkUI'
+import { MainViewModel } from '../viewmodels/MainViewModel'
+import { SwiperCom } from '../components/maincomponent/SwiperCom'
+import { BuilderHeader } from '../components/maincomponent/BuilderHeader'
+import { DiaryDatePicker } from '../components/maincomponent/DiaryDatePicker'
+import { DiaryTimePicker } from '../components/maincomponent/DiaryTimePicker'
 
-@Component
+@ComponentV2
 export struct MainView {
+  @Local isShowMaintenanceBuilder:boolean=false
+  @Local vm:MainViewModel=new MainViewModel()
   build() {
-    Column() {
-      Text('打开日历')
-        .onClick(() => {
-          //以下内容都可以不传 有默认值
-          const date: Date = new Date()
-          const yTDateDialog = new YTAddressSelectorDialog(this.getUIContext())
-          let dateOption = new DateOption() //选项配置类
-          dateOption.date = date //当前日期  默认今天
-          dateOption.minDate = new Date(2000, 0, 1) //最小选择的日期 默认10年前的今天
-          dateOption.maxDate = new Date(2048, 12, 30) //最大选择的日期 默认10年后的今天
-          dateOption.unitType = UnitType.YEAR_MONTH_DAY //日期单位 默认年月日 可选年月、月日等组合
-          dateOption.confirm = (date: Date) => { //确认选择回调函数
-            console.log('确认', YTDateUtil.formatDate(date))
-            promptAction.openToast({ message: YTDateUtil.formatDate(date) })
-          }
-          dateOption.headerLeftBuilder = wrapBuilder(headerLeftBuilder) //头部左侧按钮 默认返回按钮
-          dateOption.headerRightBuilder = wrapBuilder(headerRightBuilder) //头部右侧按钮 默认确认按钮
-          dateOption.highlightBackgroundColor = Color.Pink //选中高亮背景色
-          dateOption.highlightBorderColor = Color.Red //选中高亮边框色
-          dateOption.textStyle = {
-            //日期文字样式
-            font: { size: 20, weight: 400 },
-            color: Color.Gray
+    Stack({ alignContent: Alignment.BottomEnd }) {
+      Column() {
+        YTHeader({
+          backArrow: false,
+          title: '我的绿植',
+          rightComp: this.rightComp,
+          headerPadding: { top: 19, left: 16, right: 16 }
+        })
+        Column() {
+          Search({ value: "", placeholder: '搜索植物' })
+            .searchIcon({
+              src: $r('sys.media.ohos_ic_public_search_filled')
+            })
+            .cancelButton({
+              style: CancelButtonStyle.CONSTANT,
+              icon: {
+                src: $r('sys.media.ohos_ic_public_cancel_filled')
+              }
+            })
+            .width('100%')
+            .height(48)
+            .maxLength(20)
+            .borderRadius(12)
+            .backgroundColor('#fff')
+            .placeholderColor(Color.Grey)
+            .placeholderFont({ size: 16, weight: 400 })
+            .textFont({ size: 16, weight: 400 })
+            .onSubmit((value: string) => {
+
+            })
+            .onChange((value: string) => {
+
+            })
+
+          Row() {
+            Text('最近添加').fontSize(14).fontColor('#333333')
+            Image($r('app.media.main_icon_edit')).width(24)
+          }.width('100%').justifyContent(FlexAlign.SpaceBetween)
+
+          List({ space: 16 }) {
+            ForEach([1, 2, 3, 4], () => {
+              ListItem() {
+                Row() {
+                  Row() {
+                    Column() {
+                      Image($r('app.media.app_icon')).width(55).height(79)
+                    }
+                    .width(70)
+                    .height(90)
+                    .justifyContent(FlexAlign.Center)
+                    .alignItems(HorizontalAlign.Center)
+                    .borderRadius(20)
+                    .backgroundColor('#E8EBF0')
+                    .margin({ right: 9 })
+
+                    Column({ space: 11 }) {
+                      Text('龟背竹').fontColor('#333333')
+                      Row({ space: 5 }) {
+                        Image($r('app.media.main_icon_maintenance')).width(15).height(15)
+                        Text('今天|已浇水,施肥').fontColor('#333333').fontSize(12)
+                      }
+
+                      Row({ space: 5 }) {
+                        Image($r('app.media.main_icon_maintenance')).width(15).height(15)
+                        Text('3天后|需浇水').fontColor('#333333').fontSize(12)
+                      }
+                    }.justifyContent(FlexAlign.Start).alignItems(HorizontalAlign.Start)
+
+                    Blank()
+                    this.MaintenanceClockTextBuilder()
+                  }
+                  .width('100%')
+                  .backgroundColor('#fff')
+                  .borderRadius(12)
+                  .padding({
+                    left: 17,
+                    top: 17,
+                    right: 20,
+                    bottom: 17
+                  })
+                }.width('100%').onClick(()=>{
+                  yTRouter.pushPathByName("EditGreenPlantPage",'编辑绿植',(result:PopInfo)=>{
+                    let ans=result.result as string
+                    if(ans&&ans=='true'){
+                      //刷新植物列表
+                    }
+                  });
+                })
+              }.swipeAction({
+                end: this.itemEnd(1, 0),
+              })
+            })
+
+
+          }.width('100%')
+
+        }.width('100%')
+        .padding({ left: 16, right: 16 })
+        .bindSheet($$this.isShowMaintenanceBuilder, this.MaintenanceClockBindSheetBuilder(), {
+          height: 530,
+          showClose: false,
+          backgroundColor: Color.Transparent
+        })
+      }.width('100%').height('100%')
+      Column() {
+        Image($r('app.media.startIcon')).width(30).height(30)
+      }
+      .width(60)
+      .height(60)
+      .justifyContent(FlexAlign.Center)
+      .borderRadius('50%')
+      .backgroundColor('#FF01A74D')
+      .margin({ bottom: 22, right: 22 })
+      .onClick(() => {
+        yTRouter.pushPathByName("EditGreenPlantPage",'新增绿植',(result:PopInfo)=>{
+          let ans=result.result as string
+          if(ans&&ans=='true'){
+            //刷新植物列表
           }
-          dateOption.selectedTextStyle = {
-            //选中日期文字样式
-            font: { size: 25, weight: 400 },
-            color: Color.Yellow
+        });
+
+      })
+
+    }.width('100%')
+    .height('100%')
+    .backgroundColor('#EAF3F2')
+
+  }
+  @Builder rightComp(){
+    Stack({alignContent: Alignment.TopEnd}){
+      Image($r('app.media.icon_message'))
+        .width(24)
+        .aspectRatio(1)
+      if(true){
+        Text()
+          .width(10)
+          .aspectRatio(1)
+          .borderRadius(5)
+          .backgroundColor(Color.Red)
+      }
+    }
+    .width(26)
+    .aspectRatio(1)
+    .onClick(()=>{
+      // yTRouter.router2MessagePage()
+    })
+  }
+  @Builder
+  itemEnd(id: number, index: number) {
+    Row() {
+      Image($r('app.media.main_icon_delete')).width(25).height(25)
+    }
+    .width(62)
+    .height(115)
+    .justifyContent(FlexAlign.Center)
+    .alignItems(VerticalAlign.Center)
+    .borderRadius(10)
+    .border({
+      width: 1,
+      color: Color.Red
+    })
+    .backgroundColor(Color.Red)
+    .borderRadius(10)
+    .onClick(() => {
+      // this.deleteMemorialById(id)
+      // this.dayList=this.dayList.filter(item=>item.memorialId!=id)
+    })
+  }
+  //养护打卡文字按钮builder
+  @Builder
+  MaintenanceClockTextBuilder(){
+    Column() {
+      Text('养护').fontColor('#498552')
+      Text('打卡').fontColor('#498552')
+    }.backgroundColor('#EAFFED')
+    .padding({
+      left: 12,
+      right: 12,
+      top: 10,
+      bottom: 9
+    })
+    .border({
+      width: 2,
+      color: '#81B433'
+    })
+    .borderRadius('50%')
+    .onClick(()=>{
+      this.isShowMaintenanceBuilder=!this.isShowMaintenanceBuilder
+    })
+  }
+  @Builder
+  MaintenanceClockBindSheetBuilder(){
+    Column(){
+      Swiper(this.vm.swiperController){
+          Column(){
+            Row(){
+              BuilderHeader({
+                leftTitle:"取消",
+                centerTitle:"养护打卡",
+                rightTitle:'打卡',
+                leftClick:()=>{
+                  this.isShowMaintenanceBuilder=false
+                },
+                rightClick:()=>{
+                  this.isShowMaintenanceBuilder=true
+                }
+              })
+
+            }.width('100%')
+            .margin({bottom:16})
+
+            Column({space:20}) {
+              Column() {
+                Row() {
+                  Text('打卡事项')
+                  Image($r('app.media.startIcon')).width(18)
+                }.width('100%')
+                .justifyContent(FlexAlign.SpaceBetween)
+                .padding({ top: 16, bottom: 16 })
+                .onClick(()=>{
+                  this.vm.swiperController.changeIndex(1,true)
+                })
+                Row() {
+                  Text('打卡植物')
+                  Image($r('app.media.startIcon')).width(18)
+                }.width('100%')
+                .justifyContent(FlexAlign.SpaceBetween)
+                .padding({ top: 16, bottom: 16 })
+                .onClick(()=>{
+                  this.vm.swiperController.changeIndex(2,true)
+
+                })
+              }.backgroundColor('#F8F8F8')
+              .padding({left:10,right:10})
+              .borderRadius(12)
+
+              Column() {
+                Row() {
+                  Text('打卡日期')
+                  Image($r('app.media.startIcon')).width(18)
+                }.width('100%')
+                .justifyContent(FlexAlign.SpaceBetween)
+                .padding({ top: 16, bottom: 16 })
+                .onClick(()=>{
+                  this.vm.swiperController.changeIndex(3,true)
+                })
+
+                Row() {
+                  Text('打卡时间')
+                  Image($r('app.media.startIcon')).width(18)
+                }.width('100%')
+                .justifyContent(FlexAlign.SpaceBetween)
+                .padding({ top: 16, bottom: 16 })
+              }.backgroundColor('#F8F8F8')
+              .padding({left:10,right:10})
+              .borderRadius(12)
+              .onClick(()=>{
+                this.vm.swiperController.changeIndex(4,true)
+
+              })
+            }.width('100%')
+
+
+          }.width('100%')
+          .height(530)
+          .padding({top:19,left:16,right:16})
+          .backgroundColor(Color.White)
+          .borderRadius({topLeft:20,topRight:20})
+        //打卡事项swiper
+        SwiperCom({
+          swiperBuilder1:()=>{
+            this.SelectClockTask()
+          },
+          swiperBuilder2:()=>{
+            this.AddClockTask()
+          },
+          swiperBuilder3: () => { this.AddClockTaskAndSelectIcon() },
+          swiperComController:this.vm.swiperComController[0]
+        })
+
+        SwiperCom({
+          swiperBuilder1:()=>{
+            //选择打卡植物
+            this.SelectClockTaskGreenPlant()
+          },
+          swiperComController:this.vm.swiperComController[1]
+        })
+        SwiperCom({
+          swiperBuilder1:()=>{
+            //选择打卡日期
+            this.SelectDate()
+          },
+          swiperComController:this.vm.swiperComController[2]
+        })
+        SwiperCom({
+          swiperBuilder1:()=>{
+            //选择打卡时间
+            this.SelectTime()
+          },
+          swiperComController:this.vm.swiperComController[3]
+        })
+        TextArea({ placeholder:"您正在进行养护打卡,点击此处进行备注", text:"xxxx" }).width('100%')
+          .height(165)
+          .backgroundColor('#F8F8F8')
+          .borderRadius(12)
+          .placeholderColor('#4D333333')
+          .placeholderFont({size:14})
+          .fontColor('#FF206D43')
+          .fontSize(16)
+
+      }
+      .width('100%')
+      .height(530)
+      .autoPlay(false)
+      .indicator(false)
+      .disableSwipe(true)
+      .curve(Curve.EaseIn)
+      .duration(100)
+
+
+
+    }.width('100%').backgroundColor(Color.Transparent)
+  }
+  //选择打卡事项
+  @Builder
+  SelectClockTask(){
+    Column({space:24}){
+      BuilderHeader({
+        leftTitle:'取消',
+        centerTitle:'选择打卡事项',
+        rightTitle:'确定',
+        leftClick:()=>{
+          //取消就返回到swiper[0]
+          this.vm.swiperController.changeIndex(0,true)
+        },
+        rightClick:()=>{
+          //确定也需要返回,不过打卡事项确定了
+          this.vm.swiperController.changeIndex(0,true)
+        }
+      })
+
+      Column({space:24}) {
+        Row() {
+          Text('基本事项')
+        }.width('100%')
+        .justifyContent(FlexAlign.Start)
+
+        Scroll() {
+          Grid() {
+            ForEach([1, 2, 3, 4, 5, 6,7,8,8,8], () => {
+              GridItem() {
+                Column({space:16}) {
+                  Image($r('app.media.startIcon')).width(45).height(45)
+                  Text('xxxx').fontSize(14)
+                }
+              }
+            })
+          }.height('100%').columnsTemplate('1fr 1fr 1fr').scrollBar(BarState.Off)
+        }.layoutWeight(1).scrollBar(BarState.Off)
+      }.height(300)
+
+      Column({space:24}) {
+        Row() {
+          Text('自定义')
+        }.width('100%')
+        .justifyContent(FlexAlign.Start)
+        Scroll() {
+          Grid() {
+            ForEach([1], () => {
+              GridItem() {
+                Column() {
+                  Image($r('app.media.startIcon')).width(45).height(45)
+                  Text('xxxx')
+                }.onClick(()=>{
+                  this.vm.swiperComController[0].changeIndex(1,true)
+                })
+              }
+            })
+          }.columnsTemplate('1fr 1fr 1fr')
+        }.layoutWeight(1).scrollBar(BarState.Off)
+      }.layoutWeight(1)
+
+    }.width('100%')
+    .height(530)
+    .padding({top:16,left:16,right:16})
+    .backgroundColor(Color.White)
+    .borderRadius({topLeft:20,topRight:20})
+  }
+  //创建打卡事项
+  @Builder
+  AddClockTask(){
+    Column(){
+      Column(){
+
+        BuilderHeader({
+          leftTitle:'上一步',
+          centerTitle:'创建养护事项',
+          rightTitle:'确定',
+          leftClick:()=>{
+            this.vm.swiperComController[0].changeIndex(0,true)
+          },
+          rightClick:()=>{
+            this.vm.swiperComController[0].changeIndex(0,true)
+            //确定之后也返回,创建打卡事项成功
           }
-          yTDateDialog.show(dateOption) //设置好配置之后打开日历的函数
         })
 
-      Button('跳转页面测试')
+        Column(){
+
+        }.width(123)
+        .height(123)
+        .backgroundColor(Color.Green)
         .onClick(()=>{
-          yTRouter.pushPathByName('TestRouterPage',null)
+          //选择图标
+          this.vm.swiperComController[0].changeIndex(2,true)
         })
+      }.width('100%')
+      .height(530)
+      .padding({top:16,left:16,right:16})
+      .backgroundColor(Color.White)
+      .borderRadius({topLeft:20,topRight:20})
+    }.width('100%')
+    .height('100%')
+    .justifyContent(FlexAlign.Center)
 
-      YTCalendarPicker()
-    }
-    .attributeModifier(new BackgroundPageModifier(true))
+  }
+
+  //选择打卡事项图标
+  @Builder
+  AddClockTaskAndSelectIcon(){
+    Column(){
+      BuilderHeader({
+        leftTitle:'上一步',
+        centerTitle:'选择事项图标',
+        rightTitle:'确定',
+        leftClick:()=>{
+          this.vm.swiperComController[0].changeIndex(1,true)
+        },
+        rightClick:()=>{
+          this.vm.swiperComController[0].changeIndex(1,true)
+          //选择事项图标成功,返回
+        }
+      })
+      Column({space:24}) {
+        Scroll() {
+          Grid() {
+            ForEach([1,1,1,1,1,1,1,1,1,1,1,1,1], () => {
+              GridItem() {
+                Column() {
+                  Image($r('app.media.startIcon')).width(45).height(45)
+                  Text('xxxx')
+                }
+              }
+            })
+          }.columnsTemplate('1fr 1fr 1fr')
+        }.layoutWeight(1).scrollBar(BarState.Off)
+      }.layoutWeight(1)
+
+    }.width('100%')
+    .height(530)
+    .padding({top:16,left:16,right:16})
+    .backgroundColor(Color.White)
+    .borderRadius({topLeft:20,topRight:20})
 
   }
-}
+  //选择打卡植物
+  @Builder
+  SelectClockTaskGreenPlant(){
+    Column(){
 
-@Builder
-function headerLeftBuilder() {
-  Image($r('app.media.app_icon'))
-    .width(24)
-}
+      BuilderHeader({
+        leftTitle:'上一步',
+        centerTitle:'选择打开植物',
+        rightTitle:'确定',
+        leftClick:()=>{
+          this.vm.swiperController.changeIndex(0,true)
+        },
+        rightClick:()=>{
+          this.vm.swiperController.changeIndex(0,true)
+          //选择植物成功,返回
+        }
+      })
+
+      Search({ value:"", placeholder: '搜索植物' })
+        .searchIcon({
+          src: $r('sys.media.ohos_ic_public_search_filled')
+        })
+        .cancelButton({
+          style: CancelButtonStyle.CONSTANT,
+          icon: {
+            src: $r('sys.media.ohos_ic_public_cancel_filled')
+          }
+        })
+        .width('100%')
+        .height(48)
+        .maxLength(20)
+        .border({
+          width:1,
+          color:"#1A000000"
+        })
+        .borderRadius(12)
+        .backgroundColor('#fff')
+        .placeholderColor(Color.Grey)
+        .placeholderFont({ size: 16, weight: 400 })
+        .textFont({ size: 16, weight: 400 })
+        .onSubmit((value: string) => {
+
+        })
+        .onChange((value: string) => {
 
-@Builder
-function headerRightBuilder() {
-  Image($r("app.media.app_icon"))
-    .width(24)
-}
+        })
+
+      Grid(){
+        ForEach([1,2,3,4,5,6],()=>{
+          GridItem(){
+            Column({space:9}){
+              Column(){
+                Image($r('app.media.app_icon')).width(63).height(92)
+
+              }.width(88)
+              .height(113)
+              .justifyContent(FlexAlign.Center)
+              .backgroundColor('#FFE8EBF0')
+              .borderRadius(12)
+              Text('龟背竹').fontSize(14)
+            }.width(107)
+            .height(155)
+            .justifyContent(FlexAlign.Center)
+            .border({
+              width:1,
+              color:'#FF206D43'
+            })
+            .borderRadius(12)
+            .backgroundColor(Color.White)
+          }
+        })
+      }.width('100%')
+      .layoutWeight(1)
+      .scrollBar(BarState.Off)
+      .columnsTemplate('1fr 1fr 1fr')
+      .rowsGap(10)
+
+
+
+
+
+    }.width('100%')
+    .height(530)
+    .padding({top:19,left:8,right:8})
+    .backgroundColor(Color.White)
+    .borderRadius({topLeft:20,topRight:20})
+
+  }
+  //选择日期
+  @Builder
+  SelectDate(){
+    //日期
+    Column(){
+      DiaryDatePicker({
+        back:()=>{
+          this.vm.swiperController.changeIndex(0,true)
+        },
+        selectDateBack:()=>{
+          //需要带参数确定
+          this.vm.swiperController.changeIndex(0,true)
+
+        }
+
+      })
+    }.width('100%')
+    .backgroundColor(Color.Transparent)
+    .height(530)
+    .borderRadius({topLeft:20,topRight:20})
+  }
+  @Builder
+  SelectTime(){
+    //时间
+    Column() {
+      DiaryTimePicker({
+        onCancel:()=>{
+          this.vm.swiperController.changeIndex(0,true)
+        },
+        onConfirm:()=>{
+          this.vm.swiperController.changeIndex(0,true)
+        }
+
+      })
+    }.width('100%')
+    .height(530)
+    .backgroundColor(Color.White)
+    .borderRadius({topLeft:20,topRight:20})
+  }
+
+}
+//YTCalendarPicker()

+ 228 - 0
features/feature/src/main/ets/view/RecodeViewModel.ets

@@ -0,0 +1,228 @@
+import { AppStorageKeyCollect, IBestToast, yTToast } from 'basic';
+import { DiaryApi } from '../api/DiaryApi';
+import { DiaryData } from '../models';
+import { BasicDataSource } from '../models/BasicDataSource';
+import { DateInfo } from '../models/DateInfo';
+import { DateUtils } from '../utils/DateUtils';
+
+export class RecodeViewModel{
+  // 懒加载数据源
+  weekLoop: BasicDataSource<DateInfo> = new BasicDataSource()
+  // swiper 控制器
+  swiperController: SwiperController = new SwiperController();
+  // 是否显示时间选择器
+  showDatePicker: boolean = false
+  // 是否显示时间选择器
+  showTimePicker: number = -1
+  // swiper 容器中当前选中的 index
+  swiperCurrentIndex: number = 0
+  // 日历中被选中的日期
+  selectedDate: number = 0
+  // 当天小记录的数据
+  recodeList: DiaryData[] = []
+  // 记录时间组件的位置信息
+  postionList: Position[] = []
+
+  // 外部传入, 用于修改日历中选中的日期 ( 直接在本类中修改 UI 无法进行刷新WWW )
+  selectedDateChange: (index: number) => void = (index: number) => {}
+
+  /**
+   * 构造函数 - 初始化 weekLoop 数据源
+   */
+  constructor() {
+    // 初始化列表数据
+    const dateList: DateInfo[] = DateUtils.generateForwardDateArray(new Date, 30);
+    console.log("初始化数据" + JSON.stringify(dateList))
+    this.weekLoop.init(dateList);
+  }
+
+  /**
+   * 加载更多数据 - 向左
+   * @param days 需要加载天数
+   */
+  loadForwardMoreData(days: number): void {
+    // 取得列表最后一条数据的 id
+    const dateInfo: Date = this.weekLoop.getData(this.weekLoop.totalCount() - 1).id;
+    // 向后加载 10 天的数据
+    const dateArray: DateInfo[] = DateUtils.generateForwardDateArray(dateInfo, days)
+    dateArray.splice(0, 1)
+    console.log("向左加载的数据" +  JSON.stringify(dateArray))
+
+    // 重新挂载到数据源中
+    this.weekLoop.reloadDataPush(dateArray)
+  }
+
+  /**
+   * 加载更多数据 - 向右
+   * @param days 加载的天数
+   * @param start 起始的日期, 未传则使用当前时间
+   * @returns 加载的天数
+   */
+  loadBackwardMoreData(days: number, start?: Date): number {
+    // 向后加载 10 天的数据
+    const dateArray: DateInfo[] = DateUtils.generateBackwardDateArray(start ?? new Date(), days)
+    console.log("向右加载的数据" + JSON.stringify(dateArray))
+    dateArray.splice(0, 1)
+
+    const count = dateArray.length
+    // 重新挂载到数据源中
+    this.weekLoop.reloadDataUnshift(dateArray)
+
+    return count;
+  }
+
+  /**
+   * swiper 改变时触发
+   * @param currentIndex 当前 swiper 选中的 index
+   * @param days 加载的天数
+   */
+  swiperOnChange(currentIndex: number, days: number = 10){
+    console.log('Swiper currentIndex', currentIndex)
+    this.swiperCurrentIndex = currentIndex
+    if (currentIndex >= this.weekLoop.totalCount() - 10) {
+      // 向左加载
+      console.log('Swiper loadMoreData')
+      this.loadForwardMoreData(days)
+    } else if (currentIndex <= 10) {
+      // 向右加载
+      let count = this.loadBackwardMoreData(days, this.weekLoop.getData(0).id)
+      this.swiperController.changeIndex(this.swiperCurrentIndex + count)
+      this.selectedDateChange(this.selectedDate + count)
+    }
+  }
+
+  /**
+   * 通过日期选择器跳转至指定日期时触发
+   * @param date 跳转到的指定日期
+   */
+  jumpToDate(date: Date) {
+    const backList: DateInfo[] = DateUtils.generateBackwardDateArray(date, 20).reverse()
+    const forwardList: DateInfo[] = DateUtils.generateForwardDateArray(date, 20)
+    console.log("向右加载的数据" + JSON.stringify(backList))
+    console.log("向左加载的数据" + JSON.stringify(forwardList))
+
+    backList.pop()
+    // 小 小 大 大
+    const dateList: DateInfo[] = [...backList, ...forwardList]
+    console.log("重新加载" + JSON.stringify(dateList))
+    this.weekLoop.init(dateList);
+
+    const targetIndex = dateList.findIndex(item => item.id.getTime() === date.getTime())
+    this.swiperController.changeIndex(targetIndex)
+    this.selectedDateChange(targetIndex)
+  }
+
+  // 获取日历中被选中的日期
+  getSelectedDate(): string {
+    const ans = this.weekLoop.getData(this.selectedDate).id
+    const date = DateUtils.formatDateToCustomString(ans, false)
+    console.log("日历中被选中的日期" + date)
+    return date
+  }
+
+  /**
+   * 根据当前日历中选择的日期刷新数据
+   */
+  changeDataByIndex(){
+    const date = this.getSelectedDate()
+    this.queryNoteList(date)
+    console.log("当天小记录" + JSON.stringify(this.recodeList))
+  }
+
+  /**
+   * 时间选择器用 - 动态更改时间选择器的位置
+   * @param type 需要的坐标类型(x/y)
+   * @returns 坐标值
+   */
+  getPostion(type: 'x'|'y'): Length{
+    // 获取屏幕高度
+    const screenHeight = AppStorage.get<number>(AppStorageKeyCollect.SCREEN_HEIGHT)
+
+    if(type == 'x') {
+      return this.postionList[this.showTimePicker].x!
+    } else {
+      const y = this.postionList[this.showTimePicker].y! as number
+      // 屏幕剩余高度过小
+      if(screenHeight && y > screenHeight - 300) {
+        return y - 240
+      }
+      return y
+    }
+  }
+
+  getTime(index: number){
+    let time = this.recodeList[index].noteTime?.split(' ')[1]
+    let time1 = time?.split(':')
+    time1?.pop()
+    return time1?.join(':')
+  }
+
+  /**
+   * 在首页通过长按记录执行的删除的逻辑
+   * @param id
+   */
+  onDelRecode(id: number){
+
+    yTToast.doubleConfirm({
+      text: "确定删除该这条记录吗?",
+      click: async () => {
+        yTToast.hide()
+        let ans = await this.deleteNote(id)
+        if(ans){
+          IBestToast.show({ message: '删除了记录' })
+          //删除
+          this.recodeList=this.recodeList.filter(item=>item.id!=id)
+          //TODO:需要接后台数据请求删除后德数据列表,上述就需要删除
+          //后端请求刷新数据
+          // this.changeDataByIndex()
+        }
+      }
+    })
+  }
+  // 删除生活小记录
+  async deleteNote(id: number){
+    const ans = await DiaryApi.deleteNote(id)
+    return ans;
+  }
+
+  // 查询生活小记录
+  async queryNoteList(nowTime: string){
+    const result: DiaryData[] = await DiaryApi.queryNoteList(nowTime)
+    //
+    result.forEach(item => {
+      item.diaryDate = item.noteTime
+    })
+    //
+    result.sort((a, b) => {
+      return new Date(a.noteTime!).getTime() - new Date(b.noteTime!).getTime()
+    })
+    //
+    this.recodeList = result
+
+    console.log('查询生活小记录' + JSON.stringify(result))
+  }
+
+  // 修改生活小记录时间
+  async updateNoteTime(params: DiaryData){
+    const ans = await DiaryApi.updateNoteTime(params)
+    return ans;
+  }
+
+  // 查询生活小记录对象
+  static async queryNoteById(id: number){
+    // const ans: DiaryData = await DiaryApi.queryNoteById(id)
+    // return ans;
+  }
+
+  // 编辑生活小记录
+  static async updateNote(params: DiaryData){
+    // const ans = await DiaryApi.updateNote(params)
+    // return ans;
+  }
+
+  // 添加生活小记录
+  static async saveNote(params: DiaryData){
+    // const ans = await DiaryApi.saveNote(params)
+    // return ans;
+  }
+}

+ 237 - 197
features/feature/src/main/ets/view/SecondView.ets

@@ -1,214 +1,254 @@
-import { textToSpeech } from '@kit.CoreSpeechKit';
-import { BusinessError } from '@kit.BasicServicesKit';
+import { BasicType, yTRouter } from "basic"
+import { SecondViewModel } from "../viewmodels/SecondViewModel"
+import { promptAction } from "@kit.ArkUI"
+import { TaskItem } from "../models/Second"
 
-let ttsEngine: textToSpeech.TextToSpeechEngine;
+@ComponentV2
+export struct SecondView {
+  @Local vm:SecondViewModel=new SecondViewModel()
+  //任务栏
+  @Local setArr: Array<TaskItem> = [
+    new TaskItem({
+      text: '签到一次',
+      message: '1',
+      src:$r('app.media.app_icon'),
+      isShowClose:false,
+      click:()=>{
+        if(!this.setArr[0].isShowClose){
+          //点击签到
+          this.setArr[0].isShowClose=true
+        }
+      }
+    }),
+    new TaskItem({
+      text: '养护打卡成功一次',
+      message: '1',
+      src:$r('app.media.app_icon'),
+      isShowClose:false,
+      click:()=>{
+        if(!this.setArr[1].isShowClose){
+          //跳转页面
+        }
 
+      }
 
-@Component
-export struct SecondView {
-  @State createCount: number = 0;
-  @State voiceInfo: string = "";
-  @State originalText: string = "支付宝到账[n2]1000000元";
+    }),
+    new TaskItem({
+      text: '新增一盆绿植',
+      message: '5',
+      src:$r('app.media.app_icon'),
+      isShowClose:false,
+      click:()=>{
+        if(!this.setArr[2].isShowClose){
+          //跳转页面
+        }
+
+      }
+
+    }),
+    new TaskItem({
+      text: '记录一次',
+      message: '1',
+      src:$r('app.media.app_icon'),
+      isShowClose:false,
+      click:()=>{
+        if(!this.setArr[3].isShowClose){
+          //跳转页面
+        }
+
+      }
+    }),
+  ]
 
   build() {
-    Column() {
-      Scroll() {
-        Column() {
-          TextArea({ placeholder: 'Please enter tts original text', text: `${this.originalText}` })
-            .margin(20)
-            .border({
-              width: 5,
-              color: 0x317AE7,
-              radius: 10,
-              style: BorderStyle.Solid
-            })
-            .onChange((value: string) => {
-              this.originalText = value;
-              console.info(`original text: ${this.originalText}`);
-            })
-          Button() {
-            Text("CreateEngineByCallback")
-              .fontColor(Color.White)
-              .fontSize(20)
-          }
-          .type(ButtonType.Capsule)
-          .backgroundColor("#0x317AE7")
-          .width("80%")
-          .height(50)
-          .margin(10)
-          .onClick(() => {
-            this.createCount++;
-            console.info(`CreateTtsEngine:createCount:${this.createCount}`);
-            this.createByCallback();
+    Column({space:19}) {
+      //等级条
+      this.stepProgressBuilder()
+      //人物
+      Row({space:10}){
+        Column({space:6}){
+          Text(this.vm.value.toString()).fontSize(30).fontColor('#333333')
+          Row({space:5}){
+            Text('我的成长点').fontSize(10).fontColor('#206D43')
+            Image($r('app.media.app_icon')).width(14)
+          }.backgroundColor('#d0e3d9')
+          .padding({top:3,left:6,bottom:3,right:6})
+          .borderRadius(19)
+          .onClick(()=>{
+            yTRouter.pushPathByName("GrowInfoPage",'');
           })
 
-          Button() {
-            Text("speak")
-              .fontColor(Color.White)
-              .fontSize(20)
-          }
-          .type(ButtonType.Capsule)
-          .backgroundColor("#0x317AE7")
-          .width("80%")
-          .height(50)
-          .margin(10)
-          .onClick(() => {
-            this.createCount++;
-            this.speak();
-          })
+        }.alignItems(HorizontalAlign.Start)
 
-          Button() {
-            Text("listVoicesCallback")
-              .fontColor(Color.White)
-              .fontSize(20)
-          }
-          .type(ButtonType.Capsule)
-          .backgroundColor("#0x317AE7")
-          .width("80%")
-          .height(50)
-          .margin(10)
-          .onClick(() => {
-            this.listVoicesCallback();
-          })
+        Image($r('app.media.app_icon')).width(200)
+      }.width('100%')
+      .alignItems(VerticalAlign.Top)
+      //任务栏
+      Column(){
+        Row() {
+          Text('每日任务')
+            .fontSize(25)
+            .fontColor('#206D43')
+          Text('做任务得每周成长点')
+            .fontSize(10)
+            .fontColor('#9C9898')
+            .margin({top:10})
+        }.width('100%')
+        .justifyContent(FlexAlign.SpaceBetween)
+        .padding({left:16,right:26})
+        .height(53)
 
-          Button() {
-            Text("stop")
-              .fontColor(Color.White)
-              .fontSize(20)
-          }
-          .type(ButtonType.Capsule)
-          .backgroundColor("#0x317AE7")
-          .width("80%")
-          .height(50)
-          .margin(10)
-          .onClick(() => {
-            // 停止播报
-            console.info("Stop button clicked.");
-            ttsEngine.stop();
-          })
+        List({space:9}){
+          ForEach(this.setArr,(item:BasicType,index:number)=>{
+            ListItem(){
+              Row({space:17}){
 
-          Button() {
-            Text("isBusy")
-              .fontColor(Color.White)
-              .fontSize(20)
-          }
-          .type(ButtonType.Capsule)
-          .backgroundColor("#0x317AE7")
-          .width("80%")
-          .height(50)
-          .margin(10)
-          .onClick(() => {
-            // 查询播报状态
-            let isBusy = ttsEngine.isBusy();
-            console.info(`isBusy: ${isBusy}`);
-          })
+                Image(item.src).width(40)
+                Column({space:4}){
+                  Text(item.text).fontColor('#333333').fontWeight(500)
+                  Text(`+${item.message}成长点`).fontColor('#E69E21').fontSize(12)
+                }.alignItems(HorizontalAlign.Start)
+                Blank()
+                if(index==0) {
+                  Text(item.isShowClose ? '已签到' : '签 到')
+                    .fontColor('#fff')
+                    .padding({
+                      left: 11,
+                      right: 11,
+                      top: 8,
+                      bottom: 8
+                    })
+                    .backgroundColor(item.isShowClose?'#C4C4C4':'#206D43')
+                    .borderRadius(10)
+                    .onClick(item.click)
+                }else{
+                  Text(item.isShowClose?'已完成':'去完成')
+                    .fontColor('#fff')
+                    .padding({left:11,right:11,top:8,bottom:8})
+                    .backgroundColor(item.isShowClose?'#C4C4C4':'#206D43')
+                    .borderRadius(10)
+                    .onClick(item.click)
+                }
 
-          Button() {
-            Text("shutdown")
-              .fontColor(Color.White)
-              .fontSize(20)
-          }
-          .type(ButtonType.Capsule)
-          .backgroundColor("#0x317AA7")
-          .width("80%")
-          .height(50)
-          .margin(10)
-          .onClick(() => {
-            // 释放引擎
-            ttsEngine.shutdown();
+
+              }.width('100%')
+              .height(70)
+              .backgroundColor(Color.White)
+              .padding({left:13,right:13})
+              .borderRadius(12)
+
+            }
           })
-        }
-        .layoutWeight(1)
-      }
-      .width('100%')
-      .height('100%')
+        }.layoutWeight(1)
+        .scrollBar(BarState.Off)
+        .padding(6)
+        .align(Alignment.Top)
+
+
+      }.width('100%')
+      .borderRadius({topLeft:20,topRight:20})
+      .backgroundColor('#F8F8F8')
+
     }
+    .height('100%')
+    .width('100%')
+    .padding({top:44,left:16,right:16})
+    .linearGradient({
+      angle:180,
+      colors:[
+        ['#FEFFFF',-0.2],
+        ['#7CBE9A',1]
+      ]
+    })
   }
+  @Builder
+  stepProgressBuilder(){
+    Stack({alignContent:Alignment.Center}) {
+      Progress({ value: this.vm.value, total: 300 })
+        .width(300)
+        .style({ strokeWidth: 10, shadow: true })
+        .borderRadius(28)
+        .color('#206D43')
+      Row(){
+        Column(){
+
+        }.width(16)
+        .height(16)
+        .borderRadius('50%')
+        .margin({right:62})
+        .border({
+          width:1,
+          color:'#206D43'
+        })
+        .radialGradient({
+          center: [8, 8],
+          radius: 8,
+          colors: [
+            ['#fff',0],
+            ['#81B433',1]
+          ]
+        })
+        Column(){
+
+        }.width(16)
+        .height(16)
+        .borderRadius('50%')
+        .border({
+          width:1,
+          color:'#206D43'
+        })
+        .radialGradient({
+          center: [8, 8],
+          radius: 8,
+          colors: [
+            ['#fff',0],
+            ['#81B433',1]
+          ]
+        })
+        .margin({right:200})
+        Column(){
+
+        }.width(16)
+        .height(16)
+        .borderRadius('50%')
+        .border({
+          width:1,
+          color:'#206D43'
+        })
+        .radialGradient({
+          center: [8, 8],
+          radius: 8,
+          colors: [
+            ['#fff',0],
+            ['#81B433',1]
+          ]
+        })
+
+      }.width(320).height(16)
+      Row(){
+        Column(){
+          Text('v1')
+            .fontSize(12)
+            .fontColor('#206D43')
+            .textAlign(TextAlign.Center)
 
-  // 创建引擎,通过callback形式返回
-  private createByCallback() {
-    // 设置创建引擎参数
-    let extraParam: Record<string, Object> = { "style": 'interaction-broadcast', "locate": 'CN', "name": 'EngineName' };
-    let initParamsInfo: textToSpeech.CreateEngineParams = {
-      language: 'zh-CN',
-      person: 0,
-      online: 1,
-      extraParams: extraParam
-    };
-    // 调用createEngine方法
-    textToSpeech.createEngine(initParamsInfo,
-      (err: BusinessError, textToSpeechEngine: textToSpeech.TextToSpeechEngine) => {
-        if (!err) {
-          console.info('Succeeded in creating engine.');
-          // 接收创建引擎的实例
-          ttsEngine = textToSpeechEngine;
-        } else {
-          console.error(`Failed to create engine. Code: ${err.code}, message: ${err.message}.`);
         }
-      });
-  };
-
-  // 调用speak播报方法
-  private speak() {
-    let speakListener: textToSpeech.SpeakListener = {
-      // 开始播报回调
-      onStart(requestId: string, response: textToSpeech.StartResponse) {
-        console.info(`onStart, requestId: ${requestId} response: ${JSON.stringify(response)}`);
-      },
-      // 完成播报回调
-      onComplete(requestId: string, response: textToSpeech.CompleteResponse) {
-        console.info(`onComplete, requestId: ${requestId} response: ${JSON.stringify(response)}`);
-      },
-      // 停止播报完成回调,调用stop方法并完成时会触发此回调
-      onStop(requestId: string, response: textToSpeech.StopResponse) {
-        console.info(`onStop, requestId: ${requestId} response: ${JSON.stringify(response)}`);
-      },
-      // 返回音频流
-      onData(requestId: string, audio: ArrayBuffer, response: textToSpeech.SynthesisResponse) {
-        console.info(`onData, requestId: ${requestId} sequence: ${JSON.stringify(response)} audio: ${JSON.stringify(audio)}`);
-      },
-      // 错误回调,播报过程发生错误时触发此回调
-      onError(requestId: string, errorCode: number, errorMessage: string) {
-        console.error(`onError, requestId: ${requestId} errorCode: ${errorCode} errorMessage: ${errorMessage}`);
-      }
-    };
-    // 设置回调
-    ttsEngine.setListener(speakListener);
-    // 设置播报相关参数
-    let extraParam: Record<string, Object> = {
-      "queueMode": 0,
-      "speed": 1,
-      "volume": 2,
-      "pitch": 1,
-      "languageContext": 'zh-CN',
-      "audioType": "pcm",
-      "soundChannel": 3,
-      "playType": 1
+        .margin({right:62})
+        Column(){
+          Text('v2')
+            .fontSize(12)
+            .fontColor('#206D43')
+            .textAlign(TextAlign.Center)
+
+        }.margin({right:200})
+        Column(){
+          Text('v3')
+            .fontSize(12)
+            .fontColor('#206D43')
+            .textAlign(TextAlign.Center)
+
+        }
+      }.width(320).margin({bottom:30})
     }
-    let speakParams: textToSpeech.SpeakParams = {
-      requestId: '123456-a', // requestId在同一实例内仅能用一次,请勿重复设置
-      extraParams: extraParam
-    };
-    // 调用speak播报方法
-    ttsEngine.speak(this.originalText, speakParams);
-  };
-
-  // 查询语种音色信息,以callback形式返回
-  private listVoicesCallback() {
-    // 设置查询相关参数
-    let voicesQuery: textToSpeech.VoiceQuery = {
-      requestId: '123456-b', // requestId在同一实例内仅能用一次,请勿重复设置
-      online: 1
-    };
-    // 调用listVoices方法,以callback返回语种音色查询结果
-    ttsEngine.listVoices(voicesQuery, (err: BusinessError, voiceInfo: textToSpeech.VoiceInfo[]) => {
-      if (!err) {
-        // 接收目前支持的语种音色等信息
-        this.voiceInfo = JSON.stringify(voiceInfo);
-        console.info(`Succeeded in listing voices, voiceInfo is ${voiceInfo}`);
-      } else {
-        console.error(`Failed to list voices. Code: ${err.code}, message: ${err.message}`);
-      }
-    });
-  };
-}
+  }
+}

+ 2 - 85
features/feature/src/main/ets/view/ThirdView.ets

@@ -2,93 +2,10 @@ import { Pet, RDBMapper, RelationalStoreUtils, Test } from "basic";
 
 @Component
 export struct ThirdView {
-  @State list: Test[] = []
-  @State list2: Pet[] = []
-  id1:number = 0
-  id2:number = 0
-  petMapper:RDBMapper<Pet> = new RDBMapper(Pet)
   build() {
-    Column() {
-      Row() {
-        Button('测试新增')
-          .onClick(() => {
-            RelationalStoreUtils.insert(Test, { name: 'test1', age: 18 }, (id) => {
-              console.log('insert success');
-              this.id1 = id
-              let list = RelationalStoreUtils.getListSync(Test)
-              this.list = list
-              console.log('list:', JSON.stringify(list))
-            })
-          })
-
-        Button('测试修改')
-          .onClick(() => {
-            RelationalStoreUtils.updateItemById(Test, { id: this.id1, name: '测试1修改', age: 20 }, () => {
-              console.log('insert success');
-              let list = RelationalStoreUtils.getListSync(Test)
-              this.list = list
-              console.log('list:', JSON.stringify(list))
-            })
-          })
-        Button('测试删除')
-          .onClick(() => {
-            RelationalStoreUtils.deleteItemById(Test, this.id1)
-            console.log('insert success');
-            let list = RelationalStoreUtils.getListSync(Test)
-            this.list = list
-            console.log('list:', JSON.stringify(list))
-          })
-      }
-      .width('100%')
-      .justifyContent(FlexAlign.SpaceAround)
-      .margin({ bottom: 30 })
-
-      Text(JSON.stringify(this.list))
-        .font({ size: 20 })
-        .margin({ bottom: 20 })
-
-      Row() {
-        Button('测试新增2')
-          .onClick(() => {
-            this.petMapper.insert( { name: 'test1', tag: '标签' }, (id:number) => {
-              console.log('insert success');
-              this.id2 = id
-              let list = this.petMapper.getListSync()
-              this.list2 = list
-              console.log('list:', JSON.stringify(list))
-            })
-          })
-
-        Button('测试修改2')
-          .onClick(() => {
-            this.petMapper.updateItemById({ id: this.id2, name: '测试1修改',tag: '标签2' }, () => {
-              console.log('insert success');
-              let list = this.petMapper.getListSync()
-              this.list2= list
-              console.log('list:', JSON.stringify(list))
-            })
-          })
-        Button('测试删除2')
-          .onClick(() => {
-            this.petMapper.deleteItemByIdSync(this.id2)
-            console.log('insert success');
-            let list = this.petMapper.getListSync()
-            this.list2 = list
-            console.log('list:', JSON.stringify(list))
-          })
-      }
-      .width('100%')
-      .justifyContent(FlexAlign.SpaceAround)
-      .margin({ bottom: 30 })
-
-      Text(JSON.stringify(this.list2))
-        .font({ size: 20 })
-        .margin({ bottom: 20 })
+    Column(){
 
     }
-    .justifyContent(FlexAlign.Center)
-    .alignItems(HorizontalAlign.Center)
-    .height('100%')
-    .width('100%')
+
   }
 }

+ 26 - 0
features/feature/src/main/ets/viewmodels/EditGreenPlantPageModel.ets

@@ -0,0 +1,26 @@
+@ObservedV2
+export class EditGreenPlantPageModel{
+  @Trace
+  swiperController:SwiperController=new SwiperController()
+  @Trace
+  swiperComController:SwiperController[]=[
+    new SwiperController(),
+    new SwiperController(),
+    new SwiperController(),
+    new SwiperController(),
+  ]
+
+  @Trace
+  frequency:string=DateFrequency.NONE //默认一次
+  // @Trace
+  // siw:SwiperController=new SwiperController()
+
+}
+
+export enum DateFrequency{
+  NONE='once', //默认
+  DAY='every_day', //每天
+  WEEK='every_week', //每周
+  MONTH='every_month', //每月
+  FREE='time_day' //自定义
+}

+ 26 - 0
features/feature/src/main/ets/viewmodels/MainViewModel.ets

@@ -0,0 +1,26 @@
+@ObservedV2
+export class MainViewModel{
+  @Trace
+  swiperController:SwiperController=new SwiperController()
+  @Trace
+  swiperComController:SwiperController[]=[
+    new SwiperController(),
+    new SwiperController(),
+    new SwiperController(),
+    new SwiperController(),
+  ]
+
+  @Trace
+  frequency:string=DateFrequency.NONE //默认一次
+  // @Trace
+  // siw:SwiperController=new SwiperController()
+
+}
+
+export enum DateFrequency{
+  NONE='once', //默认
+  DAY='every_day', //每天
+  WEEK='every_week', //每周
+  MONTH='every_month', //每月
+  FREE='time_day' //自定义
+}

+ 6 - 0
features/feature/src/main/ets/viewmodels/SecondViewModel.ets

@@ -0,0 +1,6 @@
+@ObservedV2
+export class  SecondViewModel{
+  //成长值
+  @Trace
+  value:number=70
+}

+ 1 - 0
features/feature/src/main/resources/base/media/Diary_DateOpen.svg

@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1755755766785" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="5050" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M112.593358 228.860385c41.35999 0 767.301594 0 795.827277 0 37.003775 0 64.532759 27.609825 42.885739 54.892191-17.330714 21.871123-367.19501 458.883245-397.113413 496.180709-19.661805 24.495904-66.530252 24.081465-86.208431 0-21.951965-26.850531-373.59579-465.531666-398.023132-497.297137C52.043307 259.377422 71.837118 228.860385 112.593358 228.860385z" p-id="5051"></path></svg>

BIN
features/feature/src/main/resources/base/media/Diary_Entry.png


BIN
features/feature/src/main/resources/base/media/Diary_cancel.png


+ 4 - 0
features/feature/src/main/resources/base/media/Diary_close.svg

@@ -0,0 +1,4 @@
+<svg fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" class="design-iconfont">
+  <path fill="#EBEBEB" d="M12 2A10 10 0 1 0 12 22A10 10 0 1 0 12 2Z"/>
+  <path d="M14.8 9L12 11.8966M12 11.8966L15 15M12 11.8966L9.2 9M12 11.8966L9 15" stroke="#BDBDBD" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
+</svg>

BIN
features/feature/src/main/resources/base/media/RecodeTitle.png


BIN
features/feature/src/main/resources/base/media/add_Img.png


BIN
features/feature/src/main/resources/base/media/calendar.png


BIN
features/feature/src/main/resources/base/media/close.png


BIN
features/feature/src/main/resources/base/media/icon_message.png


BIN
features/feature/src/main/resources/base/media/main_icon_delete.png


BIN
features/feature/src/main/resources/base/media/main_icon_edit.png


BIN
features/feature/src/main/resources/base/media/main_icon_maintenance.png


BIN
features/feature/src/main/resources/base/media/main_icon_select_plant.png


BIN
features/feature/src/main/resources/base/media/main_icon_unselect_plant.png


+ 12 - 0
features/feature/src/main/resources/base/media/photoAlbum.svg

@@ -0,0 +1,12 @@
+<svg fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" class="design-iconfont">
+  <g clip-path="url(#qnjwvfk81__clip0_4996_75116)">
+    <path d="M1.20364 8.58219C1.54832 5.17362 4.27706 2.54264 7.68904 2.23347C9.16308 2.0999 10.7001 2 12 2C13.2999 2 14.8369 2.0999 16.311 2.23347C19.7229 2.54264 22.4517 5.17362 22.7964 8.58219C22.9158 9.76383 23 10.9639 23 12C23 13.0361 22.9158 14.2362 22.7964 15.4178C22.4517 18.8264 19.7229 21.4574 16.311 21.7665C14.8369 21.9001 13.2999 22 12 22C10.7001 22 9.16308 21.9001 7.68904 21.7665C4.27707 21.4574 1.54832 18.8264 1.20364 15.4178C1.08416 14.2362 1 13.0361 1 12C1 10.9639 1.08416 9.76383 1.20364 8.58219Z" stroke="#212245" stroke-width="2"/>
+    <path d="M5 17L7.91343 14.0234L11 17.5L15 13L19 17" stroke="#212245" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
+    <path fill="#212245" d="M16 5A2 2 0 1 0 16 9A2 2 0 1 0 16 5Z"/>
+  </g>
+  <defs>
+    <clipPath id="qnjwvfk81__clip0_4996_75116">
+      <path fill="#fff" d="M0 0H24V24H0z"/>
+    </clipPath>
+  </defs>
+</svg>

BIN
features/feature/src/main/resources/base/media/startIcon.png


+ 15 - 0
features/feature/src/main/resources/base/profile/router_map.json

@@ -4,6 +4,21 @@
       "name": "TestRouterPage",
       "pageSourceFile": "src/main/ets/pages/TestRouterPage.ets",
       "buildFunction": "TestRouterBuilder"
+    },
+    {
+      "name": "IncreaseDiaryPage",
+      "pageSourceFile": "src/main/ets/pages/IncreaseDiaryPage.ets",
+      "buildFunction": "IncreaseDiaryBuilder"
+    },
+    {
+      "name": "GrowInfoPage",
+      "pageSourceFile": "src/main/ets/pages/GrowInfoPage.ets",
+      "buildFunction": "GrowInfoBuilder"
+    },
+    {
+      "name": "EditGreenPlantPage",
+      "pageSourceFile": "src/main/ets/pages/EditGreenPlantPage.ets",
+      "buildFunction": "EditGreenPlantBuilder"
     }
   ]
 }

+ 8 - 1
products/entry/src/main/ets/pages/Index.ets

@@ -1,6 +1,6 @@
 import { BasicType, ContextHelper, YTAvoid, yTRouter } from 'basic';
 import { Mine } from 'user/src/main/ets/views/Mine';
-import { MainView, SecondView, ThirdView } from 'feature';
+import { FourView, MainView, SecondView, ThirdView } from 'feature';
 
 @Entry
 @Component
@@ -24,6 +24,11 @@ struct Index {
       src: $r('app.media.app_icon'),
       acSrc: $r('app.media.app_icon')
     },
+    {
+      text:"xx",
+      src: $r('app.media.app_icon'),
+      acSrc: $r('app.media.app_icon')
+    },
     {
       text: '我的',
       src: $r('app.media.app_icon'),
@@ -50,6 +55,8 @@ struct Index {
                 SecondView()
               } else if (index == 2) {
                 ThirdView()
+              }else if(index==3){
+                FourView()
               } else {
                 Mine()
               }

+ 12 - 1
products/entry/src/main/resources/base/profile/router_map.json

@@ -1,3 +1,14 @@
 {
-  "routerMap": []
+  "routerMap": [
+    {
+      "name": "EntryPage",
+      "pageSourceFile": "src/main/ets/pages/EntryPage.ets",
+      "buildFunction": "EntryBuilder"
+    },
+    {
+      "name": "PrivacyPage",
+      "pageSourceFile": "src/main/ets/pages/PrivacyPage.ets",
+      "buildFunction": "PrivacyBuilder"
+    }
+  ]
 }