Browse Source

美化首页图片

CuddleNan 1 day ago
parent
commit
8df537e884

+ 81 - 31
myapp/src/app/tab1/page-detail/page-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>

+ 237 - 1
myapp/src/app/tab1/page-detail/page-detail.page.scss

@@ -110,4 +110,240 @@
       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: 16px;
+    right: 16px;
+    display: flex;
+    gap: 8px;
+    
+    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;
+  }
+}

+ 13 - 3
myapp/src/app/tab1/page-detail/page-detail.page.ts

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

+ 57 - 15
myapp/src/app/tab1/page-type/page-type.page.html

@@ -1,27 +1,69 @@
-<ion-header [translucent]="true">
-  <ion-toolbar>
+<ion-header [translucent]="true" class="custom-header">
+  <ion-toolbar color="success">
     <ion-buttons slot="start">
-      <ion-back-button defaultHref="/"></ion-back-button>
+      <ion-back-button defaultHref="/" text="" color="light"></ion-back-button>
     </ion-buttons>
-    <ion-title>{{ categoryName }}</ion-title>
+    <ion-title class="header-title">
+      <ion-icon name="restaurant" class="title-icon"></ion-icon>
+      {{ categoryName }}
+    </ion-title>
   </ion-toolbar>
 </ion-header>
 
-
-<ion-content [fullscreen]="true">
-  <ion-list>
+<ion-content [fullscreen]="true" class="custom-content">
+  <!-- 食谱列表 -->
+  <ion-list lines="none" class="recipe-list">
     <ion-item 
       *ngFor="let recipe of recipeList" 
+      class="recipe-item"
       [routerLink]="['/recipe-detail', recipe.get('objectId')]"
-      detail="true" (click)="goToDetail(recipe)">
-      <ion-thumbnail slot="start">
-        <img [src]="recipe.get('imageUrl')" [alt]="recipe.get('title')">
+      detail="false"
+      (click)="goToDetail(recipe)">
+      
+      <ion-thumbnail slot="start" class="recipe-thumbnail">
+        <img [src]="recipe.get('imageUrl') || 'assets/images/default-food.jpg'" 
+             [alt]="recipe.get('title')"
+             class="recipe-image">
       </ion-thumbnail>
-      <ion-label>
-        <h2>{{ recipe.get('title') }}</h2>
-        <p *ngIf="recipe.get('description')">{{ recipe.get('description') }}</p>
+      
+      <ion-label class="recipe-label">
+        <h2 class="recipe-title">{{ recipe.get('title') }}</h2>
+        <p class="recipe-description" *ngIf="recipe.get('description')">
+          {{ recipe.get('description') }}
+        </p>
+        
+        <div class="recipe-meta">
+          <span class="meta-item">
+            <ion-icon name="time-outline" class="meta-icon"></ion-icon>
+            {{ recipe.get('cookingTime') || 30 }}分钟
+          </span>
+          <span class="meta-item">
+            <ion-icon name="star" class="meta-icon" color="warning"></ion-icon>
+            {{ recipe.get('rating') || 4.5 }}
+          </span>
+        </div>
       </ion-label>
+      
+      <ion-icon slot="end" name="chevron-forward" class="arrow-icon"></ion-icon>
     </ion-item>
   </ion-list>
-  <button (click)="importRecipeList()">导入食谱列表数据</button>
-</ion-content>
+
+  <!-- 导入按钮 -->
+  <div class="import-button-container">
+    <ion-button expand="block" color="medium" (click)="importRecipeList()" class="import-button">
+      <ion-icon slot="start" name="cloud-upload-outline"></ion-icon>
+      导入食谱列表数据
+    </ion-button>
+  </div>
+
+  <!-- 空状态 -->
+  <div class="empty-state" *ngIf="recipeList.length === 0">
+    <ion-icon name="fast-food-outline" class="empty-icon"></ion-icon>
+    <h3>暂无食谱</h3>
+    <p>当前分类下还没有食谱,快来添加第一个吧!</p>
+    <ion-button expand="block" color="medium" (click)="importRecipeList()" class="empty-button">
+      <ion-icon slot="start" name="cloud-upload-outline"></ion-icon>
+      导入食谱
+    </ion-button>
+  </div>
+</ion-content>

+ 186 - 1
myapp/src/app/tab1/page-type/page-type.page.scss

@@ -38,4 +38,189 @@ ion-thumbnail {
     ion-thumbnail {
       --size: 100px;
     }
-  }
+  }
+  
+  /* 头部样式 */
+.custom-header {
+  ion-toolbar {
+    --background: var(--ion-color-success);
+    --color: white;
+    
+    .header-title {
+      display: flex;
+      align-items: center;
+      font-size: 1.2rem;
+      
+      .title-icon {
+        margin-right: 8px;
+        font-size: 1.4rem;
+      }
+    }
+  }
+}
+
+/* 内容区域 */
+.custom-content {
+  --background: #f8f9fa;
+  padding-top: 8px;
+}
+
+/* 食谱列表 */
+.recipe-list {
+  background: transparent;
+  padding: 0 8px;
+}
+
+.recipe-item {
+  --padding-start: 8px;
+  --inner-padding-end: 8px;
+  --border-radius: 12px;
+  margin-bottom: 12px;
+  background: white;
+  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
+  transition: transform 0.3s ease, box-shadow 0.3s ease;
+  
+  &:active {
+    transform: scale(0.98);
+    box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
+  }
+}
+
+.recipe-thumbnail {
+  position: relative;
+  margin: 8px;
+  border-radius: 8px;
+  overflow: hidden;
+  width: 80px;
+  height: 80px;
+  
+  .recipe-image {
+    width: 100%;
+    height: 100%;
+    object-fit: cover;
+  }
+}
+
+.recipe-label {
+  margin: 8px 0;
+  
+  .recipe-title {
+    font-size: 1rem;
+    font-weight: 600;
+    margin-bottom: 4px;
+    color: var(--ion-color-dark);
+  }
+  
+  .recipe-description {
+    font-size: 0.8rem;
+    color: var(--ion-color-medium);
+    margin: 4px 0;
+    display: -webkit-box;
+    -webkit-line-clamp: 2;
+    -webkit-box-orient: vertical;
+    overflow: hidden;
+    text-overflow: ellipsis;
+  }
+}
+
+.recipe-meta {
+  display: flex;
+  flex-wrap: wrap;
+  gap: 12px;
+  margin-top: 8px;
+  
+  .meta-item {
+    display: flex;
+    align-items: center;
+    font-size: 0.75rem;
+    color: var(--ion-color-medium);
+    
+    .meta-icon {
+      margin-right: 4px;
+      font-size: 0.9rem;
+    }
+  }
+}
+
+.arrow-icon {
+  color: var(--ion-color-medium-shade);
+}
+
+/* 导入按钮 */
+.import-button-container {
+  padding: 16px;
+  
+  .import-button {
+    --border-radius: 12px;
+    --box-shadow: none;
+    font-weight: 500;
+  }
+}
+
+/* 空状态 */
+.empty-state {
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  justify-content: center;
+  height: 60vh;
+  text-align: center;
+  padding: 0 32px;
+  
+  .empty-icon {
+    font-size: 3rem;
+    color: var(--ion-color-medium);
+    margin-bottom: 16px;
+  }
+  
+  h3 {
+    font-size: 1.2rem;
+    color: var(--ion-color-dark);
+    margin-bottom: 8px;
+  }
+  
+  p {
+    font-size: 0.9rem;
+    color: var(--ion-color-medium);
+    margin-bottom: 16px;
+  }
+  
+  .empty-button {
+    --border-radius: 12px;
+    --box-shadow: none;
+    font-weight: 500;
+    width: 80%;
+  }
+}
+
+/* 响应式调整 */
+@media (min-width: 768px) {
+  .recipe-list {
+    padding: 0 16px;
+  }
+  
+  .recipe-item {
+    --padding-start: 16px;
+    --inner-padding-end: 16px;
+    margin-bottom: 16px;
+  }
+  
+  .recipe-thumbnail {
+    width: 100px;
+    height: 100px;
+  }
+  
+  .recipe-title {
+    font-size: 1.1rem !important;
+  }
+  
+  .recipe-description {
+    font-size: 0.9rem !important;
+  }
+  
+  .import-button-container {
+    padding: 24px;
+    max-width: 400px;
+    margin: 0 auto;
+  }
+}

+ 10 - 1
myapp/src/app/tab1/page-type/page-type.page.ts

@@ -1,7 +1,16 @@
 import { Component, OnInit } from '@angular/core';
 import { ActivatedRoute } from '@angular/router';
 import { NavController } from '@ionic/angular';
-import { IonBackButton, IonButtons, IonContent, IonHeader, IonItem, IonLabel, IonList, IonThumbnail, IonTitle, IonToolbar } from '@ionic/angular/standalone';
+import { 
+  IonHeader, IonToolbar, IonTitle, IonContent, 
+  IonBackButton, IonButtons, IonList, IonItem, 
+  IonThumbnail, IonLabel, IonButton, IonIcon 
+} from '@ionic/angular/standalone';
+import { addIcons } from 'ionicons';
+import { 
+  restaurant, chevronForward, timeOutline, 
+  star, cloudUploadOutline, fastFoodOutline 
+} from 'ionicons/icons';
 import { importAllData } from '../../import-recipe-data';
 import { CloudObject, CloudQuery } from 'src/lib/ncloud';
 

+ 74 - 67
myapp/src/app/tab1/tab1.page.html

@@ -1,97 +1,104 @@
+<!-- tab1.page.html -->
 <ion-header [translucent]="true">
-  <ion-toolbar class="custom-header">
-    <ion-title class="logo">
-      🍳 <span>味知星厨</span>
+  <ion-toolbar class="header-toolbar">
+    <ion-title class="header-title">
+      <span class="logo-icon">🍳</span>
+      <span class="logo-text">味知星厨</span>
     </ion-title>
-    <ion-buttons slot="end">
-      <ion-button class="nav-btn" (click)="login()">登录</ion-button>
-      <ion-button class="nav-btn" (click)="register()">注册</ion-button>
-    </ion-buttons>
   </ion-toolbar>
 </ion-header>
 
-<ion-content [fullscreen]="true" class="bg-light">
+<ion-content [fullscreen]="true" class="content-background">
   <!-- 搜索栏 -->
-  <ion-card class="search-card">
-    <ion-row class="search-row">
-      <ion-col size="10">
-        <ion-input 
-          class="search-input" 
-          type="text" 
+  <div class="search-container">
+    <ion-card class="search-card">
+      <ion-item lines="none" class="search-item">
+        <ion-input
+          class="search-input"
+          type="text"
           placeholder="搜索食谱(如:番茄炒蛋、低卡沙拉)"
           [(ngModel)]="searchQuery"
-          autocomplete="food"
-          spellcheck="false"
-          aria-label="食谱搜索"
+          clearInput
+          enterkeyhint="search"
+          (keyup.enter)="performSearch()"
         ></ion-input>
-      </ion-col>
-      <ion-col size="2">
         <ion-button 
-          class="search-btn" 
-          shape="round" 
+          slot="end" 
+          fill="clear" 
+          class="search-button" 
           (click)="performSearch()"
-          aria-label="搜索食谱"
+          aria-label="搜索"
         >
-          <ion-icon name="search" class="icon-md text-white"></ion-icon>
+          <ion-icon slot="icon-only" name="search"></ion-icon>
         </ion-button>
-      </ion-col>
-    </ion-row>
-  </ion-card>
+      </ion-item>
+    </ion-card>
+  </div>
 
   <!-- 分类网格 -->
-  <ion-grid class="category-grid" fixed>
-    <ion-row class="ion-justify-content-around">
-      <ion-col 
-        size="6" 
-        md="4" 
-        lg="3" 
-        class="category-card" 
-        *ngFor="let category of categories"
-        (click)="navigateToCategory(category)"
-        
-      >
-        <ion-card class="card-hover" (click)="goToTypeList()">
-          <ion-card-content class="text-center p-4">
-            <!-- <ion-icon [name]="category.icon" class="category-icon"></ion-icon> -->
-             <img style="width:64px;border-radius: 10px;" src="/assets/icon/{{category.name}}.jpg" alt="">
-            <p class="category-title">{{ category.name }}</p>
-          </ion-card-content>
-        </ion-card>
-      </ion-col>
-    </ion-row>
-  </ion-grid>
+  <div class="section-container">
+    <h2 class="section-title">美食分类</h2>
+    <ion-grid class="category-grid">
+      <ion-row>
+        <ion-col 
+          size="6" 
+          md="4" 
+          lg="3" 
+          *ngFor="let category of categories"
+          (click)="navigateToCategory()"
+        >
+          <ion-card class="category-card" >
+            <ion-card-content class="category-content">
+              <div class="category-icon-container">
+                <ion-icon [name]="category.icon" class="category-icon"></ion-icon>
+                <img style="width:64px;border-radius: 50px;" src="/assets/icon/{{category.name}}.jpg" alt="">
+              </div>
+              <h3 class="category-title">{{ category.name }}</h3>
+            </ion-card-content>
+          </ion-card>
+        </ion-col>
+      </ion-row>
+    </ion-grid>
+  </div>
 
   <!-- 推荐食谱 -->
-<ion-card class="recommend-card">
-  <ion-card-header class="px-4 pt-4">
-    <h2 class="section-title">今日推荐食谱</h2>
-  </ion-card-header>
-  <ion-card-content class="px-4">
-    <ion-grid fixed>
-      <ion-row class="ion-justify-content-around">
+  <div class="section-container">
+    <h2 class="section-title">今日推荐</h2>
+    <ion-grid class="recipe-grid">
+      <ion-row>
         <ion-col 
           size="12" 
           md="6" 
           lg="4" 
-          class="recipe-card" 
           *ngFor="let recipe of recipeGroup"
           (click)="goToDetail(recipe)"
-        > 
-          <ion-card class="recipe-card-hover">
-            <ion-img [src]="recipe.imageUrl || '/assets/images/default-food.jpg'"></ion-img>
-            <ion-card-content class="p-4">
-              <h3 class="recipe-title">{{  recipe.title }}</h3>
-              <div class="recipe-meta">
-                <ion-icon name="time" class="icon-md"></ion-icon> {{  recipe.cookingTime || 30 }}分钟
-                <ion-icon name="star" class="icon-md text-primary"></ion-icon> {{ recipe.rating || 4.5 }}评分
+        >
+          <ion-card class="recipe-card" (click)="goToDetail(recipe)">
+            <div class="recipe-image-container">
+              <ion-img 
+                [src]="recipe.imageUrl || '/assets/images/default-food.jpg'" 
+                alt="食谱图片"
+                class="recipe-image"
+              ></ion-img>
+              <div class="recipe-overlay">
+                <ion-badge class="recipe-time">
+                  <ion-icon name="time"></ion-icon>
+                  {{ recipe.cookingTime || 30 }}分钟
+                </ion-badge>
+              </div>
+            </div>
+            <ion-card-header>
+              <ion-card-title class="recipe-title">{{ recipe.title }}</ion-card-title>
+            </ion-card-header>
+            <ion-card-content class="recipe-content">
+              <div class="recipe-rating">
+                <ion-icon name="star" class="rating-icon"></ion-icon>
+                <span class="rating-value">{{ recipe.rating || 4.5 }}</span>
               </div>
             </ion-card-content>
           </ion-card>
         </ion-col>
       </ion-row>
     </ion-grid>
-  </ion-card-content>
-</ion-card>
-
-  
+  </div>
 </ion-content>

+ 192 - 1
myapp/src/app/tab1/tab1.page.scss

@@ -141,4 +141,195 @@
     border-radius: 50%;
     font-size: 1.5rem;
     cursor: pointer;
-  }
+  }
+/* tab1.page.scss */
+/* 全局样式 */
+ion-content {
+  --background: #f8f9fa;
+}
+
+/* 头部样式 */
+.header-toolbar {
+  --background: #ff6b6b;
+  --color: white;
+}
+
+.header-title {
+  display: flex;
+  align-items: center;
+  font-weight: bold;
+}
+
+.logo-icon {
+  font-size: 1.5rem;
+  margin-right: 8px;
+}
+
+.logo-text {
+  font-family: 'Arial Rounded MT Bold', sans-serif;
+}
+
+/* 搜索栏样式 */
+.search-container {
+  padding: 16px;
+}
+
+.search-card {
+  border-radius: 12px;
+  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
+}
+
+.search-item {
+  --padding-start: 12px;
+  --inner-padding-end: 8px;
+}
+
+.search-input {
+  --placeholder-color: #adb5bd;
+  --color: #495057;
+  font-size: 0.9rem;
+}
+
+.search-button {
+  --color: #ff6b6b;
+}
+
+/* 分类部分样式 */
+.section-container {
+  padding: 0 16px 16px;
+}
+
+.section-title {
+  font-size: 1.2rem;
+  font-weight: bold;
+  color: #343a40;
+  margin-bottom: 16px;
+  padding-left: 8px;
+  border-left: 4px solid #ff6b6b;
+}
+
+.category-grid {
+  padding: 0;
+}
+
+.category-card {
+  margin: 0;
+  border-radius: 12px;
+  transition: transform 0.3s ease, box-shadow 0.3s ease;
+  
+  &:active {
+    transform: scale(0.98);
+  }
+}
+
+.category-content {
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  padding: 16px 8px;
+}
+
+.category-icon-container {
+  width: 48px;
+  height: 48px;
+  background: #fff5f5;
+  border-radius: 50%;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  margin-bottom: 12px;
+}
+
+.category-icon {
+  font-size: 1.5rem;
+  color: #ff6b6b;
+}
+
+.category-title {
+  font-size: 0.9rem;
+  font-weight: 500;
+  color: #495057;
+  margin: 0;
+  text-align: center;
+}
+
+/* 推荐食谱样式 */
+.recipe-grid {
+  padding: 0;
+}
+
+.recipe-card {
+  margin: 0;
+  border-radius: 12px;
+  overflow: hidden;
+  transition: transform 0.3s ease;
+  
+  &:active {
+    transform: scale(0.98);
+  }
+}
+
+.recipe-image-container {
+  position: relative;
+  height: 160px;
+  overflow: hidden;
+}
+
+.recipe-image {
+  width: 100%;
+  height: 100%;
+  object-fit: cover;
+}
+
+.recipe-overlay {
+  position: absolute;
+  bottom: 8px;
+  left: 8px;
+}
+
+.recipe-time {
+  --background: rgba(0, 0, 0, 0.7);
+  --color: white;
+  font-weight: 500;
+  
+  ion-icon {
+    margin-right: 4px;
+  }
+}
+
+.recipe-title {
+  font-size: 1rem;
+  font-weight: 600;
+  color: #343a40;
+}
+
+.recipe-content {
+  padding-top: 0;
+}
+
+.recipe-rating {
+  display: flex;
+  align-items: center;
+}
+
+.rating-icon {
+  color: #ffc107;
+  margin-right: 4px;
+}
+
+.rating-value {
+  font-size: 0.9rem;
+  color: #6c757d;
+}
+
+/* 响应式调整 */
+@media (min-width: 768px) {
+  .section-container {
+    padding: 0 24px 24px;
+  }
+  
+  .recipe-image-container {
+    height: 200px;
+  }
+}
+  

+ 5 - 2
myapp/src/app/tab1/tab1.page.ts

@@ -2,6 +2,7 @@ import { Component, OnInit, Renderer2 } from '@angular/core';
 import { Router } from '@angular/router';
 import { NavController } from '@ionic/angular';
 import { CloudObject, CloudQuery } from 'src/lib/ncloud';
+import { IonicModule } from '@ionic/angular'; 
 
 @Component({
   selector: 'app-tab1',
@@ -9,6 +10,7 @@ import { CloudObject, CloudQuery } from 'src/lib/ncloud';
   styleUrls: ['tab1.page.scss'],
   standalone: false,
 })
+
 export class Tab1Page implements OnInit {
   searchQuery: string = '';
   categories: any[] = [
@@ -73,8 +75,9 @@ export class Tab1Page implements OnInit {
     this.router.navigate(['/register']);
   }
 
-  navigateToCategory(category: any) {
-    this.router.navigate(['/category', category.name]);
+  navigateToCategory() {
+    this.navCtrl.navigateForward(["tabs", "tab1", "page-type"]);
+    console.log('Navigating to page-detail');
   }
 
   goToRecipeDetail(recipeId: number) {

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

@@ -1,72 +1,122 @@
 <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="" color="light"></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>
+      <ion-button (click)="shareRecipe()">
+        <ion-icon name="share-social-outline" color="light"></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/default-recipe.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="light" class="category-chip">
+        <ion-icon name="pricetag" slot="start" color="primary"></ion-icon>
+        {{ recipe?.get('category') || '家常菜' }}
+      </ion-chip>
+      <ion-chip color="light" class="time-chip">
+        <ion-icon name="time" slot="start" color="warning"></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-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>
+    <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>
+      <p class="recipe-description">{{ recipe?.get('description') || '一道美味的家常菜,简单易学,营养丰富' }}</p>
+    </ion-card-content>
+  </ion-card>
+
   <!-- 食材部分 -->
   <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" color="medium" class="ingredient-bullet"></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-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-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">
+          <ion-badge color="primary" slot="start" class="step-number">
             {{ i + 1 }}
-          </ion-avatar>
-          <ion-label class="ion-text-wrap">
+          </ion-badge>
+          <ion-label class="ion-text-wrap step-text">
             <p>{{ step }}</p>
           </ion-label>
         </ion-item>
       </ion-list>
     </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>
 </ion-content>

+ 164 - 0
myapp/src/app/tab3/page-records/page-records-detail/page-records-detail.page.scss

@@ -110,4 +110,168 @@
       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;
+      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;
+      
+      .rating-badge {
+        font-size: 14px;
+        padding: 6px 10px;
+        
+        ion-icon {
+          font-size: 14px;
+          margin-right: 3px;
+        }
+      }
+    }
+  }
+  
+  .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;
+    
+    .recipe-title {
+      font-size: 1.5rem;
+      font-weight: bold;
+      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;
+    }
+  }
+  
+  .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;
+          }
+        }
+      }
+    }
+  }
+  
+  .header-title {
+    font-weight: bold;
+    font-size: 1.2rem;
   }

+ 68 - 14
myapp/src/app/tab3/page-records/page-records-detail/page-records-detail.page.ts

@@ -1,21 +1,59 @@
 import { Component, OnInit } from '@angular/core';
+import { 
+  IonHeader, 
+  IonToolbar, 
+  IonTitle, 
+  IonContent, 
+  IonBackButton, 
+  IonButtons, 
+  IonButton, 
+  IonIcon, 
+  IonCard, 
+  IonCardHeader, 
+  IonCardTitle, 
+  IonCardContent,
+  IonList,
+  IonItem,
+  IonLabel,
+  IonChip,
+  IonBadge,
+  IonAvatar,
+  IonFab,
+  IonFabButton
+} from '@ionic/angular/standalone';
 import { ActivatedRoute } from '@angular/router';
 import { addIcons } from 'ionicons';
-import { basketOutline, bookmark, bookmarkOutline, flameOutline, peopleOutline, restaurantOutline, shareSocialOutline, star, starOutline, timeOutline } from 'ionicons/icons';
+import { 
+  timeOutline, 
+  flameOutline, 
+  peopleOutline, 
+  basketOutline, 
+  restaurantOutline,
+  star,
+  starOutline,
+  bookmark,
+  bookmarkOutline,
+  shareSocialOutline,
+  pricetag,
+  time,
+  ellipse,
+  ellipseOutline
+} from 'ionicons/icons';
 import { CloudObject, CloudQuery } from 'src/lib/ncloud';
 
 @Component({
   selector: 'app-page-records-detail',
   templateUrl: './page-records-detail.page.html',
   styleUrls: ['./page-records-detail.page.scss'],
-  standalone: false
+  standalone: false,
 })
 export class PageRecordsDetailPage implements OnInit {
+  recipe: CloudObject | undefined | null;
+  isBookmarked = false;
 
-  constructor(
-    private route: ActivatedRoute
-  ) {
-    addIcons({ timeOutline, 
+  constructor(private route: ActivatedRoute) {
+    addIcons({ 
+      timeOutline, 
       flameOutline, 
       peopleOutline, 
       basketOutline, 
@@ -24,22 +62,38 @@ export class PageRecordsDetailPage implements OnInit {
       starOutline,
       bookmark,
       bookmarkOutline,
-      shareSocialOutline });
+      shareSocialOutline,
+      pricetag,
+      time,
+      ellipse,
+      ellipseOutline
+    });
+    
     this.route.params.subscribe(params => {
-     console.log(params) ;
-     this.loadRecipe(params['recipeId']);
-    })
+      this.loadRecipe(params['recipeId']);
+    });
   }
 
-  recipe : CloudObject | undefined |null;
-
   async loadRecipe(recipeId: string) {
     let query = new CloudQuery("Recipe");
     this.recipe = await query.get(recipeId);
     console.log(this.recipe);
   }
 
-  ngOnInit() {
+  toggleBookmark() {
+    this.isBookmarked = !this.isBookmarked;
+    // 这里可以添加收藏/取消收藏的逻辑
+  }
+
+  shareRecipe() {
+    // 这里可以添加分享逻辑
+    console.log('分享菜谱');
+  }
+
+  rateRecipe() {
+    // 这里可以添加评分逻辑
+    console.log('评分菜谱');
   }
 
-}
+  ngOnInit() {}
+}

+ 1 - 0
myapp/src/app/tab3/page-records/page-records.page.html

@@ -15,6 +15,7 @@
         <img [src]="item.get('imageUrl')" [alt]="item.get('title')">
       </ion-thumbnail>
       <ion-label>{{ item.get('title') }}</ion-label>
+      <ion-label>{{ item.get('description') }}</ion-label>
     </ion-item>
   </ion-list>
 

BIN
myapp/src/assets/food/fqdh.jpeg


BIN
myapp/src/assets/food/gbjd.jpeg


BIN
myapp/src/assets/food/hsr.jpeg


BIN
myapp/src/assets/food/jdnp.jpeg


BIN
myapp/src/assets/food/lmss.jpeg


BIN
myapp/src/assets/food/pdsr.jpeg


BIN
myapp/src/assets/food/qkl.jpeg


BIN
myapp/src/assets/food/sssl.jpeg


BIN
myapp/src/assets/food/ssx.jpeg


BIN
myapp/src/assets/food/tlms.jpeg


+ 0 - 0
myapp/src/assets/food/jxsl.jpg → myapp/src/assets/food/xjjx.jpg