增加女性健康的按键交互功能
authorCaisking <Casiking@zhihuishixun.com>
Thu, 23 Oct 2025 10:28:36 +0000 (18:28 +0800)
committerCaisking <Casiking@zhihuishixun.com>
Thu, 23 Oct 2025 10:28:36 +0000 (18:28 +0800)
code/sdk/application/wearable/fd272/nativeapp/nativelauncher/include/UiConfig.h
code/sdk/application/wearable/fd272/nativeapp/nativeui/womenhealth/include/WomenHealthModel.h
code/sdk/application/wearable/fd272/nativeapp/nativeui/womenhealth/include/WomenHealthPresenter.h
code/sdk/application/wearable/fd272/nativeapp/nativeui/womenhealth/include/WomenHealthView.h
code/sdk/application/wearable/fd272/nativeapp/nativeui/womenhealth/src/WomenHealthModel.cpp
code/sdk/application/wearable/fd272/nativeapp/nativeui/womenhealth/src/WomenHealthPresenter.cpp
code/sdk/application/wearable/fd272/nativeapp/nativeui/womenhealth/src/WomenHealthView.cpp

index 6c9ae69..2766c4a 100644 (file)
@@ -635,7 +635,7 @@ namespace OHOS
     static constexpr const char *PNG_APPLIST_SMART_IMAGE = APP_LIST_PATH "/smart.bin";              //语音助手
     static constexpr const char *PNG_APPLIST_CALENDAR_IMAGE = APP_LIST_PATH "/calendar.bin";              //日历
     static constexpr const char *PNG_APPLIST_HRV_IMAGE = APP_LIST_PATH "/hrv.bin";                  //hrv
-    static constexpr const char *PNG_APPLIST_WOMANHEALTH_IMAGE = APP_LIST_PATH "/womanhealth.bin";                  //女性健康
+    static constexpr const char *PNG_APPLIST_WOMANHEALTH_IMAGE = APP_LIST_PATH "/woman_health.bin";                  //女性健康
     //big Icon
     static constexpr const char *PNG_APPLIST_THEME_IMAGE_BIG = APP_LIST_PATH "/applist_big_icon/theme.bin";              // 显示方式
     static constexpr const char *PNG_APPLIST_CARDSET_IMAGE_BIG = APP_LIST_PATH "/applist_big_icon/cardsetting.bin";      // 卡片管理
@@ -679,7 +679,7 @@ namespace OHOS
     static constexpr const char *PNG_APPLIST_SMART_IMAGE_BIG = APP_LIST_PATH "/applist_big_icon/smart.bin";              //语音助手
     static constexpr const char *PNG_APPLIST_CALENDAR_IMAGE_BIG = APP_LIST_PATH "/applist_big_icon/calendar.bin";        //日历
     static constexpr const char *PNG_APPLIST_HRV_IMAGE_BIG = APP_LIST_PATH "/applist_big_icon/hrv.bin";                  //hrv
-    static constexpr const char *PNG_APPLIST_WOMANHEALTH_IMAGE_BIG = APP_LIST_PATH "/applist_big_icon/womanhealth.bin";                  //女性健康
+    static constexpr const char *PNG_APPLIST_WOMANHEALTH_IMAGE_BIG = APP_LIST_PATH "/applist_big_icon/woman_health.bin";                  //女性健康
   
     // AppList hexagon icon
     static constexpr const char *PNG_APPLIST_DEFAULT_IMG = APP_RES_PATH "/regular_hexagon.bin";
index b0d0e07..250bca8 100644 (file)
 
  
  namespace OHOS {
+ //时间结构体,年月日
+ typedef struct {
+    int year;
+    int month;
+    int day;
+ } TimeObj;
  
- 
- class WomenHealthModel {
- public:
-     static WomenHealthModel *GetInstance(void);
- 
- private:
-     WomenHealthModel();
-     WomenHealthModel(const WomenHealthModel &);
-     virtual ~WomenHealthModel();
+class WomenHealthModel {
+public:
+    static WomenHealthModel *GetInstance(void);
+    void SetMenstrualStartDate(const TimeObj &startDate);
+    void SetMenstrualEndDate(const TimeObj &endDate);
+    TimeObj GetMenstrualStartDate();
+    TimeObj GetMenstrualEndDate();
+    TimeObj GetOvulationStartDate();
+    TimeObj GetOvulationEndDate();
+    int TimeDiffInMinutes(const TimeObj &startDate, const TimeObj &endDate);
     
- };
+    // 判断某天是否在月经期内(已记录的)
+    bool IsInMenstrualPeriod(int year, int month, int day);
+    // 判断某天是否在排卵期内(已记录的)
+    bool IsInOvulationPeriod(int year, int month, int day);
+    // 判断某天是否在预测经期内
+    bool IsInPredictPeriod(int year, int month, int day);
+    // 判断某天是否在预测排卵期内(下次和下下次的排卵期)
+    bool IsInPredictOvulationPeriod(int year, int month, int day);
+    
+    // 辅助方法:获取经期开始的年月
+    void GetMenstrualStartYearMonth(int &year, int &month);
+    // 辅助方法:获取预测的最后一个月(第3次预测经期的月份)
+    void GetLastPredictYearMonth(int &year, int &month);
+    // 辅助方法:检查是否已设置经期数据
+    bool HasMenstrualData();
+
+private:
+    WomenHealthModel();
+    WomenHealthModel(const WomenHealthModel &);
+    virtual ~WomenHealthModel();
+    
+    // 比较两个日期,返回: <0表示date1在date2前,0表示相等,>0表示date1在date2后
+    int CompareDate(int year1, int month1, int day1, int year2, int month2, int day2);
+    // 给日期加上天数,返回新日期
+    TimeObj AddDays(const TimeObj &date, int days);
+    
+   //3个月的经期日期开始时间
+   TimeObj menstrualStartDate[3];
+   //3个月的经期日期结束时间
+   TimeObj menstrualEndDate[3];
+   //3个月的排卵期开始时间
+   TimeObj ovulationStartDate[3];
+   //3个月的排卵期结束时间
+   TimeObj ovulationEndDate[3];
+   //经期周期(天数)
+   int menstrualCycle = 5;
+   //排卵期周期(天数)
+   int ovulationCycle = 10;
+   //经期与排卵期之间的天数
+   int menstrualOvulationDays = 5;
+   //月经周期总长度(默认28天)
+   int totalCycle = 28;
+
+};
  }
  #endif
\ No newline at end of file
index 3bfe177..ea7c5e3 100644 (file)
  #include "NativeAbility.h"
  
  namespace OHOS {
+
+//下个月
+#define NEXT_MONTH "nextmonth"
+//上个月
+#define PREV_MONTH "prevmonth"
+//编辑
+#define EDIT "edit"
+
  class WomenHealthView;
  class WomenHealthPresenter : public Presenter<WomenHealthView>,
                                  public UIView::OnClickListener,
index fe6e16d..4b2a4a7 100644 (file)
 #include "components/ui_image_view.h"
 
  #include "womenhealth/include/WomenHealthPresenter.h"
+ 
+ namespace OHOS {
 
-namespace OHOS {
+// 日期状态枚举
+enum DayStatus {
+    DAY_STATUS_NORMAL = 0,      // 普通日期
+    DAY_STATUS_TODAY,           // 今天(灰色)
+    DAY_STATUS_MENSTRUAL,       // 月经期(红色)
+    DAY_STATUS_OVULATION,       // 排卵期(蓝色)
+    DAY_STATUS_PREDICT          // 预测经期(浅红色)
+};
 
 class WomenHealthView : public View<WomenHealthPresenter>
 {
@@ -33,25 +42,64 @@ public:
     void OnStart() override;
     static WomenHealthView *GetInstance();
     bool updata_label(int8_t type);
+    
+    // 公共方法:判断当前是否显示今天所在月份
+    bool IsShowingCurrentMonth();
+
+    void BackToToday();                                            // 回到今天所在月份
 
 private:
     bool Label_init();
+    
+    // 拆分后的初始化函数(降低耦合度)
+    void InitDayMarkers();                                         // 初始化颜色标记圆圈
+    void InitTitleLabel();                                         // 初始化顶部标题"生理周期"
+    void InitMonthLabel(int year, int month, int day, int weekday); // 初始化日期标签(X月X日 星期X)
+    void InitArrowButtons();                                       // 初始化左右箭头按钮
+    void InitEditButton();                                         // 初始化底部"编辑"按钮
+    void InitWeekLabels();                                         // 初始化星期标签
+    void InitDayLabels();                                          // 初始化日期标签UI对象
+    void UpdateDayDisplay(int year, int month, int maxDays, int weekday);  // 更新日期显示
+    
+    // 辅助函数
+    int CalculateMonthDays(int year, int month);                   // 计算某月有多少天
+    int CalculateWeekday(int year, int month, int day);            // 使用蔡勒公式计算星期几
+    void UpdateArrowButtonsVisibility();                           // 更新左右箭头按钮的显示状态
+    void UpdateEditButtonText();                                   // 更新底部按钮文本(编辑/回今天)
+
+    
+    // 判断某一天的状态(月经期、排卵期、预测经期等)
+    DayStatus GetDayStatus(uint32_t year, uint32_t month, uint32_t day);
+    
+    // 为指定日期绘制颜色标记圆圈
+    void DrawDayMarker(int dayIndex, int x, int y, DayStatus status);
+    
     UIViewGroup *group{nullptr};
     UIView:: OnDragListener* dragListener{nullptr};
-    UILabel *mon_label{nullptr};
+    
+    // 顶部UI组件
+    UILabel *title_label{nullptr};        // 标题"生理周期"
+    UILabel *mon_label{nullptr};          // 日期标签"X月X日 星期X"
+    UILabelButton *left_arrow{nullptr};   // 左箭头按钮
+    UILabelButton *right_arrow{nullptr};  // 右箭头按钮
+    
+    // 星期和日期标签
     UILabel *week_label[7]{nullptr};
     UILabel *day_label[31]{nullptr};
-    UIImageView *imageview{nullptr};
-
-    UIImageAnimatorView *PullUpAnimatorView{nullptr};   // 上拉动画
-
-    ImageAnimatorInfo PullUpimageAnimatorInfo[70]{0};
-
-    const ImageInfo** PullUpimageAnimator_imageInfo{nullptr};
     
-    uint32_t show_y=0;
-    uint32_t show_m=0;
-    uint32_t show_d=0;
+    // 底部按钮
+    UILabelButton *edit_button{nullptr};  // 编辑按钮
+    
+    // 不同状态的标记圆圈(最多显示31天)
+    UIImageView *dayMarker[31]{nullptr};  // 颜色标记圆圈数组
+    
+    uint32_t show_y=0;   // 当前显示的年
+    uint32_t show_m=0;   // 当前显示的月
+    uint32_t show_d=0;   // 当前显示的日
+    
+    uint32_t today_y=0;  // 今天的年
+    uint32_t today_m=0;  // 今天的月
+    uint32_t today_d=0;  // 今天的日
 };
 }
 
index c24dee6..69900c8 100644 (file)
 
 
  #include "womenhealth/include/WomenHealthModel.h"
+ #include "wearable_log.h"
+
  
- #ifdef __cplusplus
- extern "C" {
- #endif
- 
- using namespace OHOS;
- 
- WomenHealthModel::WomenHealthModel()
- {
- }
- 
- WomenHealthModel::~WomenHealthModel()
- {
- }
+ /*
  
+- 经期默认时长:5-6 天(用户可在该范围选择具体天数)
+- 排卵期默认计算:基于 28 天标准周期,自动推算为 10 天(排卵日及前后各 4-5 天)
+- 周期默认值:28 天(示例:9 月 3 日开始经期,下次预测经期为 10 月 1 日,即 9 月 3 日加 28 天)
  
- WomenHealthModel *WomenHealthModel::GetInstance(void)
+ */
+
+ namespace OHOS
  {
-     static WomenHealthModel callLogModel;
-     return &callLogModel;
- }
- 
- #ifdef __cplusplus
- }
- #endif
+
+   WomenHealthModel::WomenHealthModel()
+   {
+       // 初始化所有日期为0
+       for (int i = 0; i < 3; i++) {
+           menstrualStartDate[i] = {0, 0, 0};
+           menstrualEndDate[i] = {0, 0, 0};
+           ovulationStartDate[i] = {0, 0, 0};
+           ovulationEndDate[i] = {0, 0, 0};
+       }
+   }
+
+   WomenHealthModel::~WomenHealthModel(){}
+
+   WomenHealthModel *WomenHealthModel::GetInstance(void)
+   {
+       static WomenHealthModel instance;
+       return &instance;
+   }
+
+   //获取第一个月的经期开始时间
+   TimeObj WomenHealthModel::GetMenstrualStartDate()
+   {
+       return menstrualStartDate[0];
+   }
+   //获取第一个月的经期结束时间
+   TimeObj WomenHealthModel::GetMenstrualEndDate()
+   {
+       return menstrualEndDate[0];
+   }
+   //获取第一个月的排卵期开始时间
+   TimeObj WomenHealthModel::GetOvulationStartDate()
+   {
+       return ovulationStartDate[0];
+   }
+   //获取第一个月的排卵期结束时间
+   TimeObj WomenHealthModel::GetOvulationEndDate()
+   {
+       return ovulationEndDate[0];
+   }
+   
+   /**
+    * @brief 比较两个日期
+    * @return <0表示date1在date2前,0表示相等,>0表示date1在date2后
+    */
+   int WomenHealthModel::CompareDate(int year1, int month1, int day1, int year2, int month2, int day2)
+   {
+       if (year1 != year2) return year1 - year2;
+       if (month1 != month2) return month1 - month2;
+       return day1 - day2;
+   }
+   
+   /**
+    * @brief 给日期加上指定天数
+    * @param date 原始日期
+    * @param days 要加的天数
+    * @return 新日期
+    */
+   TimeObj WomenHealthModel::AddDays(const TimeObj &date, int days)
+   {
+       TimeObj result = date;
+       result.day += days;
+       
+       // 简单的日期计算(可以优化)
+       while (result.day > 31) {
+           result.day -= 30;  // 简化:每月按30天计算
+           result.month++;
+           if (result.month > 12) {
+               result.month = 1;
+               result.year++;
+           }
+       }
+       
+       while (result.day < 1) {
+           result.month--;
+           if (result.month < 1) {
+               result.month = 12;
+               result.year--;
+           }
+           result.day += 30;  // 简化:每月按30天计算
+       }
+       
+       return result;
+   }
+
+   /**
+    * @brief 用户设置经期开始日期
+    * @param startDate 经期开始日期
+    * 
+    * 根据开始日期自动计算:
+    * 1. 经期结束时间 = 开始时间 + menstrualCycle天
+    * 2. 排卵期开始时间 = 经期结束时间 + menstrualOvulationDays天
+    * 3. 排卵期结束时间 = 排卵期开始时间 + ovulationCycle天
+    * 4. 预测下次经期 = 本次开始 + totalCycle天(28天)
+    */
+   void WomenHealthModel::SetMenstrualStartDate(const TimeObj &startDate)
+   {
+       //设置这个月的经期开始时间
+       menstrualStartDate[0] = startDate;
+       
+       //经期结束时间 = 开始时间 + menstrualCycle天(默认5天)
+       menstrualEndDate[0] = AddDays(menstrualStartDate[0], menstrualCycle);
+       
+       //排卵期开始时间 = 经期结束时间 + menstrualOvulationDays天(默认5天)
+       ovulationStartDate[0] = AddDays(menstrualEndDate[0], menstrualOvulationDays);
+       
+       //排卵期结束时间 = 排卵期开始时间 + ovulationCycle天(默认10天)
+       ovulationEndDate[0] = AddDays(ovulationStartDate[0], ovulationCycle);
+       
+       //预测下次经期 = 本次开始 + totalCycle天(默认28天)
+       menstrualStartDate[1] = AddDays(menstrualStartDate[0], totalCycle);
+       menstrualEndDate[1] = AddDays(menstrualStartDate[1], menstrualCycle);
+       ovulationStartDate[1] = AddDays(menstrualEndDate[1], menstrualOvulationDays);
+       ovulationEndDate[1] = AddDays(ovulationStartDate[1], ovulationCycle);
+       
+       //预测下下次经期 = 下次开始 + totalCycle天
+       menstrualStartDate[2] = AddDays(menstrualStartDate[1], totalCycle);
+       menstrualEndDate[2] = AddDays(menstrualStartDate[2], menstrualCycle);
+       ovulationStartDate[2] = AddDays(menstrualEndDate[2], menstrualOvulationDays);
+       ovulationEndDate[2] = AddDays(ovulationStartDate[2], ovulationCycle);
+
+       //打印所有时间
+       WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "=== 本次月经 ===");
+       WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "经期开始: %d-%d-%d", menstrualStartDate[0].year, menstrualStartDate[0].month, menstrualStartDate[0].day);
+       WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "经期结束: %d-%d-%d", menstrualEndDate[0].year, menstrualEndDate[0].month, menstrualEndDate[0].day);
+       WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "排卵期开始: %d-%d-%d", ovulationStartDate[0].year, ovulationStartDate[0].month, ovulationStartDate[0].day);
+       WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "排卵期结束: %d-%d-%d", ovulationEndDate[0].year, ovulationEndDate[0].month, ovulationEndDate[0].day);
+       WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "=== 预测下次周期 ===");
+       WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "预测经期: %d-%d-%d 至 %d-%d-%d", menstrualStartDate[1].year, menstrualStartDate[1].month, menstrualStartDate[1].day, menstrualEndDate[1].year, menstrualEndDate[1].month, menstrualEndDate[1].day);
+       WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "预测排卵期: %d-%d-%d 至 %d-%d-%d", ovulationStartDate[1].year, ovulationStartDate[1].month, ovulationStartDate[1].day, ovulationEndDate[1].year, ovulationEndDate[1].month, ovulationEndDate[1].day);
+       WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "=== 预测下下次周期 ===");
+       WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "预测经期: %d-%d-%d 至 %d-%d-%d", menstrualStartDate[2].year, menstrualStartDate[2].month, menstrualStartDate[2].day, menstrualEndDate[2].year, menstrualEndDate[2].month, menstrualEndDate[2].day);
+       WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "预测排卵期: %d-%d-%d 至 %d-%d-%d", ovulationStartDate[2].year, ovulationStartDate[2].month, ovulationStartDate[2].day, ovulationEndDate[2].year, ovulationEndDate[2].month, ovulationEndDate[2].day);
+   }
+
+    int WomenHealthModel::TimeDiffInMinutes(const TimeObj &startDate, const TimeObj &endDate)
+    {
+        //计算差值天数
+        int diffDays = (endDate.year - startDate.year) * 365 + (endDate.month - startDate.month) * 30 + (endDate.day - startDate.day);
+        return diffDays;
+    }
+
+   /**
+    * @brief 用户设置经期结束日期
+    * @param endDate 经期结束日期
+    * 
+    * 根据开始和结束日期重新计算周期长度
+    */
+   void WomenHealthModel::SetMenstrualEndDate(const TimeObj &endDate)
+   {
+       menstrualEndDate[0] = endDate;
+       //计算经期持续天数
+       int diffDays = TimeDiffInMinutes(menstrualStartDate[0], menstrualEndDate[0]);
+       if (diffDays > 0) {
+           menstrualCycle = diffDays;
+       }
+       //重新计算排卵期和预测经期
+       SetMenstrualStartDate(menstrualStartDate[0]);
+   }
+   
+   /**
+    * @brief 判断某天是否在月经期内(已记录的)
+    * @return true表示在月经期内
+    */
+   bool WomenHealthModel::IsInMenstrualPeriod(int year, int month, int day)
+   {
+       // 检查第一个月经期(已记录的)
+       if (menstrualStartDate[0].year == 0) {
+           return false;  // 还没有设置数据
+       }
+       
+       int cmpStart = CompareDate(year, month, day, 
+                                  menstrualStartDate[0].year, menstrualStartDate[0].month, menstrualStartDate[0].day);
+       int cmpEnd = CompareDate(year, month, day,
+                                menstrualEndDate[0].year, menstrualEndDate[0].month, menstrualEndDate[0].day);
+       
+       // 在开始和结束之间
+       return (cmpStart >= 0 && cmpEnd <= 0);
+   }
+   
+   /**
+    * @brief 判断某天是否在排卵期内
+    * @return true表示在排卵期内
+    */
+   bool WomenHealthModel::IsInOvulationPeriod(int year, int month, int day)
+   {
+       // 检查排卵期
+       if (ovulationStartDate[0].year == 0) {
+           return false;  // 还没有设置数据
+       }
+       
+       int cmpStart = CompareDate(year, month, day,
+                                  ovulationStartDate[0].year, ovulationStartDate[0].month, ovulationStartDate[0].day);
+       int cmpEnd = CompareDate(year, month, day,
+                                ovulationEndDate[0].year, ovulationEndDate[0].month, ovulationEndDate[0].day);
+       
+       // 在开始和结束之间
+       return (cmpStart >= 0 && cmpEnd <= 0);
+   }
+   
+   /**
+    * @brief 判断某天是否在预测经期内
+    * @return true表示在预测经期内
+    */
+   bool WomenHealthModel::IsInPredictPeriod(int year, int month, int day)
+   {
+       // 检查预测的月经期(索引1和2)
+       for (int i = 1; i < 3; i++) {
+           if (menstrualStartDate[i].year == 0) {
+               continue;
+           }
+           
+           int cmpStart = CompareDate(year, month, day,
+                                      menstrualStartDate[i].year, menstrualStartDate[i].month, menstrualStartDate[i].day);
+           int cmpEnd = CompareDate(year, month, day,
+                                    menstrualEndDate[i].year, menstrualEndDate[i].month, menstrualEndDate[i].day);
+           
+           // 在预测的开始和结束之间
+           if (cmpStart >= 0 && cmpEnd <= 0) {
+               return true;
+           }
+       }
+       
+       return false;
+   }
+   
+   /**
+    * @brief 判断某天是否在预测排卵期内(下次和下下次的排卵期)
+    * @return true表示在预测排卵期内
+    */
+   bool WomenHealthModel::IsInPredictOvulationPeriod(int year, int month, int day)
+   {
+       // 检查预测的排卵期(索引1和2)
+       for (int i = 1; i < 3; i++) {
+           if (ovulationStartDate[i].year == 0) {
+               continue;
+           }
+           
+           int cmpStart = CompareDate(year, month, day,
+                                      ovulationStartDate[i].year, ovulationStartDate[i].month, ovulationStartDate[i].day);
+           int cmpEnd = CompareDate(year, month, day,
+                                    ovulationEndDate[i].year, ovulationEndDate[i].month, ovulationEndDate[i].day);
+           
+           // 在预测的排卵期开始和结束之间
+           if (cmpStart >= 0 && cmpEnd <= 0) {
+               return true;
+           }
+       }
+       
+       return false;
+   }
+   
+   /**
+    * @brief 获取经期开始的年月
+    * @param year 输出参数:年份
+    * @param month 输出参数:月份
+    */
+   void WomenHealthModel::GetMenstrualStartYearMonth(int &year, int &month)
+   {
+       year = menstrualStartDate[0].year;
+       month = menstrualStartDate[0].month;
+   }
+   
+   /**
+    * @brief 获取预测的最后一个月(第3次预测经期的月份)
+    * @param year 输出参数:年份
+    * @param month 输出参数:月份
+    */
+   void WomenHealthModel::GetLastPredictYearMonth(int &year, int &month)
+   {
+       // 第3次预测(索引2)的经期结束月份
+       if (menstrualEndDate[2].year != 0) {
+           year = menstrualEndDate[2].year;
+           month = menstrualEndDate[2].month;
+       } else {
+           year = 0;
+           month = 0;
+       }
+   }
+   
+   /**
+    * @brief 检查是否已设置经期数据
+    * @return true表示已设置,false表示未设置
+    */
+   bool WomenHealthModel::HasMenstrualData()
+   {
+       return (menstrualStartDate[0].year != 0);
+   }
+
+
+}
  
\ No newline at end of file
index 3144079..4ffa656 100644 (file)
@@ -17,7 +17,7 @@
  {
 
     REGIST_MENU_PRO(VIEW_WOMEN_HEALTH, WomenHealthView, WomenHealthPresenter,
-        PNG_APPLIST_CALENDAR_IMAGE_BIG, PNG_APPLIST_CALENDAR_IMAGE, PNG_APPLIST_CALENDAR_IMAGE, "日历", STR_CALENDAR);
+        PNG_APPLIST_WOMANHEALTH_IMAGE_BIG, PNG_APPLIST_WOMANHEALTH_IMAGE, PNG_APPLIST_WOMANHEALTH_IMAGE, "女性健康", STR_WOMANHEALTH);
 
      static WomenHealthPresenter *g_pMainView = nullptr;
      WomenHealthPresenter::WomenHealthPresenter()
          RootView::GetInstance()->SetOnKeyActListener(this);
      }
  
-     bool WomenHealthPresenter::OnClick(UIView &view, const ClickEvent &event)
-     {
-         UNUSED(event);
-         WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "OnClick");
- 
-         return false;
-     }
+    bool WomenHealthPresenter::OnClick(UIView &view, const ClickEvent &event)
+    {
+       UNUSED(event);
+       WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "WomenHealthPresenter::OnClick");
+       
+       if(strcmp(view.GetViewId(), NEXT_MONTH) == 0)
+       {
+           WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "点击右箭头:切换到下个月");
+           WomenHealthView::GetInstance()->updata_label(2);
+       }
+       else if(strcmp(view.GetViewId(), PREV_MONTH) == 0)
+       {
+           WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "点击左箭头:切换到上个月");
+           WomenHealthView::GetInstance()->updata_label(1);
+       }
+       else if(strcmp(view.GetViewId(), EDIT) == 0)
+       {
+           // 判断当前是否显示今天所在月份
+           if (WomenHealthView::GetInstance()->IsShowingCurrentMonth())
+           {
+               // 当前显示今天所在月份 -> 执行"编辑"功能
+               WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "点击编辑按钮:跳转到编辑页面");
+               // TODO: 跳转到编辑页面,让用户设置经期开始日期
+               // NativeAbility::GetInstance().Navigate(VIEW_WOMEN_HEALTH_EDIT);
+           }
+           else
+           {
+               // 当前显示其他月份 -> 执行"回今天"功能
+               WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "点击回今天按钮:返回今天所在月份");
+               //需要先判断界面是否存在
+               if(WomenHealthView::GetInstance() != nullptr)
+               {
+                   WomenHealthView::GetInstance()->BackToToday();
+               }
+           }
+       }
+       return true;
+    }
  
      bool WomenHealthPresenter::OnDragEnd(OHOS::UIView &view, const OHOS::DragEvent &event)
      {
              if (event.GetPreLastPoint().x - event.GetStartPoint().x > 100)
                  NativeAbility::GetInstance().Back();
          }
-         if (event.GetDragDirection() == DragEvent::DIRECTION_BOTTOM_TO_TOP)
-         {
-             // if(event.GetPreLastPoint().y-event.GetStartPoint().y>100)
-             WomenHealthView::GetInstance()->updata_label(2);
-         }
-         if (event.GetDragDirection() == DragEvent::DIRECTION_TOP_TO_BOTTOM)
-         {
-             // if(event.GetPreLastPoint().y-event.GetStartPoint().y>100)
-             WomenHealthView::GetInstance()->updata_label(1);
-         }
+        //  if (event.GetDragDirection() == DragEvent::DIRECTION_BOTTOM_TO_TOP)
+        //  {
+        //      // if(event.GetPreLastPoint().y-event.GetStartPoint().y>100)
+        //      WomenHealthView::GetInstance()->updata_label(2);
+        //  }
+        //  if (event.GetDragDirection() == DragEvent::DIRECTION_TOP_TO_BOTTOM)
+        //  {
+        //      // if(event.GetPreLastPoint().y-event.GetStartPoint().y>100)
+        //      WomenHealthView::GetInstance()->updata_label(1);
+        //  }
          return true;
      }
  
index a109983..96c78d4 100644 (file)
  #include "NativeAbility.h"
  #include "ConfigModel.h"
  #include "languagecode/LanguageInit.h"
- namespace OHOS
- {
- 
-     static WomenHealthView *g_pMainView_WomenHealthView = nullptr;
- 
-     static char *dial_id_str[] = {"7", "8", "9", "C", "%", "4", "5", "6", "÷", "x", "1", "2", "3", "-", "+", "", "0", ".", "=", ""};
- 
-     static constexpr int16_t PULLUP_ANIMATOR_VIEW_X = 213;
-     static constexpr int16_t PULLUP_ANIMATOR_VIEW_Y = 380;
-     static constexpr int16_t PULLUP_ANIMATOR_VIEW_W = 40;
-     static constexpr int16_t PULLUP_ANIMATOR_VIEW_H = 40;
-     static constexpr int16_t PULLUP_ANIMATOR_VIEW_NUM_FRAMES = 70;
-     static constexpr int16_t PULLUP_ANIMATOR_VIEW_TIME = 100;
- 
-     static constexpr const char *PullUpPaths = "/user/res/weather/PullUp/PullUp_";
- 
-     static constexpr const char *stepPaths = "/user/res/step/";
- 
-     WomenHealthView::WomenHealthView()
-     {
-         g_pMainView_WomenHealthView = this;
-     }
- 
-     WomenHealthView::~WomenHealthView()
-     {
-         g_pMainView_WomenHealthView = nullptr;
-         if (group)
-         {
-             group->RemoveAll();
- 
-             if (mon_label)
-             {
-                 delete mon_label;
-                 mon_label = nullptr;
-             }
- 
-             if (imageview)
-             {
-                 delete imageview;
-                 imageview = nullptr;
-             }
- 
-             for (int i = 0; i < 7; i++)
-             {
-                 if (week_label[i])
-                 {
-                     delete week_label[i];
-                     week_label[i] = nullptr;
-                 }
-             }
- 
-             for (int i = 0; i < 31; i++)
-             {
-                 if (day_label[i])
-                 {
-                     delete day_label[i];
-                     day_label[i] = nullptr;
-                 }
-             }
- 
-             if (PullUpAnimatorView != nullptr)
-             {
-                 PullUpAnimatorView->Stop();
-                 delete PullUpAnimatorView;
-                 PullUpAnimatorView = nullptr;
-             }
- 
-             FreeImageInfoArray(PullUpimageAnimator_imageInfo, PullUpPaths, PULLUP_ANIMATOR_VIEW_NUM_FRAMES);
- 
-             delete group;
-             group = nullptr;
-         }
- 
-         g_pMainView_WomenHealthView = nullptr;
-     }
- 
-     WomenHealthView *WomenHealthView::GetInstance()
-     {
-         return g_pMainView_WomenHealthView;
-     }
-     static char *week_Z_str[] = {"一", "二", "三", "四", "五", "六", "日"};
-     static char *week_E_str[] = {"MON", "THE", "WED", "THU", "FRI", "SAT", "SUN"};
- 
-     bool WomenHealthView::updata_label(int8_t type)
-     {
-         for (int i = 0; i < 31; i++)
-         {
-             day_label[i]->SetVisible(false);
-         }
-         imageview->SetVisible(false);
- 
-         if (type == 1)
-         {
-             show_m--;
-             if (show_m == 0)
-             {
-                 show_m = 12;
-                 show_y--;
-             }
-         }
-         else
-         {
-             show_m++;
-             if (show_m == 13)
-             {
-                 show_m = 1;
-                 show_y++;
-             }
-         }
-         uint8_t mon_max_day = 0;
-         uint8_t is_run = 0;
-         if (show_y % 4 == 0 && show_y % 100 != 0 || show_y % 400 == 0)
-         {
-             is_run = 1;
-         }
- 
-         if (show_m == 2)
-         {
-             mon_max_day = 28 + is_run;
-         }
-         else if (show_m == 1 || show_m == 3 || show_m == 5 || show_m == 7 || show_m == 8 || show_m == 10 || show_m == 12)
-         {
-             mon_max_day = 31;
-         }
-         else
-         {
-             mon_max_day = 30;
-         }
- 
-         int y = show_y;
-         int m = show_m;
-         int week = 0;
-         {
-             if (m == 1 || m == 2)
-             {
-                 m += 12;
-                 y--;
-             }
-             week = (1 + 2 * m + 3 * (m + 1) / 5 + y + y / 4 - y / 100 + y / 400) % 7;
-         }
- 
-         char mon[20] = {0};
-         sprintf(mon, "%d.%d", show_y, show_m);
-         mon_label->SetText(mon);
- 
-         for (int i = 0; i < mon_max_day; i++)
-         {
-             int x = ((i + week) % 7);
-             int y = ((i + week) / 7);
-             day_label[i]->SetPosition(58 + 50 * x, 140 + 44 * y); // widget's left position and top position
-             char day[5];
-             sprintf(day, "%d", i + 1);
-             ;
-             day_label[i]->SetText(day);
-             time_t currtime;
-             time(&currtime);
-             struct tm *timeinfo;
-             timeinfo = localtime(&currtime);
-             int y_ = timeinfo->tm_year + 1900;
-             int m_ = timeinfo->tm_mon + 1;
-             int d_ = timeinfo->tm_mday;
-             if (i + 1 == d_ && show_y == y_ && show_m == m_)
-             {
-                 imageview->SetPosition(58 + 50 * x, 140 + 44 * y);
-                 imageview->SetVisible(true);
-             }
-             day_label[i]->SetVisible(true);
-         }
-         RootView::GetInstance()->Invalidate();
-         return true;
-     }
-     bool WomenHealthView::Label_init()
-     {
-         // Add Label to App
-         uint8_t mon_max_day = 0;
- 
-         uint8_t is_run = 0;
-         time_t currtime;
-         time(&currtime);
-         struct tm *timeinfo;
-         timeinfo = localtime(&currtime);
-         int y = timeinfo->tm_year + 1900;
-         int m = timeinfo->tm_mon + 1;
-         int d = timeinfo->tm_mday;
-         int h = timeinfo->tm_hour;
-         int min = timeinfo->tm_min;
-         int week = timeinfo->tm_wday;
-         WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "%d,%d,%d,%d", y, m, d, week);
-         if (y % 4 == 0 && y % 100 != 0 || y % 400 == 0) //
-         {
-             is_run = 1;
-         }
- 
-         if (m == 2)
-         {
-             mon_max_day = 28 + is_run;
-         }
-         else if (m == 1 ||
-                  m == 3 ||
-                  m == 5 ||
-                  m == 7 ||
-                  m == 8 ||
-                  m == 10 ||
-                  m == 12)
-         {
-             mon_max_day = 31;
-         }
-         else
-         {
-             mon_max_day = 30;
-         }
- 
-         show_y = y;
-         show_m = m;
-         show_d = d;
- 
-         if (mon_label == nullptr)
-         {
-             mon_label = new UILabel();
-         }
-         mon_label->SetPosition(83, 50); // widget's left position and top position
-         mon_label->Resize(300, 35);     // widget's width and height
-         mon_label->SetViewId("label1"); // Set style
-         mon_label->SetStyle(STYLE_TEXT_FONT, 30);
- 
-         char mon[20] = {0};
-         sprintf(mon, "%d.%d", y, m);
- 
-         if (m == 1 || m == 2)
-         {
-             m += 12;
-             y--;
-         }
-         week = (1 + 2 * m + 3 * (m + 1) / 5 + y + y / 4 - y / 100 + y / 400) % 7;
- 
-         mon_label->SetText(mon);
-         mon_label->SetLineBreakMode(UILabel::LINE_BREAK_WRAP);
-         mon_label->SetAlign(TEXT_ALIGNMENT_CENTER, TEXT_ALIGNMENT_CENTER);
-         mon_label->SetRollSpeed(0);
-         mon_label->SetFont(DEFAULT_VECTOR_FONT_FILENAME, 30);
- 
-         // Add to rootView
-         group->Add(mon_label);
- 
-         for (int i = 0; i < 7; i++)
-         {
-             if (week_label[i] == nullptr)
-             {
-                 week_label[i] = new UILabel();
-             }
-             week_label[i]->SetPosition(58 + 50 * (i), 110); // widget's left position and top position
-             week_label[i]->Resize(50, 30);                  // widget's width and height
-             week_label[i]->SetViewId("label3");             // Set style
-             week_label[i]->SetStyle(STYLE_TEXT_FONT, 20);
- 
-             if (ConfigModel::GetInstance()->GetLanguage() == ZH_CN)
-                 week_label[i]->SetText(week_Z_str[i]);
-             else
-                 week_label[i]->SetText(week_E_str[i]);
- 
-             week_label[i]->SetLineBreakMode(UILabel::LINE_BREAK_WRAP);
-             week_label[i]->SetTextColor(Color::GetColorFromRGBA(0x66, 0x66, 0x66, 0xff));
-             week_label[i]->SetAlign(TEXT_ALIGNMENT_CENTER, TEXT_ALIGNMENT_CENTER);
-             week_label[i]->SetRollSpeed(0);
-             week_label[i]->SetFont(DEFAULT_VECTOR_FONT_FILENAME, 20);
- 
-             group->Add(week_label[i]);
-             week_label[i]->SetVisible(true);
-         }
-         // Add Label to App
-         if (imageview == nullptr)
-         {
-             imageview = new UIImageView();
-         }
- 
-         imageview->SetPosition(58, 140);
-         imageview->Resize(50, 50);
-         imageview->SetViewId("image1");
-         imageview->SetStyle(STYLE_BACKGROUND_COLOR, 0xffff5a36);
-         imageview->SetStyle(STYLE_BACKGROUND_OPA, 0xff);
-         imageview->SetStyle(STYLE_BORDER_RADIUS, 100);
-         group->Add(imageview);
-         imageview->SetVisible(false);
- 
-         for (int i = 0; i < 31; i++)
-         {
-             if (day_label[i] == nullptr)
-             {
-                 day_label[i] = new UILabel();
-             }
- 
-             day_label[i]->SetPosition(58, 140); // widget's left position and top position
-             day_label[i]->Resize(50, 44);       // widget's width and height
-             day_label[i]->SetViewId("label3");  // Set style
-             day_label[i]->SetStyle(STYLE_TEXT_FONT, 20);
- 
-             day_label[i]->SetStyle(STYLE_BORDER_RADIUS, 100);
- 
-             day_label[i]->SetLineBreakMode(UILabel::LINE_BREAK_ELLIPSIS);
-             day_label[i]->SetAlign(TEXT_ALIGNMENT_CENTER, TEXT_ALIGNMENT_CENTER);
-             day_label[i]->SetRollSpeed(0);
-             day_label[i]->SetFont(DEFAULT_VECTOR_FONT_FILENAME, 30);
- 
-             group->Add(day_label[i]);
-             day_label[i]->SetVisible(false);
-         }
-         for (int i = 0; i < mon_max_day; i++)
-         {
-             int x = ((i + week) % 7);
-             int y = ((i + week) / 7);
-             day_label[i]->SetPosition(58 + 50 * x, 140 + 44 * y); // widget's left position and top position
-             char day[5];
-             sprintf(day, "%d", i + 1);
-             ;
-             day_label[i]->SetText(day);
-             if (i + 1 == d)
-             {
-                 imageview->SetPosition(58 + 50 * x, 140 + 44 * y);
-                 imageview->SetVisible(true);
-             }
-             day_label[i]->SetVisible(true);
-         }
- 
-         PullUpimageAnimator_imageInfo = CreateImageInfoArray(PullUpPaths, PULLUP_ANIMATOR_VIEW_NUM_FRAMES);
-         if (PullUpAnimatorView == nullptr)
-         {
-             PullUpAnimatorView = new UIImageAnimatorView();
-             if (PullUpAnimatorView == nullptr)
-             {
-                 WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "PullUpAnimatorView new fail");
-                 return false;
-             }
-             for (uint8_t i = 0; i < PULLUP_ANIMATOR_VIEW_NUM_FRAMES; i++)
-             {
-                 // PullUpimageAnimatorInfo[i].imageInfo = ImageCacheManager::GetInstance().LoadSingleRes(PullUpPathsArray[i]);
-                 // PullUpimageAnimatorInfo[i].imageType = IMG_SRC_IMAGE_INFO;
-                 PullUpimageAnimatorInfo[i].imageInfo = PullUpimageAnimator_imageInfo[i];
-                 // PullUpPathsArray[i];
-                 PullUpimageAnimatorInfo[i].imageType = IMG_SRC_IMAGE_INFO;
-                 PullUpimageAnimatorInfo[i].pos.x = PULLUP_ANIMATOR_VIEW_X;
-                 PullUpimageAnimatorInfo[i].pos.y = PULLUP_ANIMATOR_VIEW_Y;
-                 PullUpimageAnimatorInfo[i].width = PULLUP_ANIMATOR_VIEW_W;
-                 PullUpimageAnimatorInfo[i].height = PULLUP_ANIMATOR_VIEW_H;
-             }
-             PullUpAnimatorView->SetPosition(PULLUP_ANIMATOR_VIEW_X, PULLUP_ANIMATOR_VIEW_Y, PULLUP_ANIMATOR_VIEW_W, PULLUP_ANIMATOR_VIEW_H);
-             PullUpAnimatorView->SetStyle(STYLE_BACKGROUND_COLOR, 0xffffffff);
-             PullUpAnimatorView->SetStyle(STYLE_BACKGROUND_OPA, 0xff);
-             PullUpAnimatorView->SetImageAnimatorSrc(PullUpimageAnimatorInfo, PULLUP_ANIMATOR_VIEW_NUM_FRAMES, PULLUP_ANIMATOR_VIEW_TIME);
-             PullUpAnimatorView->SetRepeat(true);
-             PullUpAnimatorView->Start();
-         }
-         group->Add(PullUpAnimatorView);
- 
-         return true;
-     }
- 
-     void WomenHealthView::OnStart()
-     {
-         group = new UIViewGroup();
-         if (group == nullptr)
-         {
-             WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "CallingView::UIViewGroup::new group error");
-             return;
-         }
-         group->SetPosition(0, 0);
-         group->Resize(VERTICAL_RESOLUTION, HORIZONTAL_RESOLUTION); // 454 : value
-         group->SetTouchable(true);
-         group->SetDraggable(true);
-         group->SetOnDragListener(presenter_);
-         AddViewToRootContainer(group);
- 
-         if (!Label_init())
-         {
-             WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "CallingView::UIViewGroup::new group error");
-             return;
-         }
-     }
- }
\ No newline at end of file
+namespace OHOS
+{
+    // 全局静态指针,用于获取当前View实例
+    static WomenHealthView *g_pMainView_WomenHealthView = nullptr;
+
+    /**
+     * @brief 构造函数 - 创建女性健康界面对象
+     * 作用:初始化全局实例指针,让其他地方可以通过GetInstance()获取这个对象
+     */
+    WomenHealthView::WomenHealthView()
+    {
+        g_pMainView_WomenHealthView = this; // 保存当前对象指针到全局变量
+    }
+
+    /**
+     * @brief 析构函数 - 销毁女性健康界面对象
+     * 作用:清理所有分配的内存,防止内存泄漏
+     * 包括:主容器、月份标签、星期标签、日期标签、今日标记、动画等
+     */
+    WomenHealthView::~WomenHealthView()
+    {
+        g_pMainView_WomenHealthView = nullptr;
+        if (group) // 如果主容器存在
+        {
+            group->RemoveAll(); // 移除所有子控件
+
+            // 删除月份标签(如:"2024.10")
+            if (mon_label)
+            {
+                delete mon_label;
+                mon_label = nullptr;
+            }
+
+            // 删除31个日期颜色标记圆圈
+            for (int i = 0; i < 31; i++)
+            {
+                if (dayMarker[i])
+                {
+                    delete dayMarker[i];
+                    dayMarker[i] = nullptr;
+                }
+            }
+
+            // 删除7个星期标签(一、二、三、四、五、六、日)
+            for (int i = 0; i < 7; i++)
+            {
+                if (week_label[i])
+                {
+                    delete week_label[i];
+                    week_label[i] = nullptr;
+                }
+            }
+
+            // 删除31个日期标签(1-31号)
+            for (int i = 0; i < 31; i++)
+            {
+                if (day_label[i])
+                {
+                    delete day_label[i];
+                    day_label[i] = nullptr;
+                }
+            }
+
+            // 删除顶部标题"生理周期"
+            if (title_label)
+            {
+                delete title_label;
+                title_label = nullptr;
+            }
+
+            // 删除日期标签"X月X日 星期X"
+            if (mon_label)
+            {
+                delete mon_label;
+                mon_label = nullptr;
+            }
+
+            // 删除左右箭头按钮 
+            if (left_arrow)
+            {
+                delete left_arrow;
+                left_arrow = nullptr;
+            }
+            if (right_arrow)
+            {
+                delete right_arrow;
+                right_arrow = nullptr;
+            }
+
+            // 删除底部"编辑"按钮
+            if (edit_button)
+            {
+                delete edit_button;
+                edit_button = nullptr;
+            }
+          
+            // 删除主容器
+            delete group;
+            group = nullptr;
+        }
+
+        g_pMainView_WomenHealthView = nullptr;
+    }
+
+    /**
+     * @brief 获取女性健康界面的单例对象
+     * @return 返回当前女性健康界面的指针
+     * 作用:其他地方可以通过这个函数获取界面对象,进行界面更新等操作
+     */
+    WomenHealthView *WomenHealthView::GetInstance()
+    {
+        return g_pMainView_WomenHealthView;
+    }
+    
+    /**
+     * @brief 判断当前是否显示今天所在月份
+     * @return true=当前显示今天所在月份, false=显示其他月份
+     * 
+     * 作用:供Presenter调用,判断应该执行"编辑"还是"回今天"功能
+     */
+    bool WomenHealthView::IsShowingCurrentMonth()
+    {
+        return (show_y == today_y && show_m == today_m);
+    }
+    
+    // 中文星期标签数组
+    static char *week_Z_str[] = {"一", "二", "三", "四", "五", "六", "日"};
+    // 英文星期标签数组
+    static char *week_E_str[] = {"MON", "THE", "WED", "THU", "FRI", "SAT", "SUN"};
+
+    /**
+     * @brief 计算某月有多少天
+     * @param year 年份
+     * @param month 月份(1-12)
+     * @return 该月的天数
+     */
+    int WomenHealthView::CalculateMonthDays(int year, int month)
+    {
+        // 判断是否闰年
+        bool isLeapYear = (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0);
+        
+        if (month == 2) {
+            return isLeapYear ? 29 : 28;  // 2月
+        } else if (month == 1 || month == 3 || month == 5 || month == 7 || 
+                   month == 8 || month == 10 || month == 12) {
+            return 31;  // 大月
+        } else {
+            return 30;  // 小月
+        }
+    }
+    
+    /**
+     * @brief 使用系统函数计算星期几(更准确)
+     * @param year 年份
+     * @param month 月份(1-12)
+     * @param day 日期
+     * @return 星期几(0=星期日, 1=星期一, ..., 6=星期六)
+     * 
+     * 使用系统的 mktime 和 localtime 函数来计算星期,避免手动实现蔡勒公式可能的错误
+     */
+    int WomenHealthView::CalculateWeekday(int year, int month, int day)
+    {
+        struct tm timeStruct = {0};
+        timeStruct.tm_year = year - 1900;  // tm_year是从1900年开始
+        timeStruct.tm_mon = month - 1;     // tm_mon是0-11
+        timeStruct.tm_mday = day;
+        
+        // 使用mktime来规范化时间结构,并自动计算星期
+        time_t t = mktime(&timeStruct);
+        if (t == -1) {
+            // 如果转换失败,使用蔡勒公式作为备用
+            int y = year;
+            int m = month;
+            if (m == 1 || m == 2) {
+                m += 12;
+                y--;
+            }
+            int w = (day + 2 * m + 3 * (m + 1) / 5 + y + y / 4 - y / 100 + y / 400 + 1) % 7;
+            return (w + 6) % 7;
+        }
+        
+        // 获取规范化后的时间结构
+        struct tm *result = localtime(&t);
+        
+        // tm_wday: 0=星期日, 1=星期一, ..., 6=星期六(正好符合我们的需求)
+        return result->tm_wday;
+    }
+    
+    /**
+     * @brief 初始化31个颜色标记圆圈
+     * 
+     * 作用:创建用于标记月经期、排卵期等状态的圆圈
+     * 注意:必须先添加到容器,这样才会显示在日期标签下方
+     */
+    void WomenHealthView::InitDayMarkers()
+    {
+        for (int i = 0; i < 31; i++) {
+            if (dayMarker[i] == nullptr) {
+                dayMarker[i] = new UIImageView();
+                if (dayMarker[i] != nullptr) {
+                    dayMarker[i]->Resize(46, 46);
+                    dayMarker[i]->SetStyle(STYLE_BACKGROUND_OPA, 0xff);
+                    dayMarker[i]->SetStyle(STYLE_BORDER_RADIUS, 23);
+                    group->Add(dayMarker[i]);
+                    dayMarker[i]->SetVisible(false);  // 默认隐藏
+                }
+            }
+        }
+    }
+    
+    /**
+     * @brief 初始化顶部标题"生理周期"
+     */
+    void WomenHealthView::InitTitleLabel()
+    {
+        if (title_label == nullptr) {
+            title_label = new UILabel();
+        }
+        
+        title_label->SetPosition(0, 20);      // 顶部中央
+        title_label->Resize(454, 40);         // 全屏宽度
+        title_label->SetText("生理周期");
+        title_label->SetStyle(STYLE_TEXT_FONT, 28);
+        title_label->SetAlign(TEXT_ALIGNMENT_CENTER, TEXT_ALIGNMENT_CENTER);
+        title_label->SetLineBreakMode(UILabel::LINE_BREAK_WRAP);
+        title_label->SetRollSpeed(0);
+        title_label->SetFont(DEFAULT_VECTOR_FONT_FILENAME, 28);
+        title_label->SetTextColor(Color::White());
+        
+        group->Add(title_label);
+    }
+    
+    /**
+     * @brief 初始化日期标签(显示"X月X日 星期X")
+     * @param year 年份
+     * @param month 月份
+     * @param day 日期(当前日期)
+     * @param weekday 星期几
+     */
+    void WomenHealthView::InitMonthLabel(int year, int month, int day, int weekday)
+    {
+        if (mon_label == nullptr) {
+            mon_label = new UILabel();
+        }
+        
+        mon_label->SetPosition(100, 75);   // 标题下方,中央位置(左右留出箭头空间)
+        mon_label->Resize(254, 35);        // 宽度留给左右箭头
+        mon_label->SetViewId("label1");
+        mon_label->SetStyle(STYLE_TEXT_FONT, 24);
+        
+        // 格式化日期文本:"9月5日 星期五"
+        static const char* weekday_str[] = {"星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"};
+        char date_text[50] = {0};
+        int wd = CalculateWeekday(year, month, day);  // 计算星期几
+        sprintf(date_text, "%d月%d日 %s", month, day, weekday_str[wd]);
+        mon_label->SetText(date_text);
+        
+        mon_label->SetLineBreakMode(UILabel::LINE_BREAK_WRAP);
+        mon_label->SetAlign(TEXT_ALIGNMENT_CENTER, TEXT_ALIGNMENT_CENTER);
+        mon_label->SetRollSpeed(0);
+        mon_label->SetFont(DEFAULT_VECTOR_FONT_FILENAME, 24);
+        mon_label->SetTextColor(Color::White());
+        
+        group->Add(mon_label);
+    }
+    
+    /**
+     * @brief 初始化左右箭头按钮
+     */
+    void WomenHealthView::InitArrowButtons()
+    {
+        // 左箭头按钮
+        if (left_arrow == nullptr) {
+            left_arrow = new UILabelButton();
+        }
+        left_arrow->SetPosition(40, 50);   // 日期左侧
+        left_arrow->Resize(80, 80);
+        left_arrow->SetText("<");
+        left_arrow->SetStyle(STYLE_TEXT_FONT, 30);
+        left_arrow->SetStyle(STYLE_LINE_HEIGHT, 35);
+        left_arrow->SetFont(DEFAULT_VECTOR_FONT_FILENAME, 30);
+
+        left_arrow->SetViewId(PREV_MONTH);
+        // 设置按钮背景样式
+        left_arrow->SetStyle(STYLE_BACKGROUND_COLOR, OPA_OPAQUE);
+        left_arrow->SetStyle(STYLE_BACKGROUND_OPA, OPA_OPAQUE);
+        left_arrow->SetStyleForState(STYLE_BACKGROUND_COLOR, OPA_OPAQUE, UIButton::PRESSED);
+        left_arrow->SetStyleForState(STYLE_BACKGROUND_OPA, OPA_OPAQUE, UIButton::PRESSED);
+        left_arrow->SetStyle(STYLE_BORDER_RADIUS, 100);
+        UIView::OnClickListener *clickListener = (UIView::OnClickListener *)OHOS::WomenHealthPresenter::GetInstance();
+        left_arrow->SetOnClickListener(clickListener);
+ 
+        group->Add(left_arrow);
+        
+        // 右箭头按钮
+        if (right_arrow == nullptr) {
+            right_arrow = new UILabelButton();
+        }
+        right_arrow->SetPosition(320, 50);  // 日期右侧
+        right_arrow->Resize(80, 80);
+        right_arrow->SetText(">");
+        right_arrow->SetStyle(STYLE_TEXT_FONT, 30);
+        right_arrow->SetStyle(STYLE_LINE_HEIGHT, 35);
+        right_arrow->SetFont(DEFAULT_VECTOR_FONT_FILENAME, 30);
+
+        right_arrow->SetViewId(NEXT_MONTH);
+        // 设置按钮背景样式
+        right_arrow->SetStyle(STYLE_BACKGROUND_COLOR, OPA_OPAQUE);
+        right_arrow->SetStyle(STYLE_BACKGROUND_OPA, OPA_OPAQUE);
+        right_arrow->SetStyleForState(STYLE_BACKGROUND_COLOR, OPA_OPAQUE, UIButton::PRESSED);
+        right_arrow->SetStyleForState(STYLE_BACKGROUND_OPA, OPA_OPAQUE, UIButton::PRESSED);
+        right_arrow->SetStyle(STYLE_BORDER_RADIUS, 100);
+        UIView::OnClickListener *clickListener2 = (UIView::OnClickListener *)OHOS::WomenHealthPresenter::GetInstance();
+        right_arrow->SetOnClickListener(clickListener2);
+ 
+        group->Add(right_arrow);
+    }
+    
+    /**
+     * @brief 初始化底部"编辑"按钮
+     */
+    void WomenHealthView::InitEditButton()
+    {
+        if (edit_button == nullptr) {
+            edit_button = new UILabelButton();
+        }
+        
+        edit_button->SetPosition(118, 350);  // 底部中央
+        edit_button->Resize(230, 80);
+        edit_button->SetText("编辑");
+        edit_button->SetStyle(STYLE_TEXT_FONT, 30);
+        edit_button->SetStyle(STYLE_LINE_HEIGHT, 35);
+        edit_button->SetFont(DEFAULT_VECTOR_FONT_FILENAME, 30);
+        edit_button->SetViewId(EDIT);
+        // 设置按钮背景样式
+        edit_button->SetStyle(STYLE_BACKGROUND_COLOR, OPA_OPAQUE);
+        edit_button->SetStyle(STYLE_BACKGROUND_OPA, OPA_OPAQUE);
+        edit_button->SetStyleForState(STYLE_BACKGROUND_COLOR, OPA_OPAQUE, UIButton::PRESSED);
+        edit_button->SetStyleForState(STYLE_BACKGROUND_OPA, OPA_OPAQUE, UIButton::PRESSED);
+        edit_button->SetStyle(STYLE_BORDER_RADIUS, 100);
+        UIView::OnClickListener *clickListener = (UIView::OnClickListener *)OHOS::WomenHealthPresenter::GetInstance();
+        edit_button->SetOnClickListener(clickListener);
+        
+        group->Add(edit_button);
+    }
+    
+    /**
+     * @brief 初始化7个星期标签(一、二、三、四、五、六、日)
+     * 
+     * 作用:显示日历的星期头部
+     * 注意:根据设计图要求,暂时不显示星期行
+     */
+    void WomenHealthView::InitWeekLabels()
+    {
+        for (int i = 0; i < 7; i++) {
+            if (week_label[i] == nullptr) {
+                week_label[i] = new UILabel();
+            }
+            
+            // 设置位置:横向排列,起始X=58,每个间隔50像素
+            week_label[i]->SetPosition(58 + 50 * i, 110);
+            week_label[i]->Resize(50, 30);
+            week_label[i]->SetViewId("label3");
+            week_label[i]->SetStyle(STYLE_TEXT_FONT, 20);
+            
+            // 根据系统语言设置中文或英文
+            if (ConfigModel::GetInstance()->GetLanguage() == ZH_CN) {
+                week_label[i]->SetText(week_Z_str[i]);  // 中文:"一"、"二"等
+            } else {
+                week_label[i]->SetText(week_E_str[i]);  // 英文:"MON"、"TUE"等
+            }
+            
+            week_label[i]->SetLineBreakMode(UILabel::LINE_BREAK_WRAP);
+            week_label[i]->SetTextColor(Color::GetColorFromRGBA(0x66, 0x66, 0x66, 0xff));  // 灰色
+            week_label[i]->SetAlign(TEXT_ALIGNMENT_CENTER, TEXT_ALIGNMENT_CENTER);
+            week_label[i]->SetRollSpeed(0);
+            week_label[i]->SetFont(DEFAULT_VECTOR_FONT_FILENAME, 20);
+            
+            group->Add(week_label[i]);
+            week_label[i]->SetVisible(false);  // 暂时隐藏星期行(按设计图要求)
+        }
+    }
+    
+    /**
+     * @brief 初始化31个日期标签UI对象(只创建,不设置内容)
+     * 
+     * 作用:预先创建所有可能用到的日期标签对象
+     * 注意:因为去掉了星期行,日期起始Y坐标调整为120(原来是140)
+     */
+    void WomenHealthView::InitDayLabels()
+    {
+        for (int i = 0; i < 31; i++) {
+            if (day_label[i] == nullptr) {
+                day_label[i] = new UILabel();
+            }
+            
+            day_label[i]->SetPosition(58, 120);  // 初始位置(往上移了20像素)
+            day_label[i]->Resize(50, 44);
+            day_label[i]->SetViewId("label3");
+            day_label[i]->SetStyle(STYLE_TEXT_FONT, 20);
+            day_label[i]->SetStyle(STYLE_BORDER_RADIUS, 100);
+            
+            day_label[i]->SetLineBreakMode(UILabel::LINE_BREAK_ELLIPSIS);
+            day_label[i]->SetAlign(TEXT_ALIGNMENT_CENTER, TEXT_ALIGNMENT_CENTER);
+            day_label[i]->SetRollSpeed(0);
+            day_label[i]->SetFont(DEFAULT_VECTOR_FONT_FILENAME, 30);
+            
+            group->Add(day_label[i]);
+            day_label[i]->SetVisible(false);  // 默认隐藏
+        }
+    }
+    
+    /**
+     * @brief 更新底部按钮文本
+     * 
+     * 作用:根据当前显示的月份,动态修改按钮文本
+     * 规则:
+     * - 如果当前显示的是今天所在月份 → 显示"编辑"
+     * - 如果当前显示的不是今天所在月份 → 显示"回今天"
+     */
+    void WomenHealthView::UpdateEditButtonText()
+    {
+        if (edit_button == nullptr) {
+            return;
+        }
+        
+        // 判断当前显示的是否是今天所在月份
+        if (show_y == today_y && show_m == today_m) {
+            edit_button->SetText("编辑");
+        } else {
+            edit_button->SetText("回今天");
+        }
+    }
+    
+    /**
+     * @brief 回到今天所在的月份
+     * 
+     * 作用:点击"回今天"按钮时调用,将界面切换回今天所在的月份
+     */
+    void WomenHealthView::BackToToday()
+    {
+        WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "回到今天所在月份: %d年%d月", today_y, today_m);
+        
+        // 第一步:隐藏所有日期标签和颜色标记
+        for (int i = 0; i < 31; i++) {
+            day_label[i]->SetVisible(false);
+            if (dayMarker[i]) {
+                dayMarker[i]->SetVisible(false);
+            }
+        }
+        
+        // 第二步:恢复到今天的年月
+        show_y = today_y;
+        show_m = today_m;
+        show_d = today_d;
+        
+        // 第三步:计算天数和星期
+        int mon_max_day = CalculateMonthDays(show_y, show_m);
+        int weekday = CalculateWeekday(show_y, show_m, 1);
+        
+        // 第四步:更新日期标签
+        static const char* weekday_str[] = {"星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"};
+        char date_text[50] = {0};
+        int wd = CalculateWeekday(show_y, show_m, show_d);
+        sprintf(date_text, "%d月%d日 %s", show_m, show_d, weekday_str[wd]);
+        mon_label->SetText(date_text);
+        
+        // 第五步:更新日期显示
+        UpdateDayDisplay(show_y, show_m, mon_max_day, weekday);
+        
+        // 第六步:更新箭头和按钮状态
+        UpdateArrowButtonsVisibility();
+        UpdateEditButtonText();
+        
+        // 第七步:刷新界面
+        RootView::GetInstance()->Invalidate();
+    }
+    
+    /**
+     * @brief 更新左右箭头按钮的显示状态
+     * 
+     * 作用:根据当前显示的月份,判断是否显示左右箭头按钮
+     * 规则:
+     * 1. 如果当前月 = 经期开始月,隐藏左箭头(不能查看更早的月份)
+     * 2. 如果当前月 = 预测的最后一个月,隐藏右箭头(不能查看更晚的月份)
+     */
+    void WomenHealthView::UpdateArrowButtonsVisibility()
+    {
+        WomenHealthModel* model = WomenHealthModel::GetInstance();
+        
+        // 如果还没有设置经期数据,显示所有箭头
+        if (!model->HasMenstrualData()) {
+            if (left_arrow) left_arrow->SetVisible(true);
+            if (right_arrow) right_arrow->SetVisible(true);
+            return;
+        }
+        
+        // 获取经期开始的年月
+        int startYear = 0, startMonth = 0;
+        model->GetMenstrualStartYearMonth(startYear, startMonth);
+        
+        // 获取预测的最后一个月
+        int lastYear = 0, lastMonth = 0;
+        model->GetLastPredictYearMonth(lastYear, lastMonth);
+        
+        // 判断是否显示左箭头:当前月 == 经期开始月 时隐藏
+        if (left_arrow) {
+            if (show_y == startYear && show_m == startMonth) {
+                left_arrow->SetVisible(false);  // 已经是最早的月份,隐藏左箭头
+            } else {
+                left_arrow->SetVisible(true);
+            }
+        }
+        
+        // 判断是否显示右箭头:当前月 == 预测最后一个月 时隐藏
+        if (right_arrow) {
+            if (lastYear != 0 && show_y == lastYear && show_m == lastMonth) {
+                right_arrow->SetVisible(false);  // 已经是最后的月份,隐藏右箭头
+            } else {
+                right_arrow->SetVisible(true);
+            }
+        }
+    }
+    
+    /**
+     * @brief 更新日期显示(显示当月所有日期并绘制状态标记)
+     * @param year 年份
+     * @param month 月份
+     * @param maxDays 该月最大天数
+     * @param weekday 1号是星期几
+     */
+    void WomenHealthView::UpdateDayDisplay(int year, int month, int maxDays, int weekday)
+    {
+        // 显示当月的所有日期
+        for (int i = 0; i < maxDays; i++) {
+            // 计算该日期在日历表格中的位置
+            int x = (i + weekday) % 7;  // 列位置(0-6)
+            int y = (i + weekday) / 7;  // 行位置(0-5)
+            
+            // 计算屏幕坐标(Y坐标从120开始,因为去掉了星期行)
+            int posX = 58 + 50 * x;
+            int posY = 120 + 44 * y;
+            
+            // 设置日期标签位置和文本
+            day_label[i]->SetPosition(posX, posY);
+            char day[5];
+            sprintf(day, "%d", i + 1);
+            day_label[i]->SetText(day);
+            
+            // 判断该日期的状态并绘制颜色标记
+            DayStatus status = GetDayStatus(year, month, i + 1);
+            DrawDayMarker(i, posX, posY, status);
+            
+            day_label[i]->SetVisible(true);
+        }
+        
+        // 隐藏多余的日期标签(如果从大月切换到小月)
+        for (int i = maxDays; i < 31; i++) {
+            day_label[i]->SetVisible(false);
+            dayMarker[i]->SetVisible(false);
+        }
+    }
+
+    /**
+     * @brief 判断某一天的状态
+     * @param year 年份
+     * @param month 月份
+     * @param day 日期
+     * @return DayStatus 返回该日期的状态
+     * 
+     * 作用:根据女性健康数据模型,判断某天是月经期、排卵期、预测经期还是普通日
+     * 
+     * 判断优先级(从高到低):
+     * 1. 今天(灰色)
+     * 2. 已记录月经期(红色)
+     * 3. 当前排卵期(蓝色)
+     * 4. 预测排卵期(蓝色) ← 新增
+     * 5. 预测月经期(粉色)
+     * 6. 普通日期(白色)
+     */
+    DayStatus WomenHealthView::GetDayStatus(uint32_t year, uint32_t month, uint32_t day)
+    {
+        // 获取当前系统时间
+        time_t now;
+        time(&now);
+        struct tm *nowInfo = localtime(&now);
+        uint32_t todayYear = nowInfo->tm_year + 1900;
+        uint32_t todayMonth = nowInfo->tm_mon + 1;
+        uint32_t todayDay = nowInfo->tm_mday;
+        
+        // 如果是今天,返回今天状态(灰色圆圈)
+        if (year == todayYear && month == todayMonth && day == todayDay) {
+            return DAY_STATUS_TODAY;
+        }
+        
+        // 从WomenHealthModel获取数据,判断该天所处的时期
+        WomenHealthModel* model = WomenHealthModel::GetInstance();
+        
+        // 判断优先级:
+        // 1. 优先判断是否在已记录的月经期内(最高优先级)
+        if (model->IsInMenstrualPeriod(year, month, day)) {
+            return DAY_STATUS_MENSTRUAL;  // 月经期(红色标记)
+        }
+        
+        // 2. 判断是否在排卵期内(包括当前排卵期)
+        if (model->IsInOvulationPeriod(year, month, day)) {
+            return DAY_STATUS_OVULATION;  // 排卵期(蓝色标记)
+        }
+        
+        // 3. 判断是否在预测排卵期内(下次和下下次的排卵期,也是蓝色)
+        if (model->IsInPredictOvulationPeriod(year, month, day)) {
+            return DAY_STATUS_OVULATION;  // 预测排卵期(蓝色标记)
+        }
+        
+        // 4. 判断是否在预测经期内
+        if (model->IsInPredictPeriod(year, month, day)) {
+            return DAY_STATUS_PREDICT;  // 预测经期(粉色标记)
+        }
+        
+        // 5. 普通日期
+        return DAY_STATUS_NORMAL;  // 普通日期(白色)
+    }
+
+    /**
+     * @brief 为指定日期绘制颜色标记圆圈
+     * @param dayIndex 日期索引(0-30,对应1-31号)
+     * @param x 圆圈的X坐标
+     * @param y 圆圈的Y坐标
+     * @param status 日期状态(决定圆圈颜色)
+     * 
+     * 作用:根据日期状态绘制不同颜色的圆圈背景
+     * - 月经期:红色 (0xFFFF5A5A)
+     * - 排卵期:蓝色 (0xFF5AB0FF)
+     * - 预测经期:浅红色 (0xFFFFB5B5)
+     * - 今天:灰色 (0xFF808080)
+     * - 普通日:不显示圆圈
+     */
+    void WomenHealthView::DrawDayMarker(int dayIndex, int x, int y, DayStatus status)
+    {
+        // 如果是普通日期,隐藏标记
+        if (status == DAY_STATUS_NORMAL) {
+            if (dayMarker[dayIndex]) {
+                dayMarker[dayIndex]->SetVisible(false);
+            }
+            return;
+        }
+        
+        // 如果标记对象不存在,创建它
+        if (dayMarker[dayIndex] == nullptr) {
+            dayMarker[dayIndex] = new UIImageView();
+            if (dayMarker[dayIndex] == nullptr) {
+                return;
+            }
+            dayMarker[dayIndex]->Resize(46,46);  // 圆圈大小46*46
+            dayMarker[dayIndex]->SetStyle(STYLE_BACKGROUND_OPA, 0xff);  // 不透明
+            dayMarker[dayIndex]->SetStyle(STYLE_BORDER_RADIUS, 23);     // 圆角23,形成圆形
+            group->Add(dayMarker[dayIndex]);
+        }
+        
+        // 根据状态设置颜色
+        uint32_t color = 0xFFFFFFFF;  // 默认白色
+        switch (status) {
+            case DAY_STATUS_MENSTRUAL:  // 月经期:红色
+                color = 0xFFFF5A5A;
+                break;
+            case DAY_STATUS_OVULATION:  // 排卵期:蓝色
+                color = 0xFF5AB0FF;
+                break;
+            case DAY_STATUS_PREDICT:    // 预测经期:浅红色
+                color = 0xFFFFB5B5;
+                break;
+            case DAY_STATUS_TODAY:      // 今天:灰色
+                color = 0xFF808080;
+                break;
+            default:
+                break;
+        }
+        
+        // 设置位置和颜色
+        dayMarker[dayIndex]->SetPosition(x, y);
+        dayMarker[dayIndex]->SetStyle(STYLE_BACKGROUND_COLOR, color);
+        dayMarker[dayIndex]->SetVisible(true);
+    }
+
+    /**
+     * @brief 更新日历标签显示(优化后的版本)
+     * @param type 切换类型:1=切换到上个月, 2=切换到下个月, 其他=刷新当前月
+     * @return 成功返回true,失败返回false
+     * 
+     * 作用:当用户上下滑动或点击箭头时,切换月份并重新显示日历
+     * 
+     * 工作流程:
+     * 1. 隐藏所有日期标签和标记
+     * 2. 获取边界月份(经期开始月和预测最后月)
+     * 3. 检查是否可以切换月份(防止超出边界)
+     * 4. 根据type参数计算新的年月
+     * 5. 更新日期标签"X月X日 星期X"
+     * 6. 调用UpdateDayDisplay更新显示
+     * 7. 更新箭头按钮显示状态
+     * 8. 刷新界面
+     */
+    bool WomenHealthView::updata_label(int8_t type)
+    {
+        // 第一步:隐藏所有日期标签和颜色标记
+        for (int i = 0; i < 31; i++) {
+            day_label[i]->SetVisible(false);
+            if (dayMarker[i]) {
+                dayMarker[i]->SetVisible(false);
+            }
+        }
+
+        // 第二步:获取Model数据,判断边界
+        WomenHealthModel* model = WomenHealthModel::GetInstance();
+        
+        // 如果还没有设置经期数据,允许自由切换月份
+        if (model->HasMenstrualData()) {
+            // 获取经期开始的年月
+            int startYear = 0, startMonth = 0;
+            model->GetMenstrualStartYearMonth(startYear, startMonth);
+            
+            // 获取预测的最后一个月
+            int lastYear = 0, lastMonth = 0;
+            model->GetLastPredictYearMonth(lastYear, lastMonth);
+            
+            // 第三步:检查边界,防止超出范围
+            if (type == 1) {  // 想要查看上个月
+                // 如果当前已经是经期开始的月份,不允许再往前
+                if (show_y == startYear && show_m == startMonth) {
+                    WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "已经是最早的月份,无法查看上个月");
+                    return false;
+                }
+            } else if (type == 2) {  // 想要查看下个月
+                // 如果当前已经是预测的最后一个月,不允许再往后
+                if (lastYear != 0 && show_y == lastYear && show_m == lastMonth) {
+                    WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "已经是最后的月份,无法查看下个月");
+                    return false;
+                }
+            }
+        }
+
+        // 第四步:根据滑动方向更新年月
+        if (type == 1) {  // 向上滑动或点击左箭头,显示上个月
+            show_m--;
+            if (show_m == 0) {  // 跨年到去年12月
+                show_m = 12;
+                show_y--;
+            }
+        } else {  // 向下滑动或点击右箭头,显示下个月
+            show_m++;
+            if (show_m == 13) {  // 跨年到明年1月
+                show_m = 1;
+                show_y++;
+            }
+        }
+        
+        // 第五步:使用辅助函数计算该月天数和1号星期几
+        int mon_max_day = CalculateMonthDays(show_y, show_m);
+        int weekday = CalculateWeekday(show_y, show_m, 1);
+
+        // 第六步:更新日期标签("X月X日 星期X"格式)
+        static const char* weekday_str[] = {"星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"};
+        char date_text[50] = {0};
+        int wd = CalculateWeekday(show_y, show_m, show_d);  // 使用当前保存的日期
+        sprintf(date_text, "%d月%d日 %s", show_m, show_d, weekday_str[wd]);
+        mon_label->SetText(date_text);
+ 
+        // 第七步:调用UpdateDayDisplay更新日期显示
+        UpdateDayDisplay(show_y, show_m, mon_max_day, weekday);
+        
+        // 第八步:更新箭头按钮的显示状态
+        UpdateArrowButtonsVisibility();
+        
+        // 第九步:更新底部按钮文本(编辑/回今天)
+        UpdateEditButtonText();
+        
+        // 第十步:刷新屏幕显示
+        RootView::GetInstance()->Invalidate();
+        return true;
+    }
+    /**
+     * @brief 初始化所有标签和UI组件
+     * @return 成功返回true,失败返回false
+     * 
+     * 作用:第一次进入界面时,创建所有需要的UI组件
+     * 
+     * 工作流程:
+     * 1. 获取当前系统时间
+     * 2. 计算当月天数和1号星期几
+     * 3. 创建并设置月份标签
+     * 4. 创建并设置7个星期标签
+     * 5. 创建今日标记圆圈
+     * 6. 创建31个日期标签
+     * 7. 显示当月所有日期
+     * 8. 创建上拉动画
+     */
+    /**
+     * @brief 初始化所有UI组件(重构后的简洁版本)
+     * 
+     * 作用:调用各个独立的初始化函数,降低耦合度
+     * 
+     * 工作流程:
+     * 1. 获取当前系统时间
+     * 2. 计算当月天数和1号星期几
+     * 3. 依次调用各个初始化函数
+     * 4. 更新日期显示
+     */
+    bool WomenHealthView::Label_init()
+    {
+        // 第一步:获取当前系统时间
+        time_t currtime;
+        time(&currtime);
+        struct tm *timeinfo = localtime(&currtime);
+        
+        int year = timeinfo->tm_year + 1900;   // 年份
+        int month = timeinfo->tm_mon + 1;       // 月份
+        int day = timeinfo->tm_mday;            // 日期
+        
+        WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "女性健康界面初始化: %d年%d月%d日", year, month, day);
+        
+        // 第二步:计算当月天数和1号星期几
+        int mon_max_day = CalculateMonthDays(year, month);
+        int weekday = CalculateWeekday(year, month, 1);  // 计算1号是星期几
+        
+        // 第三步:保存今天的日期(用于"回今天"功能)
+        today_y = year;
+        today_m = month;
+        today_d = day;
+        
+        // 第四步:保存当前显示的年月日(用于后续切换月份)
+        show_y = year;
+        show_m = month;
+        show_d = day;
+        
+        // 第五步:依次调用各个独立的初始化函数(降低耦合度)
+        InitDayMarkers();                          // 初始化颜色标记圆圈
+        InitTitleLabel();                          // 初始化顶部标题"生理周期"
+        InitMonthLabel(year, month, day, weekday); // 初始化日期标签"X月X日 星期X"
+        InitArrowButtons();                        // 初始化左右箭头按钮
+        InitWeekLabels();                          // 初始化星期标签(已隐藏)
+        InitDayLabels();                           // 初始化日期标签
+        UpdateDayDisplay(year, month, mon_max_day, weekday);  // 更新日期显示
+        InitEditButton();                          // 初始化底部"编辑"按钮
+        UpdateArrowButtonsVisibility();            // 更新箭头按钮的显示状态
+        UpdateEditButtonText();                    // 更新底部按钮文本(编辑/回今天)
+        
+        return true;
+    }
+ 
+    /**
+     * @brief 界面启动函数 - 进入女性健康界面时调用
+     * 
+     * 作用:创建主容器并初始化所有UI组件
+     * 
+     * 工作流程:
+     * 1. 创建主容器(UIViewGroup)
+     * 2. 设置容器大小为全屏
+     * 3. 启用触摸和拖动功能(支持上下滑动切换月份)
+     * 4. 设置拖动监听器(由Presenter处理)
+     * 5. 调用Label_init()初始化所有标签
+     */
+    void WomenHealthView::OnStart()
+    {
+        // 创建主容器
+        group = new UIViewGroup();
+        if (group == nullptr)
+        {
+            WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "WomenHealthView::创建主容器失败");
+            return;
+        }
+        
+        // 设置容器属性
+        group->SetPosition(0, 0);  // 位置:屏幕左上角
+        group->Resize(VERTICAL_RESOLUTION, HORIZONTAL_RESOLUTION);  // 大小:全屏
+        group->SetTouchable(true);     // 允许触摸
+        group->SetDraggable(true);     // 允许拖动
+        group->SetOnDragListener(presenter_);  // 设置拖动监听器,由Presenter处理滑动事件
+        
+        // 将容器添加到根容器
+        AddViewToRootContainer(group);
+
+        //测试一下效果 设置今天为月经开始日期
+        TimeObj startDate = {2025, 10, 23};
+        WomenHealthModel::GetInstance()->SetMenstrualStartDate(startDate);
+
+        // 初始化所有标签和UI组件
+        if (!Label_init())
+        {
+            WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "WomenHealthView::初始化标签失败");
+            return;
+        }
+    }
+}
\ No newline at end of file