CuddleNan пре 1 дан
родитељ
комит
0071dcc5f9

+ 2 - 2
myapp/src/app/tab1/page-detail/page-detail.page.scss

@@ -149,11 +149,11 @@
   .image-overlay {
     position: absolute;
     bottom: 16px;
-    left: 16px;
+    left: 240px;
     right: 16px;
     display: flex;
     gap: 8px;
-    
+    width: 150px;
     ion-chip {
       --background: rgba(255, 255, 255, 0.9);
       backdrop-filter: blur(5px);

+ 16 - 12
myapp/src/app/tab1/page-detail/page-detail.page.ts

@@ -1,20 +1,24 @@
 import { Component, OnInit } from '@angular/core';
-import { ActivatedRoute } from '@angular/router';
 import { 
-  IonHeader, IonToolbar, IonTitle, IonContent, 
-  IonBackButton, IonButtons, IonButton, IonIcon,
-  IonCard, IonCardHeader, IonCardTitle, IonCardContent,
-  IonList, IonItem, IonLabel, IonNote, IonChip,
-  IonAvatar
+  IonBackButton, 
+  IonButtons, 
+  IonContent, 
+  IonHeader, 
+  IonIcon, 
+  IonItem, 
+  IonLabel, 
+  IonList, 
+  IonThumbnail, 
+  IonTitle, 
+  IonToolbar,
+  IonButton
 } from '@ionic/angular/standalone';
 import { addIcons } from 'ionicons';
-import { 
-  timeOutline, flameOutline, peopleOutline, 
-  basketOutline, restaurantOutline, star, 
-  starOutline, bookmarkOutline, shareSocialOutline,
-  pricetagOutline,
-  bookmark} from 'ionicons/icons';
+import { timeOutline, trashOutline, star, refresh, flameOutline, peopleOutline, basketOutline, restaurantOutline, starOutline, bookmarkOutline, shareSocialOutline, bookmark } from 'ionicons/icons';
 import { CloudObject, CloudQuery } from 'src/lib/ncloud';
+import { NavController } from '@ionic/angular';
+import { Pipe, PipeTransform } from '@angular/core';
+import { ActivatedRoute } from '@angular/router';
 
 
 interface Ingredient {

+ 2 - 2
myapp/src/app/tab1/tab1.page.scss

@@ -150,7 +150,7 @@ ion-content {
 
 /* 头部样式 */
 .header-toolbar {
-  --background: #ff6b6b;
+  --background: #2dd55b;
   --color: white;
 }
 
@@ -205,7 +205,7 @@ ion-content {
   color: #343a40;
   margin-bottom: 16px;
   padding-left: 8px;
-  border-left: 4px solid #ff6b6b;
+  border-left: 4px solid #2dd55b;
 }
 
 .category-grid {

+ 81 - 31
myapp/src/app/tab3/page-collections/page-collections-detail/page-collections-detail.page.html

@@ -1,72 +1,122 @@
-<ion-header [translucent]="true">
-  <ion-toolbar>
+<ion-header [translucent]="true" class="recipe-header">
+  <ion-toolbar color="light">
     <ion-buttons slot="start">
-      <ion-back-button defaultHref="/"></ion-back-button>
+      <ion-back-button defaultHref="/" text="" color="dark"></ion-back-button>
+    </ion-buttons>
+    <ion-title class="header-title">菜谱详情</ion-title>
+    <ion-buttons slot="end">
+      <ion-button fill="clear" color="dark">
+        <ion-icon slot="icon-only" name="bookmark-outline"></ion-icon>
+      </ion-button>
+      <ion-button fill="clear" color="dark">
+        <ion-icon slot="icon-only" name="share-social-outline"></ion-icon>
+      </ion-button>
     </ion-buttons>
-    <ion-title>菜谱详情</ion-title>
   </ion-toolbar>
 </ion-header>
 
-<ion-content [fullscreen]="true">
+<ion-content [fullscreen]="true" class="recipe-content">
   <!-- 菜品图片 -->
   <div class="recipe-image-container">
-    <img [src]="recipe?.get('imageUrl')" [alt]="recipe?.get('title')" class="recipe-image">
+    <img [src]="recipe?.get('imageUrl') || 'assets/images/default-food.jpg'" 
+         [alt]="recipe?.get('title')" 
+         class="recipe-image">
     <div class="image-overlay">
-      <ion-chip color="primary">{{ recipe?.get('category')}}</ion-chip>
-      <ion-chip color="dark">{{ recipe?.get('cookTime') }}</ion-chip>
+      <ion-chip color="success" outline>
+        <ion-icon name="pricetag-outline" slot="start"></ion-icon>
+        {{ recipe?.get('category') || '未分类' }}
+      </ion-chip>
+      <ion-chip color="warning" outline>
+        <ion-icon name="time-outline" slot="start"></ion-icon>
+        {{ recipe?.get('cookTime') || '30分钟' }}
+      </ion-chip>
     </div>
   </div>
 
-  <!-- 菜品名称 -->
-  <div class="recipe-header">
-    <h1 class="recipe-title">{{ recipe?.get('title') }}</h1>
+  <!-- 菜品名称和评分 -->
+  <div class="recipe-info-section">
+    <div class="recipe-header">
+      <h1 class="recipe-title">{{ recipe?.get('title') }}</h1>
+      <div class="recipe-rating">
+        <ion-icon name="star" color="warning"></ion-icon>
+        <ion-icon name="star" color="warning"></ion-icon>
+        <ion-icon name="star" color="warning"></ion-icon>
+        <ion-icon name="star" color="warning"></ion-icon>
+        <ion-icon name="star-outline" color="warning"></ion-icon>
+        <span class="rating-text">4.5</span>
+      </div>
+    </div>
+
+    <!-- 菜品元信息 -->
     <div class="recipe-meta">
-      <span class="meta-item"><ion-icon name="time-outline"></ion-icon> {{ recipe?.get('prepTime') }} 准备</span>
-      <span class="meta-item"><ion-icon name="flame-outline"></ion-icon> {{ recipe?.get('difficulty') }}</span>
-      <span class="meta-item"><ion-icon name="people-outline"></ion-icon> {{ recipe?.get('servings') }} 人份</span>
+      <ion-item lines="none" class="meta-item">
+        <ion-icon slot="start" name="time-outline" color="medium"></ion-icon>
+        <ion-label>{{ recipe?.get('prepTime') || '10分钟' }} 准备</ion-label>
+      </ion-item>
+      
+      <ion-item lines="none" class="meta-item">
+        <ion-icon slot="start" name="flame-outline" color="medium"></ion-icon>
+        <ion-label>{{ recipe?.get('difficulty') || '中等' }}难度</ion-label>
+      </ion-item>
+      
+      <ion-item lines="none" class="meta-item">
+        <ion-icon slot="start" name="people-outline" color="medium"></ion-icon>
+        <ion-label>{{ recipe?.get('servings') || 2 }} 人份</ion-label>
+      </ion-item>
     </div>
+
+    <!-- 菜品描述 -->
+    <p class="recipe-description" *ngIf="recipe?.get('description')">
+      {{ recipe?.get('description') }}
+    </p>
   </div>
 
   <!-- 食材部分 -->
   <ion-card class="section-card">
-    <ion-card-header>
-      <ion-card-title>
-        <ion-icon name="basket-outline" slot="start"></ion-icon>
+    <ion-card-header class="section-header">
+      <ion-card-title class="section-title">
+        <ion-icon name="basket-outline" class="section-icon"></ion-icon>
         所需食材
       </ion-card-title>
     </ion-card-header>
     <ion-card-content>
-      <ion-list lines="none">
-        <ion-item *ngFor="let ingredient of recipe?.get('ingredients')">
-          <ion-label>{{ ingredient.name }}</ion-label>
-          <ion-note slot="end" color="primary">{{ ingredient.amount }}</ion-note>
+      <ion-list lines="none" class="ingredient-list">
+        <ion-item *ngFor="let ingredient of recipe?.get('ingredients')" class="ingredient-item">
+          <ion-icon name="ellipse" slot="start" class="bullet-icon"></ion-icon>
+          <ion-label class="ingredient-name">{{ ingredient.name }}</ion-label>
+          <ion-note slot="end" color="primary" class="ingredient-amount">{{ ingredient.amount }}</ion-note>
         </ion-item>
       </ion-list>
     </ion-card-content>
   </ion-card>
 
   <!-- 操作步骤 -->
-  <ion-card class="section-card" *ngIf="recipe">
-    <ion-card-header>
-      <ion-card-title>
-        <ion-icon name="restaurant-outline" slot="start"></ion-icon>
+  <ion-card class="section-card">
+    <ion-card-header class="section-header">
+      <ion-card-title class="section-title">
+        <ion-icon name="restaurant-outline" class="section-icon"></ion-icon>
         操作步骤
       </ion-card-title>
     </ion-card-header>
     <ion-card-content>
-      <ion-list lines="none">
-        <ion-item 
-          *ngFor="let step of recipe?.get('steps'); let i = index" 
-          class="step-item"
-        >
+      <ion-list lines="none" class="step-list">
+        <ion-item *ngFor="let step of recipe?.get('steps'); let i = index" class="step-item">
           <ion-avatar slot="start" class="step-number">
             {{ i + 1 }}
           </ion-avatar>
-          <ion-label class="ion-text-wrap">
+          <ion-label class="ion-text-wrap step-text">
             <p>{{ step }}</p>
           </ion-label>
         </ion-item>
       </ion-list>
     </ion-card-content>
   </ion-card>
+
+  <!-- 底部操作按钮 -->
+  <div class="action-buttons">
+    <ion-button expand="block" color="success" shape="round" class="cook-button">
+      <ion-icon name="restaurant" slot="start"></ion-icon>
+      开始烹饪
+    </ion-button>
+  </div>
 </ion-content>

+ 326 - 90
myapp/src/app/tab3/page-collections/page-collections-detail/page-collections-detail.page.scss

@@ -1,113 +1,349 @@
 .recipe-image-container {
-    position: relative;
+  position: relative;
+  width: 100%;
+  height: 250px;
+  overflow: hidden;
+  
+  .recipe-image {
     width: 100%;
-    height: 250px;
-    overflow: hidden;
-    
-    .recipe-image {
-      width: 100%;
-      height: 100%;
-      object-fit: cover;
-    }
-    
-    .image-overlay {
-      position: absolute;
-      top: 10px;
-      right: 10px;
-      display: flex;
-      flex-direction: column;
-      gap: 5px;
-    }
+    height: 100%;
+    object-fit: cover;
   }
   
-  .recipe-header {
-    padding: 16px;
-    
-    .recipe-title {
-      font-size: 1.8rem;
-      font-weight: bold;
-      margin-bottom: 8px;
-      color: var(--ion-color-dark);
-    }
-    
-    .recipe-meta {
-      display: flex;
-      gap: 16px;
-      margin-top: 8px;
-      
-      .meta-item {
-        display: flex;
-        align-items: center;
-        font-size: 0.9rem;
-        color: var(--ion-color-medium);
-        
-        ion-icon {
-          margin-right: 4px;
-          font-size: 1rem;
-        }
-      }
-    }
+  .image-overlay {
+    position: absolute;
+    top: 10px;
+    right: 10px;
+    display: flex;
+    flex-direction: column;
+    gap: 5px;
   }
+}
+
+.recipe-header {
+  padding: 16px;
   
-  .section-card {
-    margin: 16px;
-    border-radius: 12px;
-    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
+  .recipe-title {
+    font-size: 1.8rem;
+    font-weight: bold;
+    margin-bottom: 8px;
+    color: var(--ion-color-dark);
+  }
+  
+  .recipe-meta {
+    display: flex;
+    gap: 16px;
+    margin-top: 8px;
     
-    ion-card-header {
-      padding-bottom: 0;
+    .meta-item {
+      display: flex;
+      align-items: center;
+      font-size: 0.9rem;
+      color: var(--ion-color-medium);
       
-      ion-card-title {
-        display: flex;
-        align-items: center;
-        font-size: 1.2rem;
-        color: var(--ion-color-dark);
-        
-        ion-icon {
-          margin-right: 8px;
-          color: var(--ion-color-primary);
-        }
+      ion-icon {
+        margin-right: 4px;
+        font-size: 1rem;
       }
     }
   }
+}
+
+.section-card {
+  margin: 16px;
+  border-radius: 12px;
+  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
   
-  .step-item {
-    --padding-start: 0;
-    --inner-padding-end: 0;
-    align-items: flex-start;
+  ion-card-header {
+    padding-bottom: 0;
     
-    .step-number {
-      width: 28px;
-      height: 28px;
-      background: var(--ion-color-primary);
-      color: white;
+    ion-card-title {
       display: flex;
       align-items: center;
-      justify-content: center;
-      font-size: 0.9rem;
-      font-weight: bold;
-      margin-right: 12px;
-    }
-    
-    ion-label {
-      margin-top: 4px;
-      margin-bottom: 4px;
+      font-size: 1.2rem;
+      color: var(--ion-color-dark);
       
-      p {
-        margin: 0;
-        color: var(--ion-color-dark);
-        line-height: 1.5;
+      ion-icon {
+        margin-right: 8px;
+        color: var(--ion-color-primary);
       }
     }
   }
+}
+
+.step-item {
+  --padding-start: 0;
+  --inner-padding-end: 0;
+  align-items: flex-start;
+  
+  .step-number {
+    width: 28px;
+    height: 28px;
+    background: var(--ion-color-primary);
+    color: white;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    font-size: 0.9rem;
+    font-weight: bold;
+    margin-right: 12px;
+  }
   
-  @media (min-width: 768px) {
-    .recipe-image-container {
-      height: 350px;
+  ion-label {
+    margin-top: 4px;
+    margin-bottom: 4px;
+    
+    p {
+      margin: 0;
+      color: var(--ion-color-dark);
+      line-height: 1.5;
     }
+  }
+}
+
+@media (min-width: 768px) {
+  .recipe-image-container {
+    height: 350px;
+  }
+  
+  .section-card {
+    margin: 20px auto;
+    max-width: 800px;
+  }
+}
+
+/* 头部样式 */
+.recipe-header {
+ion-toolbar {
+  --background: white;
+  --border-width: 0;
+  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
+  
+  .header-title {
+    font-size: 1.2rem;
+    font-weight: 600;
+    color: var(--ion-color-dark);
+  }
+}
+}
+
+/* 内容区域 */
+.recipe-content {
+--background: #f8f9fa;
+padding-bottom: 80px;
+}
+
+/* 菜品图片 */
+.recipe-image-container {
+position: relative;
+width: 100%;
+height: 250px;
+overflow: hidden;
+
+.recipe-image {
+  width: 100%;
+  height: 100%;
+  object-fit: cover;
+}
+
+.image-overlay {
+  position: absolute;
+  bottom: 16px;
+  left: 240px;
+  right: 16px;
+  display: flex;
+  gap: 8px;
+  width: 150px;
+  ion-chip {
+    --background: rgba(255, 255, 255, 0.9);
+    backdrop-filter: blur(5px);
+  }
+}
+}
+
+/* 菜品信息部分 */
+.recipe-info-section {
+padding: 16px;
+background: white;
+margin-bottom: 16px;
+}
+
+.recipe-header {
+display: flex;
+justify-content: space-between;
+align-items: center;
+margin-bottom: 12px;
+
+.recipe-title {
+  font-size: 1.5rem;
+  font-weight: 600;
+  color: var(--ion-color-dark);
+  margin: 0;
+  flex: 1;
+}
+
+.recipe-rating {
+  display: flex;
+  align-items: center;
+  
+  ion-icon {
+    font-size: 1.2rem;
+    margin-right: 2px;
+  }
+  
+  .rating-text {
+    font-size: 0.9rem;
+    color: var(--ion-color-medium);
+    margin-left: 4px;
+  }
+}
+}
+
+.recipe-meta {
+display: flex;
+flex-wrap: wrap;
+gap: 8px;
+margin-bottom: 16px;
+
+.meta-item {
+  --padding-start: 0;
+  --inner-padding-end: 0;
+  --min-height: 32px;
+  flex: 1 0 calc(33.333% - 8px);
+  
+  ion-icon {
+    font-size: 1.2rem;
+  }
+  
+  ion-label {
+    font-size: 0.85rem;
+    color: var(--ion-color-medium);
+  }
+}
+}
+
+.recipe-description {
+font-size: 0.95rem;
+color: var(--ion-color-medium);
+line-height: 1.6;
+margin: 0;
+}
+
+/* 卡片部分 */
+.section-card {
+margin: 16px;
+border-radius: 12px;
+box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
+
+.section-header {
+  padding-bottom: 0;
+  
+  .section-title {
+    font-size: 1.1rem;
+    font-weight: 600;
+    display: flex;
+    align-items: center;
     
-    .section-card {
-      margin: 20px auto;
-      max-width: 800px;
+    .section-icon {
+      margin-right: 8px;
+      color: var(--ion-color-primary);
     }
-  }
+  }
+}
+}
+
+/* 食材列表 */
+.ingredient-list {
+.ingredient-item {
+  --padding-start: 0;
+  --inner-padding-end: 0;
+  --min-height: 48px;
+  border-bottom: 1px dashed var(--ion-color-light-shade);
+  
+  &:last-child {
+    border-bottom: none;
+  }
+  
+  .bullet-icon {
+    color: var(--ion-color-primary);
+    font-size: 0.6rem;
+  }
+  
+  .ingredient-name {
+    font-size: 0.95rem;
+  }
+  
+  .ingredient-amount {
+    font-weight: 500;
+  }
+}
+}
+
+/* 步骤列表 */
+.step-list {
+.step-item {
+  --padding-start: 0;
+  --inner-padding-end: 0;
+  --min-height: auto;
+  align-items: flex-start;
+  padding: 12px 0;
+  
+  .step-number {
+    width: 28px;
+    height: 28px;
+    background: var(--ion-color-primary);
+    color: white;
+    font-size: 0.9rem;
+    font-weight: 600;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    margin-right: 12px;
+  }
+  
+  .step-text {
+    font-size: 0.95rem;
+    color: var(--ion-color-medium);
+    line-height: 1.6;
+    white-space: normal;
+  }
+}
+}
+
+/* 底部按钮 */
+.action-buttons {
+position: fixed;
+bottom: 0;
+left: 0;
+right: 0;
+padding: 16px;
+background: linear-gradient(to top, white 50%, transparent 100%);
+
+.cook-button {
+  --box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
+  --padding-top: 16px;
+  --padding-bottom: 16px;
+  font-weight: 600;
+}
+}
+
+/* 响应式调整 */
+@media (min-width: 768px) {
+.recipe-image-container {
+  height: 350px;
+}
+
+.recipe-info-section {
+  padding: 24px;
+}
+
+.section-card {
+  margin: 24px;
+}
+
+.action-buttons {
+  padding: 24px;
+  max-width: 600px;
+  margin: 0 auto;
+}
+}

+ 47 - 18
myapp/src/app/tab3/page-collections/page-collections.page.html

@@ -1,38 +1,67 @@
 <ion-header [translucent]="true">
-  <ion-toolbar>
+  <ion-toolbar color="primary">
     <ion-buttons slot="start">
-      <ion-back-button defaultHref="/"></ion-back-button>
+      <ion-back-button defaultHref="/" text="返回"></ion-back-button>
     </ion-buttons>
     <ion-title>我的收藏</ion-title>
+    <ion-buttons slot="end">
+      <ion-button (click)="loadRecipeFavoriteList()">
+        <ion-icon slot="icon-only" name="refresh" class="refresh-icon"></ion-icon>
+      </ion-button>
+    </ion-buttons>
   </ion-toolbar>
 </ion-header>
 
-<ion-content [fullscreen]="true">
+<ion-content [fullscreen]="true" class="ion-padding">
   <!-- 收藏列表 -->
-  <ion-list>
+  <ion-list lines="none" *ngIf="recipeFavoriteList.length > 0">
     <ion-item-sliding *ngFor="let item of recipeFavoriteList">
-      <ion-item  (click)="goToDetail(item.id)">
-        <ion-thumbnail slot="start">
-          <img [src]="item.get('imageUrl')" [alt]="item.get('title')">
+      <ion-item detail="true" (click)="goToDetail(item.id)" class="favorite-item">
+        <ion-thumbnail slot="start" class="item-thumbnail">
+          <img [src]="item.get('imageUrl')" [alt]="item.get('title')" class="thumbnail-img">
         </ion-thumbnail>
-        <ion-label>
-          <h2>{{ item.get('title') }}</h2>
-          <p *ngIf="item.get('favoriteTime')">收藏时间: {{ item.get('favoriteTime') | date:'yyyy-MM-dd' }}</p>
+        <ion-label class="item-content">
+          <div class="item-header">
+            <h2 class="item-title">{{ item.get('title') }}</h2>
+            <div class="rating-container">
+              <ion-icon name="star" color="warning"></ion-icon>
+              <span>{{ item.get('rating') || '0.0' }}</span>
+            </div>
+          </div>
+          <p class="item-desc">{{ item.get('description') }}</p>
+          <div class="item-footer">
+            <div class="time-container" *ngIf="item.get('favoriteTime')">
+              <ion-icon name="time-outline"></ion-icon>
+              <span>{{ item.get('favoriteTime') | date:'yyyy-MM-dd' }}</span>
+            </div>
+            <ion-badge color="light" *ngIf="item.get('cookingTime')">
+              <ion-icon name="timer-outline"></ion-icon>
+              {{ item.get('cookingTime') }}
+            </ion-badge>
+          </div>
         </ion-label>
-        <ion-icon name="heart" slot="end" color="danger"></ion-icon>
+        <ion-icon name="heart" slot="end" color="danger" class="heart-icon"></ion-icon>
       </ion-item>
+      
       <ion-item-options side="end">
-        <!-- <ion-item-option color="danger" (click)="removeCollection(item.id)">
-          <ion-icon name="trash" slot="icon-only"></ion-icon>
-        </ion-item-option> -->
+        <ion-item-option color="danger" ><!-- (click)="removeCollection(item.id)" -->
+          <ion-icon name="trash" size="large"></ion-icon>
+          <span>删除</span>
+        </ion-item-option>
       </ion-item-options>
     </ion-item-sliding>
   </ion-list>
 
   <!-- 空状态提示 -->
-  <div class="empty-state" *ngIf="recipeFavoriteList.length === 0">
-    <ion-icon name="heart-outline"></ion-icon>
-    <h3>暂无收藏记录</h3>
-    <p>您收藏的菜品将会显示在这里</p>
+  <div class="empty-state ion-text-center" *ngIf="recipeFavoriteList.length === 0">
+    <div class="empty-icon">
+      <ion-icon name="heart-outline" color="medium"></ion-icon>
+    </div>
+    <h3 class="empty-title">暂无收藏记录</h3>
+    <p class="empty-text">您收藏的菜品将会显示在这里</p>
+    <ion-button fill="outline" color="medium" (click)="loadRecipeFavoriteList()">
+      <ion-icon slot="start" name="refresh"></ion-icon>
+      刷新
+    </ion-button>
   </div>
 </ion-content>

+ 193 - 1
myapp/src/app/tab3/page-collections/page-collections.page.scss

@@ -62,4 +62,196 @@ ion-thumbnail {
     ion-thumbnail {
       --size: 80px;
     }
-  }
+  }
+
+  /* 收藏项样式 */
+.favorite-item {
+  --padding-start: 0;
+  --inner-padding-end: 0;
+  --background: var(--ion-color-light);
+  border-radius: 12px;
+  margin-bottom: 12px;
+  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
+}
+
+.item-thumbnail {
+  --size: 80px;
+  --border-radius: 8px;
+  margin: 8px;
+  
+  .thumbnail-img {
+    border-radius: 8px;
+    object-fit: cover;
+  }
+}
+
+.item-label {
+  margin: 10px 0;
+  
+  .item-title {
+    font-weight: 600;
+    font-size: 1.1rem;
+    margin-bottom: 5px;
+  }
+  
+  .item-time {
+    display: flex;
+    align-items: center;
+    color: var(--ion-color-medium);
+    font-size: 0.9rem;
+    
+    .time-icon {
+      margin-right: 5px;
+    }
+  }
+}
+
+.heart-icon {
+  margin-right: 16px;
+  font-size: 1.5rem;
+}
+
+/* 空状态样式 */
+.empty-state {
+  height: 70vh;
+  display: flex;
+  flex-direction: column;
+  justify-content: center;
+  align-items: center;
+  
+  .empty-icon {
+    font-size: 4rem;
+    margin-bottom: 20px;
+    opacity: 0.5;
+  }
+  
+  .empty-title {
+    color: var(--ion-color-medium);
+    font-weight: 600;
+    margin-bottom: 8px;
+  }
+  
+  .empty-text {
+    color: var(--ion-color-medium);
+    margin-bottom: 20px;
+    font-size: 0.9rem;
+  }
+}
+/* 收藏项样式 */
+.favorite-item {
+  --padding-start: 0;
+  --inner-padding-end: 0;
+  --background: var(--ion-color-light);
+  border-radius: 12px;
+  margin-bottom: 12px;
+  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
+}
+
+.item-thumbnail {
+  --size: 80px;
+  --border-radius: 8px;
+  margin: 8px;
+  
+  .thumbnail-img {
+    border-radius: 8px;
+    object-fit: cover;
+  }
+}
+
+.item-content {
+  margin: 10px 0;
+  
+  .item-header {
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    margin-bottom: 6px;
+    
+    .item-title {
+      font-weight: 600;
+      font-size: 1.1rem;
+      margin: 0;
+    }
+    
+    .rating-container {
+      display: flex;
+      align-items: center;
+      color: var(--ion-color-warning);
+      font-size: 0.9rem;
+      
+      ion-icon {
+        margin-right: 4px;
+      }
+    }
+  }
+  
+  .item-desc {
+    color: var(--ion-color-medium);
+    font-size: 0.9rem;
+    margin-bottom: 8px;
+    line-height: 1.4;
+  }
+  
+  .item-footer {
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    
+    .time-container {
+      display: flex;
+      align-items: center;
+      color: var(--ion-color-medium);
+      font-size: 0.85rem;
+      
+      ion-icon {
+        margin-right: 4px;
+      }
+    }
+    
+    ion-badge {
+      font-weight: normal;
+      padding: 4px 8px;
+      
+      ion-icon {
+        margin-right: 4px;
+        font-size: 0.9rem;
+      }
+    }
+  }
+}
+
+.heart-icon {
+  margin-right: 16px;
+  font-size: 1.5rem;
+}
+
+.refresh-icon {
+  font-size: 1.2rem;
+}
+
+/* 空状态样式 */
+.empty-state {
+  height: 70vh;
+  display: flex;
+  flex-direction: column;
+  justify-content: center;
+  align-items: center;
+  
+  .empty-icon {
+    font-size: 4rem;
+    margin-bottom: 20px;
+    opacity: 0.5;
+  }
+  
+  .empty-title {
+    color: var(--ion-color-medium);
+    font-weight: 600;
+    margin-bottom: 8px;
+  }
+  
+  .empty-text {
+    color: var(--ion-color-medium);
+    margin-bottom: 20px;
+    font-size: 0.9rem;
+  }
+}

+ 18 - 3
myapp/src/app/tab3/page-collections/page-collections.page.ts

@@ -1,8 +1,23 @@
 import { Component, OnInit } from '@angular/core';
-import { IonBackButton, IonButtons, IonContent, IonHeader, IonIcon, IonItem, IonItemOption, IonItemOptions, IonItemSliding, IonLabel, IonList, IonThumbnail, IonTitle, IonToolbar } from '@ionic/angular/standalone';
+import { 
+  IonBackButton, 
+  IonButtons, 
+  IonContent, 
+  IonHeader, 
+  IonIcon, 
+  IonItem, 
+  IonItemOption, 
+  IonItemOptions, 
+  IonItemSliding, 
+  IonLabel, 
+  IonList, 
+  IonThumbnail, 
+  IonTitle, 
+  IonToolbar,
+  IonButton
+} from '@ionic/angular/standalone';
 import { addIcons } from 'ionicons';
-import { codeDownloadSharp, heart, heartOutline, trash } from 'ionicons/icons';
-import { importAllData } from 'src/app/import-recipe-data';
+import { heart, heartOutline, trash, timeOutline, refresh } from 'ionicons/icons';
 import { CloudObject, CloudQuery } from 'src/lib/ncloud';
 import { NavController } from '@ionic/angular';
 import { Router } from '@angular/router';

+ 63 - 63
myapp/src/app/tab3/page-records/page-records-detail/page-records-detail.page.html

@@ -1,18 +1,15 @@
-<ion-header [translucent]="true">
-  <ion-toolbar color="primary">
+<ion-header [translucent]="true" class="recipe-header">
+  <ion-toolbar color="light">
     <ion-buttons slot="start">
-      <ion-back-button defaultHref="/" text="" color="light"></ion-back-button>
+      <ion-back-button defaultHref="/" text="" color="dark"></ion-back-button>
     </ion-buttons>
     <ion-title class="header-title">菜谱详情</ion-title>
     <ion-buttons slot="end">
-      <ion-button (click)="toggleBookmark()">
-        <ion-icon 
-          [name]="isBookmarked ? 'bookmark' : 'bookmark-outline'" 
-          color="light">
-        </ion-icon>
+      <ion-button fill="clear" color="dark">
+        <ion-icon slot="icon-only" name="bookmark-outline"></ion-icon>
       </ion-button>
-      <ion-button (click)="shareRecipe()">
-        <ion-icon name="share-social-outline" color="light"></ion-icon>
+      <ion-button fill="clear" color="dark">
+        <ion-icon slot="icon-only" name="share-social-outline"></ion-icon>
       </ion-button>
     </ion-buttons>
   </ion-toolbar>
@@ -21,51 +18,58 @@
 <ion-content [fullscreen]="true" class="recipe-content">
   <!-- 菜品图片 -->
   <div class="recipe-image-container">
-    <img 
-      [src]="recipe?.get('imageUrl') || 'assets/default-recipe.jpg'" 
-      [alt]="recipe?.get('title')" 
-      class="recipe-image">
+    <img [src]="recipe?.get('imageUrl') || 'assets/images/default-food.jpg'" 
+         [alt]="recipe?.get('title')" 
+         class="recipe-image">
     <div class="image-overlay">
-      <ion-chip color="light" class="category-chip">
-        <ion-icon name="pricetag" slot="start" color="primary"></ion-icon>
-        {{ recipe?.get('category') || '家常菜' }}
+      <ion-chip color="success" outline>
+        <ion-icon name="pricetag-outline" slot="start"></ion-icon>
+        {{ recipe?.get('category') || '未分类' }}
       </ion-chip>
-      <ion-chip color="light" class="time-chip">
-        <ion-icon name="time" slot="start" color="warning"></ion-icon>
+      <ion-chip color="warning" outline>
+        <ion-icon name="time-outline" slot="start"></ion-icon>
         {{ recipe?.get('cookTime') || '30分钟' }}
       </ion-chip>
     </div>
-    <div class="rating-overlay" *ngIf="recipe?.get('rating')">
-      <ion-badge color="warning" class="rating-badge">
-        <ion-icon name="star" color="light"></ion-icon>
-        {{ recipe?.get('rating') }}
-      </ion-badge>
-    </div>
   </div>
 
-  <!-- 菜品名称和基本信息 -->
-  <ion-card class="recipe-header-card">
-    <ion-card-header>
-      <ion-card-title class="recipe-title">{{ recipe?.get('title') || '美味菜谱' }}</ion-card-title>
-    </ion-card-header>
-    <ion-card-content>
-      <div class="recipe-meta">
-        <ion-chip outline color="medium" class="meta-chip">
-          <ion-icon name="time-outline" slot="start"></ion-icon>
-          {{ recipe?.get('prepTime') || '15分钟' }} 准备
-        </ion-chip>
-        <ion-chip outline color="medium" class="meta-chip">
-          <ion-icon name="flame-outline" slot="start"></ion-icon>
-          {{ recipe?.get('difficulty') || '中等' }}
-        </ion-chip>
-        <ion-chip outline color="medium" class="meta-chip">
-          <ion-icon name="people-outline" slot="start"></ion-icon>
-          {{ recipe?.get('servings') || '4' }} 人份
-        </ion-chip>
+  <!-- 菜品名称和评分 -->
+  <div class="recipe-info-section">
+    <div class="recipe-header">
+      <h1 class="recipe-title">{{ recipe?.get('title') }}</h1>
+      <div class="recipe-rating">
+        <ion-icon name="star" color="warning"></ion-icon>
+        <ion-icon name="star" color="warning"></ion-icon>
+        <ion-icon name="star" color="warning"></ion-icon>
+        <ion-icon name="star" color="warning"></ion-icon>
+        <ion-icon name="star-outline" color="warning"></ion-icon>
+        <span class="rating-text">4.5</span>
       </div>
-      <p class="recipe-description">{{ recipe?.get('description') || '一道美味的家常菜,简单易学,营养丰富' }}</p>
-    </ion-card-content>
-  </ion-card>
+    </div>
+
+    <!-- 菜品元信息 -->
+    <div class="recipe-meta">
+      <ion-item lines="none" class="meta-item">
+        <ion-icon slot="start" name="time-outline" color="medium"></ion-icon>
+        <ion-label>{{ recipe?.get('prepTime') || '10分钟' }} 准备</ion-label>
+      </ion-item>
+      
+      <ion-item lines="none" class="meta-item">
+        <ion-icon slot="start" name="flame-outline" color="medium"></ion-icon>
+        <ion-label>{{ recipe?.get('difficulty') || '中等' }}难度</ion-label>
+      </ion-item>
+      
+      <ion-item lines="none" class="meta-item">
+        <ion-icon slot="start" name="people-outline" color="medium"></ion-icon>
+        <ion-label>{{ recipe?.get('servings') || 2 }} 人份</ion-label>
+      </ion-item>
+    </div>
+
+    <!-- 菜品描述 -->
+    <p class="recipe-description" *ngIf="recipe?.get('description')">
+      {{ recipe?.get('description') }}
+    </p>
+  </div>
 
   <!-- 食材部分 -->
   <ion-card class="section-card">
@@ -78,11 +82,9 @@
     <ion-card-content>
       <ion-list lines="none" class="ingredient-list">
         <ion-item *ngFor="let ingredient of recipe?.get('ingredients')" class="ingredient-item">
-          <ion-icon name="ellipse" slot="start" color="medium" class="ingredient-bullet"></ion-icon>
+          <ion-icon name="ellipse" slot="start" class="bullet-icon"></ion-icon>
           <ion-label class="ingredient-name">{{ ingredient.name }}</ion-label>
-          <ion-badge color="primary" mode="ios" class="ingredient-amount">
-            {{ ingredient.amount }}
-          </ion-badge>
+          <ion-note slot="end" color="primary" class="ingredient-amount">{{ ingredient.amount }}</ion-note>
         </ion-item>
       </ion-list>
     </ion-card-content>
@@ -98,13 +100,10 @@
     </ion-card-header>
     <ion-card-content>
       <ion-list lines="none" class="step-list">
-        <ion-item 
-          *ngFor="let step of recipe?.get('steps'); let i = index" 
-          class="step-item"
-        >
-          <ion-badge color="primary" slot="start" class="step-number">
+        <ion-item *ngFor="let step of recipe?.get('steps'); let i = index" class="step-item">
+          <ion-avatar slot="start" class="step-number">
             {{ i + 1 }}
-          </ion-badge>
+          </ion-avatar>
           <ion-label class="ion-text-wrap step-text">
             <p>{{ step }}</p>
           </ion-label>
@@ -113,10 +112,11 @@
     </ion-card-content>
   </ion-card>
 
-  <!-- 底部操作栏 -->
-  <ion-fab vertical="bottom" horizontal="end" slot="fixed">
-    <ion-fab-button color="primary" (click)="rateRecipe()">
-      <ion-icon name="star-outline"></ion-icon>
-    </ion-fab-button>
-  </ion-fab>
+  <!-- 底部操作按钮 -->
+  <div class="action-buttons">
+    <ion-button expand="block" color="success" shape="round" class="cook-button">
+      <ion-icon name="restaurant" slot="start"></ion-icon>
+      开始烹饪
+    </ion-button>
+  </div>
 </ion-content>

+ 314 - 242
myapp/src/app/tab3/page-records/page-records-detail/page-records-detail.page.scss

@@ -1,277 +1,349 @@
 .recipe-image-container {
-    position: relative;
+  position: relative;
+  width: 100%;
+  height: 250px;
+  overflow: hidden;
+  
+  .recipe-image {
     width: 100%;
-    height: 250px;
-    overflow: hidden;
-    
-    .recipe-image {
-      width: 100%;
-      height: 100%;
-      object-fit: cover;
-    }
-    
-    .image-overlay {
-      position: absolute;
-      top: 10px;
-      right: 10px;
-      display: flex;
-      flex-direction: column;
-      gap: 5px;
-    }
+    height: 100%;
+    object-fit: cover;
   }
   
-  .recipe-header {
-    padding: 16px;
-    
-    .recipe-title {
-      font-size: 1.8rem;
-      font-weight: bold;
-      margin-bottom: 8px;
-      color: var(--ion-color-dark);
-    }
-    
-    .recipe-meta {
-      display: flex;
-      gap: 16px;
-      margin-top: 8px;
-      
-      .meta-item {
-        display: flex;
-        align-items: center;
-        font-size: 0.9rem;
-        color: var(--ion-color-medium);
-        
-        ion-icon {
-          margin-right: 4px;
-          font-size: 1rem;
-        }
-      }
-    }
+  .image-overlay {
+    position: absolute;
+    top: 10px;
+    right: 10px;
+    display: flex;
+    flex-direction: column;
+    gap: 5px;
   }
+}
+
+.recipe-header {
+  padding: 16px;
   
-  .section-card {
-    margin: 16px;
-    border-radius: 12px;
-    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
-    
-    ion-card-header {
-      padding-bottom: 0;
-      
-      ion-card-title {
-        display: flex;
-        align-items: center;
-        font-size: 1.2rem;
-        color: var(--ion-color-dark);
-        
-        ion-icon {
-          margin-right: 8px;
-          color: var(--ion-color-primary);
-        }
-      }
-    }
+  .recipe-title {
+    font-size: 1.8rem;
+    font-weight: bold;
+    margin-bottom: 8px;
+    color: var(--ion-color-dark);
   }
   
-  .step-item {
-    --padding-start: 0;
-    --inner-padding-end: 0;
-    align-items: flex-start;
+  .recipe-meta {
+    display: flex;
+    gap: 16px;
+    margin-top: 8px;
     
-    .step-number {
-      width: 28px;
-      height: 28px;
-      background: var(--ion-color-primary);
-      color: white;
+    .meta-item {
       display: flex;
       align-items: center;
-      justify-content: center;
       font-size: 0.9rem;
-      font-weight: bold;
-      margin-right: 12px;
-    }
-    
-    ion-label {
-      margin-top: 4px;
-      margin-bottom: 4px;
+      color: var(--ion-color-medium);
       
-      p {
-        margin: 0;
-        color: var(--ion-color-dark);
-        line-height: 1.5;
+      ion-icon {
+        margin-right: 4px;
+        font-size: 1rem;
       }
     }
   }
+}
+
+.section-card {
+  margin: 16px;
+  border-radius: 12px;
+  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
   
-  @media (min-width: 768px) {
-    .recipe-image-container {
-      height: 350px;
-    }
+  ion-card-header {
+    padding-bottom: 0;
     
-    .section-card {
-      margin: 20px auto;
-      max-width: 800px;
-    }
-  }
-  .recipe-content {
-    --background: #f5f5f5;
-    --padding-top: 0;
-  }
-  
-  .recipe-image-container {
-    position: relative;
-    height: 250px;
-    overflow: hidden;
-    
-    .recipe-image {
-      width: 100%;
-      height: 100%;
-      object-fit: cover;
-      object-position: center;
-    }
-    
-    .image-overlay {
-      position: absolute;
-      bottom: 15px;
-      left: 15px;
+    ion-card-title {
       display: flex;
-      gap: 10px;
-      
-      ion-chip {
-        --background: rgba(255, 255, 255, 0.9);
-        backdrop-filter: blur(5px);
-        
-        ion-icon {
-          margin-right: 5px;
-        }
-      }
-    }
-    
-    .rating-overlay {
-      position: absolute;
-      top: 15px;
-      right: 15px;
+      align-items: center;
+      font-size: 1.2rem;
+      color: var(--ion-color-dark);
       
-      .rating-badge {
-        font-size: 14px;
-        padding: 6px 10px;
-        
-        ion-icon {
-          font-size: 14px;
-          margin-right: 3px;
-        }
+      ion-icon {
+        margin-right: 8px;
+        color: var(--ion-color-primary);
       }
     }
   }
+}
+
+.step-item {
+  --padding-start: 0;
+  --inner-padding-end: 0;
+  align-items: flex-start;
+  
+  .step-number {
+    width: 28px;
+    height: 28px;
+    background: var(--ion-color-primary);
+    color: white;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    font-size: 0.9rem;
+    font-weight: bold;
+    margin-right: 12px;
+  }
   
-  .recipe-header-card {
-    margin: -20px 15px 0;
-    border-radius: 15px;
-    box-shadow: 0 4px 16px rgba(0, 0, 0, 0.1);
-    position: relative;
-    z-index: 1;
+  ion-label {
+    margin-top: 4px;
+    margin-bottom: 4px;
     
-    .recipe-title {
-      font-size: 1.5rem;
-      font-weight: bold;
+    p {
+      margin: 0;
       color: var(--ion-color-dark);
-      margin-bottom: 10px;
-    }
-    
-    .recipe-meta {
-      display: flex;
-      flex-wrap: wrap;
-      gap: 8px;
-      margin-bottom: 15px;
-      
-      .meta-chip {
-        --background: rgba(var(--ion-color-medium-rgb), 0.1);
-        font-size: 12px;
-        
-        ion-icon {
-          font-size: 14px;
-        }
-      }
-    }
-    
-    .recipe-description {
-      color: var(--ion-color-medium);
-      font-size: 14px;
       line-height: 1.5;
-      margin: 0;
     }
   }
+}
+
+@media (min-width: 768px) {
+  .recipe-image-container {
+    height: 350px;
+  }
   
   .section-card {
-    margin: 20px 15px;
-    border-radius: 15px;
-    box-shadow: 0 4px 16px rgba(0, 0, 0, 0.1);
-    
-    .section-header {
-      padding-bottom: 0;
-      
-      .section-title {
-        font-size: 1.2rem;
-        font-weight: bold;
-        display: flex;
-        align-items: center;
-        
-        .section-icon {
-          margin-right: 10px;
-          color: var(--ion-color-primary);
-        }
-      }
-    }
-    
-    .ingredient-list {
-      .ingredient-item {
-        --padding-start: 0;
-        --inner-padding-end: 0;
-        --min-height: 48px;
-        
-        .ingredient-bullet {
-          font-size: 8px;
-        }
-        
-        .ingredient-name {
-          font-size: 15px;
-        }
-        
-        .ingredient-amount {
-          font-weight: bold;
-          font-size: 13px;
-        }
-      }
-    }
-    
-    .step-list {
-      .step-item {
-        --padding-start: 0;
-        --inner-padding-end: 0;
-        --min-height: auto;
-        align-items: flex-start;
-        margin-bottom: 20px;
-        
-        .step-number {
-          width: 28px;
-          height: 28px;
-          display: flex;
-          align-items: center;
-          justify-content: center;
-          margin-right: 15px;
-          margin-top: 2px;
-        }
-        
-        .step-text {
-          p {
-            margin: 0;
-            font-size: 15px;
-            line-height: 1.5;
-          }
-        }
-      }
-    }
+    margin: 20px auto;
+    max-width: 800px;
   }
+}
+
+/* 头部样式 */
+.recipe-header {
+ion-toolbar {
+  --background: white;
+  --border-width: 0;
+  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
   
   .header-title {
-    font-weight: bold;
     font-size: 1.2rem;
-  }
+    font-weight: 600;
+    color: var(--ion-color-dark);
+  }
+}
+}
+
+/* 内容区域 */
+.recipe-content {
+--background: #f8f9fa;
+padding-bottom: 80px;
+}
+
+/* 菜品图片 */
+.recipe-image-container {
+position: relative;
+width: 100%;
+height: 250px;
+overflow: hidden;
+
+.recipe-image {
+  width: 100%;
+  height: 100%;
+  object-fit: cover;
+}
+
+.image-overlay {
+  position: absolute;
+  bottom: 16px;
+  left: 240px;
+  right: 16px;
+  display: flex;
+  gap: 8px;
+  width: 150px;
+  ion-chip {
+    --background: rgba(255, 255, 255, 0.9);
+    backdrop-filter: blur(5px);
+  }
+}
+}
+
+/* 菜品信息部分 */
+.recipe-info-section {
+padding: 16px;
+background: white;
+margin-bottom: 16px;
+}
+
+.recipe-header {
+display: flex;
+justify-content: space-between;
+align-items: center;
+margin-bottom: 12px;
+
+.recipe-title {
+  font-size: 1.5rem;
+  font-weight: 600;
+  color: var(--ion-color-dark);
+  margin: 0;
+  flex: 1;
+}
+
+.recipe-rating {
+  display: flex;
+  align-items: center;
+  
+  ion-icon {
+    font-size: 1.2rem;
+    margin-right: 2px;
+  }
+  
+  .rating-text {
+    font-size: 0.9rem;
+    color: var(--ion-color-medium);
+    margin-left: 4px;
+  }
+}
+}
+
+.recipe-meta {
+display: flex;
+flex-wrap: wrap;
+gap: 8px;
+margin-bottom: 16px;
+
+.meta-item {
+  --padding-start: 0;
+  --inner-padding-end: 0;
+  --min-height: 32px;
+  flex: 1 0 calc(33.333% - 8px);
+  
+  ion-icon {
+    font-size: 1.2rem;
+  }
+  
+  ion-label {
+    font-size: 0.85rem;
+    color: var(--ion-color-medium);
+  }
+}
+}
+
+.recipe-description {
+font-size: 0.95rem;
+color: var(--ion-color-medium);
+line-height: 1.6;
+margin: 0;
+}
+
+/* 卡片部分 */
+.section-card {
+margin: 16px;
+border-radius: 12px;
+box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
+
+.section-header {
+  padding-bottom: 0;
+  
+  .section-title {
+    font-size: 1.1rem;
+    font-weight: 600;
+    display: flex;
+    align-items: center;
+    
+    .section-icon {
+      margin-right: 8px;
+      color: var(--ion-color-primary);
+    }
+  }
+}
+}
+
+/* 食材列表 */
+.ingredient-list {
+.ingredient-item {
+  --padding-start: 0;
+  --inner-padding-end: 0;
+  --min-height: 48px;
+  border-bottom: 1px dashed var(--ion-color-light-shade);
+  
+  &:last-child {
+    border-bottom: none;
+  }
+  
+  .bullet-icon {
+    color: var(--ion-color-primary);
+    font-size: 0.6rem;
+  }
+  
+  .ingredient-name {
+    font-size: 0.95rem;
+  }
+  
+  .ingredient-amount {
+    font-weight: 500;
+  }
+}
+}
+
+/* 步骤列表 */
+.step-list {
+.step-item {
+  --padding-start: 0;
+  --inner-padding-end: 0;
+  --min-height: auto;
+  align-items: flex-start;
+  padding: 12px 0;
+  
+  .step-number {
+    width: 28px;
+    height: 28px;
+    background: var(--ion-color-primary);
+    color: white;
+    font-size: 0.9rem;
+    font-weight: 600;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    margin-right: 12px;
+  }
+  
+  .step-text {
+    font-size: 0.95rem;
+    color: var(--ion-color-medium);
+    line-height: 1.6;
+    white-space: normal;
+  }
+}
+}
+
+/* 底部按钮 */
+.action-buttons {
+position: fixed;
+bottom: 0;
+left: 0;
+right: 0;
+padding: 16px;
+background: linear-gradient(to top, white 50%, transparent 100%);
+
+.cook-button {
+  --box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
+  --padding-top: 16px;
+  --padding-bottom: 16px;
+  font-weight: 600;
+}
+}
+
+/* 响应式调整 */
+@media (min-width: 768px) {
+.recipe-image-container {
+  height: 350px;
+}
+
+.recipe-info-section {
+  padding: 24px;
+}
+
+.section-card {
+  margin: 24px;
+}
+
+.action-buttons {
+  padding: 24px;
+  max-width: 600px;
+  margin: 0 auto;
+}
+}

+ 41 - 13
myapp/src/app/tab3/page-records/page-records.page.html

@@ -1,28 +1,56 @@
 <ion-header [translucent]="true">
-  <ion-toolbar>
+  <ion-toolbar color="primary">
     <ion-buttons slot="start">
-      <ion-back-button defaultHref="/"></ion-back-button>
+      <ion-back-button defaultHref="/" text="返回"></ion-back-button>
     </ion-buttons>
     <ion-title>浏览历史</ion-title>
+    <ion-buttons slot="end">
+      <ion-button ><!-- (click)="clearHistory()" -->
+        <ion-icon slot="icon-only" name="trash-outline"></ion-icon>
+      </ion-button>
+    </ion-buttons>
   </ion-toolbar>
 </ion-header>
 
-<ion-content [fullscreen]="true">
+<ion-content [fullscreen]="true" class="ion-padding">
   <!-- 浏览记录列表 -->
-  <ion-list>
-    <ion-item *ngFor="let item of recipeRecordList" (click)="goToDetail(item.id)">
-      <ion-thumbnail slot="start">
-        <img [src]="item.get('imageUrl')" [alt]="item.get('title')">
+  <ion-list lines="none" *ngIf="recipeRecordList.length > 0">
+    <ion-item 
+      *ngFor="let item of recipeRecordList" 
+      (click)="goToDetail(item.id)"
+      class="history-item"
+      detail="true"
+    >
+      <ion-thumbnail slot="start" class="item-thumbnail">
+        <img [src]="item.get('imageUrl')" [alt]="item.get('title')" class="thumbnail-img">
       </ion-thumbnail>
-      <ion-label>{{ item.get('title') }}</ion-label>
-      <ion-label>{{ item.get('description') }}</ion-label>
+      <ion-label class="item-content">
+        <h2 class="item-title">{{ item.get('title') }}</h2>
+        <p class="item-desc">{{ item.get('description')}}</p>
+        <div class="item-meta">
+          <span class="meta-rating">
+            <ion-icon name="star" color="warning"></ion-icon>
+            {{ item.get('rating') || '0.0' }}
+          </span>
+          <!-- <span class="meta-time">
+            <ion-icon name="time-outline"></ion-icon>
+            {{ item.get('cookingTime') || '未知' }}
+          </span> -->
+        </div>
+      </ion-label>
     </ion-item>
   </ion-list>
 
   <!-- 空状态提示 -->
-  <div class="empty-state" *ngIf="historyList.length === 0">
-    <ion-icon name="time-outline"></ion-icon>
-    <h3>暂无浏览记录</h3>
-    <p>您浏览过的菜品将会显示在这里</p>
+  <div class="empty-state ion-text-center" *ngIf="recipeRecordList.length === 0">
+    <div class="empty-icon">
+      <ion-icon name="time-outline" color="medium"></ion-icon>
+    </div>
+    <h3 class="empty-title">暂无浏览记录</h3>
+    <p class="empty-text">您浏览过的菜品将会显示在这里</p>
+    <ion-button fill="outline" color="medium" (click)="loadRecipeFavoriteList()">
+      <ion-icon slot="start" name="refresh"></ion-icon>
+      刷新
+    </ion-button>
   </div>
 </ion-content>

+ 74 - 30
myapp/src/app/tab3/page-records/page-records.page.scss

@@ -1,39 +1,83 @@
-ion-thumbnail {
-    --size: 64px;
-    --border-radius: 8px;
-    
-    img {
-      object-fit: cover;
-    }
+/* 历史记录项样式 */
+.history-item {
+  --padding-start: 0;
+  --inner-padding-end: 0;
+  --background: var(--ion-color-light);
+  border-radius: 12px;
+  margin-bottom: 12px;
+  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
+}
+
+.item-thumbnail {
+  --size: 80px;
+  --border-radius: 8px;
+  margin: 8px;
+  
+  .thumbnail-img {
+    border-radius: 8px;
+    object-fit: cover;
   }
+}
+
+.item-content {
+  margin: 10px 0;
   
-  ion-item {
-    --padding-start: 16px;
-    --padding-end: 16px;
+  .item-title {
+    font-weight: 600;
+    font-size: 1.1rem;
+    margin-bottom: 5px;
   }
   
-  .empty-state {
-    display: flex;
-    flex-direction: column;
-    align-items: center;
-    justify-content: center;
-    height: 60vh;
-    text-align: center;
+  .item-desc {
     color: var(--ion-color-medium);
+    font-size: 0.9rem;
+    margin-bottom: 8px;
+  }
+  
+  .item-meta {
+    display: flex;
+    gap: 15px;
     
-    ion-icon {
-      font-size: 48px;
-      margin-bottom: 16px;
-    }
-    
-    h3 {
-      font-size: 18px;
-      margin-bottom: 8px;
-      color: var(--ion-color-dark);
+    .meta-rating, .meta-time {
+      display: flex;
+      align-items: center;
+      font-size: 0.85rem;
+      color: var(--ion-color-medium);
+      
+      ion-icon {
+        margin-right: 4px;
+      }
     }
     
-    p {
-      font-size: 14px;
-      margin: 0;
+    .meta-rating {
+      color: var(--ion-color-warning);
     }
-  }
+  }
+}
+
+/* 空状态样式 */
+.empty-state {
+  height: 70vh;
+  display: flex;
+  flex-direction: column;
+  justify-content: center;
+  align-items: center;
+  
+  .empty-icon {
+    font-size: 4rem;
+    margin-bottom: 20px;
+    opacity: 0.5;
+  }
+  
+  .empty-title {
+    color: var(--ion-color-medium);
+    font-weight: 600;
+    margin-bottom: 8px;
+  }
+  
+  .empty-text {
+    color: var(--ion-color-medium);
+    margin-bottom: 20px;
+    font-size: 0.9rem;
+  }
+}

+ 1 - 1
myapp/src/app/tab3/tab3.page.ts

@@ -97,7 +97,7 @@ export class Tab3Page {
   }
   async login() {
     let user : any = new CloudUser();
-     user = await this.currentUser?.login("abctest","1234")
+     user = await this.currentUser?.login("0224989","123456")
       if(user?.id){
         this.currentUser = user;
       }

BIN
myapp/src/assets/avatar.png


+ 1 - 0
myapp/src/lib/ncloud.ts

@@ -17,6 +17,7 @@ export class CloudObject {
     cookingTime: any;
     rating: any;
     objectId: any;
+    
 
     constructor(className: string) {
         this.className = className;