浏览代码

食谱检索

CuddleNan 1 天之前
父节点
当前提交
9e11f51465
共有 21 个文件被更改,包括 906 次插入51 次删除
  1. 17 0
      myapp/src/app/tab1/page-selectlist/page-selectlist-detail/page-selectlist-detail-routing.module.ts
  2. 20 0
      myapp/src/app/tab1/page-selectlist/page-selectlist-detail/page-selectlist-detail.module.ts
  3. 122 0
      myapp/src/app/tab1/page-selectlist/page-selectlist-detail/page-selectlist-detail.page.html
  4. 349 0
      myapp/src/app/tab1/page-selectlist/page-selectlist-detail/page-selectlist-detail.page.scss
  5. 17 0
      myapp/src/app/tab1/page-selectlist/page-selectlist-detail/page-selectlist-detail.page.spec.ts
  6. 43 0
      myapp/src/app/tab1/page-selectlist/page-selectlist-detail/page-selectlist-detail.page.ts
  7. 22 0
      myapp/src/app/tab1/page-selectlist/page-selectlist-routing.module.ts
  8. 20 0
      myapp/src/app/tab1/page-selectlist/page-selectlist.module.ts
  9. 43 0
      myapp/src/app/tab1/page-selectlist/page-selectlist.page.html
  10. 121 0
      myapp/src/app/tab1/page-selectlist/page-selectlist.page.scss
  11. 17 0
      myapp/src/app/tab1/page-selectlist/page-selectlist.page.spec.ts
  12. 31 0
      myapp/src/app/tab1/page-selectlist/page-selectlist.page.ts
  13. 32 28
      myapp/src/app/tab1/tab1-routing.module.ts
  14. 1 1
      myapp/src/app/tab1/tab1.page.html
  15. 5 5
      myapp/src/app/tab1/tab1.page.scss
  16. 26 3
      myapp/src/app/tab1/tab1.page.ts
  17. 9 9
      myapp/src/app/tab2/tab2.page.html
  18. 2 2
      myapp/src/app/tab3/page-collections/page-collections.page.html
  19. 2 2
      myapp/src/app/tab3/page-records/page-records.page.html
  20. 1 1
      myapp/src/app/tab3/tab3.page.html
  21. 6 0
      myapp/src/lib/ncloud.ts

+ 17 - 0
myapp/src/app/tab1/page-selectlist/page-selectlist-detail/page-selectlist-detail-routing.module.ts

@@ -0,0 +1,17 @@
+import { NgModule } from '@angular/core';
+import { Routes, RouterModule } from '@angular/router';
+
+import { PageSelectlistDetailPage } from './page-selectlist-detail.page';
+
+const routes: Routes = [
+  {
+    path: '',
+    component: PageSelectlistDetailPage
+  }
+];
+
+@NgModule({
+  imports: [RouterModule.forChild(routes)],
+  exports: [RouterModule],
+})
+export class PageSelectlistDetailPageRoutingModule {}

+ 20 - 0
myapp/src/app/tab1/page-selectlist/page-selectlist-detail/page-selectlist-detail.module.ts

@@ -0,0 +1,20 @@
+import { NgModule } from '@angular/core';
+import { CommonModule } from '@angular/common';
+import { FormsModule } from '@angular/forms';
+
+import { IonicModule } from '@ionic/angular';
+
+import { PageSelectlistDetailPageRoutingModule } from './page-selectlist-detail-routing.module';
+
+import { PageSelectlistDetailPage } from './page-selectlist-detail.page';
+
+@NgModule({
+  imports: [
+    CommonModule,
+    FormsModule,
+    IonicModule,
+    PageSelectlistDetailPageRoutingModule
+  ],
+  declarations: [PageSelectlistDetailPage]
+})
+export class PageSelectlistDetailPageModule {}

+ 122 - 0
myapp/src/app/tab1/page-selectlist/page-selectlist-detail/page-selectlist-detail.page.html

@@ -0,0 +1,122 @@
+<ion-header [translucent]="true" class="recipe-header">
+  <ion-toolbar color="light">
+    <ion-buttons slot="start">
+      <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-toolbar>
+</ion-header>
+
+<ion-content [fullscreen]="true" class="recipe-content">
+  <!-- 菜品图片 -->
+  <div class="recipe-image-container">
+    <img [src]="recipe?.get('imageUrl') || 'assets/images/default-food.jpg'" 
+         [alt]="recipe?.get('title')" 
+         class="recipe-image">
+    <div class="image-overlay">
+      <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-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">
+      <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 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" 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">
+    <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" 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 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>

+ 349 - 0
myapp/src/app/tab1/page-selectlist/page-selectlist-detail/page-selectlist-detail.page.scss

@@ -0,0 +1,349 @@
+.recipe-image-container {
+    position: relative;
+    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;
+    }
+  }
+  
+  .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;
+        }
+      }
+    }
+  }
+  
+  .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);
+        }
+      }
+    }
+  }
+  
+  .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;
+    }
+    
+    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-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;
+  }
+  }

+ 17 - 0
myapp/src/app/tab1/page-selectlist/page-selectlist-detail/page-selectlist-detail.page.spec.ts

@@ -0,0 +1,17 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { PageSelectlistDetailPage } from './page-selectlist-detail.page';
+
+describe('PageSelectlistDetailPage', () => {
+  let component: PageSelectlistDetailPage;
+  let fixture: ComponentFixture<PageSelectlistDetailPage>;
+
+  beforeEach(() => {
+    fixture = TestBed.createComponent(PageSelectlistDetailPage);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});

+ 43 - 0
myapp/src/app/tab1/page-selectlist/page-selectlist-detail/page-selectlist-detail.page.ts

@@ -0,0 +1,43 @@
+import { Component, OnInit } from '@angular/core';
+import { ActivatedRoute } from '@angular/router';
+import { addIcons } from 'ionicons';
+import { basketOutline, bookmark, bookmarkOutline, flameOutline, peopleOutline, restaurantOutline, shareSocialOutline, star, starOutline, timeOutline } from 'ionicons/icons';
+import { CloudObject, CloudQuery } from 'src/lib/ncloud';
+
+@Component({
+  selector: 'app-page-selectlist-detail',
+  templateUrl: './page-selectlist-detail.page.html',
+  styleUrls: ['./page-selectlist-detail.page.scss'],
+  standalone: false
+})
+export class PageSelectlistDetailPage implements OnInit {
+  constructor(
+    private route: ActivatedRoute
+  ) {
+    addIcons({ timeOutline, 
+      flameOutline, 
+      peopleOutline, 
+      basketOutline, 
+      restaurantOutline,
+      star,
+      starOutline,
+      bookmark,
+      bookmarkOutline,
+      shareSocialOutline });
+    this.route.params.subscribe(params => {
+     console.log(params) ;
+     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() {
+  }
+}

+ 22 - 0
myapp/src/app/tab1/page-selectlist/page-selectlist-routing.module.ts

@@ -0,0 +1,22 @@
+import { NgModule } from '@angular/core';
+import { Routes, RouterModule } from '@angular/router';
+
+import { PageSelectlistPage } from './page-selectlist.page';
+
+const routes: Routes = [
+  {
+    path: '',
+    component: PageSelectlistPage
+  },
+  {
+    path: 'page-selectlist-detail/:recipeId',
+    loadChildren: () => import('./page-selectlist-detail/page-selectlist-detail.module').then( m => m.PageSelectlistDetailPageModule)
+  }
+
+];
+
+@NgModule({
+  imports: [RouterModule.forChild(routes)],
+  exports: [RouterModule],
+})
+export class PageSelectlistPageRoutingModule {}

+ 20 - 0
myapp/src/app/tab1/page-selectlist/page-selectlist.module.ts

@@ -0,0 +1,20 @@
+import { NgModule } from '@angular/core';
+import { CommonModule } from '@angular/common';
+import { FormsModule } from '@angular/forms';
+
+import { IonicModule } from '@ionic/angular';
+
+import { PageSelectlistPageRoutingModule } from './page-selectlist-routing.module';
+
+import { PageSelectlistPage } from './page-selectlist.page';
+
+@NgModule({
+  imports: [
+    CommonModule,
+    FormsModule,
+    IonicModule,
+    PageSelectlistPageRoutingModule
+  ],
+  declarations: [PageSelectlistPage]
+})
+export class PageSelectlistPageModule {}

+ 43 - 0
myapp/src/app/tab1/page-selectlist/page-selectlist.page.html

@@ -0,0 +1,43 @@
+<ion-header>
+  <ion-toolbar color="success">
+    <ion-buttons slot="start">
+      <ion-back-button defaultHref="/" text="" color="light"></ion-back-button>
+    </ion-buttons>
+    <ion-title color="light">搜索结果</ion-title>
+  </ion-toolbar>
+</ion-header>
+
+<ion-content class="ion-padding">
+  <div *ngIf="searchResults.length === 0" class="empty-state">
+    <ion-icon name="search-outline" class="empty-icon"></ion-icon>
+    <ion-text color="medium">没有找到相关食谱</ion-text>
+  </div>
+
+  <ion-list lines="none">
+    <ion-item *ngFor="let item of searchResults" class="compact-item" detail (click)="goToDetail(item.id)">
+      <ion-thumbnail slot="start" class="recipe-thumbnail">
+        <img [src]="item.get('imageUrl') || 'assets/images/default-food.jpg'" alt="{{item.get('title')}}">
+      </ion-thumbnail>
+      
+      <ion-label class="ion-text-wrap">
+        <h3>{{item.get('title') || '未知标题'}}</h3>
+        <p class="description">{{item.get('description') || '暂无描述'}}</p>
+        
+        <div class="meta-info">
+          <span class="rating">
+            <ion-icon name="star" color="warning"></ion-icon>
+            {{item.get('rating') || '0'}}
+          </span>
+          <span class="time">
+            <ion-icon name="time-outline"></ion-icon>
+            {{item.get('cookingTime') || '?'}}分钟
+          </span>
+          <span class="difficulty" *ngIf="item.get('difficulty')">
+            <ion-icon name="speedometer-outline"></ion-icon>
+            {{item.get('difficulty')}}
+          </span>
+        </div>
+      </ion-label>
+    </ion-item>
+  </ion-list>
+</ion-content>

+ 121 - 0
myapp/src/app/tab1/page-selectlist/page-selectlist.page.scss

@@ -0,0 +1,121 @@
+.empty-state {
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+    justify-content: center;
+    height: 50vh;
+    text-align: center;
+  
+    .empty-icon {
+      font-size: 64px;
+      margin-bottom: 16px;
+      opacity: 0.5;
+    }
+  }
+  
+  .compact-item {
+    --padding-start: 8px;
+    --inner-padding-end: 8px;
+    margin-bottom: 8px;
+    border-radius: 8px;
+    border: 1px solid var(--ion-color-light-shade);
+    
+    h3 {
+      font-weight: 500;
+      margin-bottom: 4px;
+    }
+    
+    .description {
+      color: var(--ion-color-medium);
+      font-size: 0.875rem;
+      margin-bottom: 6px;
+      display: -webkit-box;
+      -webkit-line-clamp: 2;
+      -webkit-box-orient: vertical;
+      overflow: hidden;
+      text-overflow: ellipsis;
+    }
+    
+    .meta-info {
+      display: flex;
+      align-items: center;
+      font-size: 0.75rem;
+      color: var(--ion-color-medium);
+      
+      ion-icon {
+        font-size: 0.875rem;
+        margin-right: 2px;
+      }
+      
+      .rating {
+        margin-right: 12px;
+        display: flex;
+        align-items: center;
+      }
+      
+      .time {
+        display: flex;
+        align-items: center;
+      }
+    }
+  }.empty-state {
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+    justify-content: center;
+    height: 50vh;
+    text-align: center;
+  
+    .empty-icon {
+      font-size: 64px;
+      margin-bottom: 16px;
+      opacity: 0.5;
+    }
+  }
+  
+  .compact-item {
+    --padding-start: 8px;
+    --inner-padding-end: 8px;
+    margin-bottom: 8px;
+    border-radius: 8px;
+    border: 1px solid var(--ion-color-light-shade);
+    
+    h3 {
+      font-weight: 500;
+      margin-bottom: 4px;
+    }
+    
+    .description {
+      color: var(--ion-color-medium);
+      font-size: 0.875rem;
+      margin-bottom: 6px;
+      display: -webkit-box;
+      -webkit-line-clamp: 2;
+      -webkit-box-orient: vertical;
+      overflow: hidden;
+      text-overflow: ellipsis;
+    }
+    
+    .meta-info {
+      display: flex;
+      align-items: center;
+      font-size: 0.75rem;
+      color: var(--ion-color-medium);
+      
+      ion-icon {
+        font-size: 0.875rem;
+        margin-right: 2px;
+      }
+      
+      .rating {
+        margin-right: 12px;
+        display: flex;
+        align-items: center;
+      }
+      
+      .time {
+        display: flex;
+        align-items: center;
+      }
+    }
+  }

+ 17 - 0
myapp/src/app/tab1/page-selectlist/page-selectlist.page.spec.ts

@@ -0,0 +1,17 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { PageSelectlistPage } from './page-selectlist.page';
+
+describe('PageSelectlistPage', () => {
+  let component: PageSelectlistPage;
+  let fixture: ComponentFixture<PageSelectlistPage>;
+
+  beforeEach(() => {
+    fixture = TestBed.createComponent(PageSelectlistPage);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});

+ 31 - 0
myapp/src/app/tab1/page-selectlist/page-selectlist.page.ts

@@ -0,0 +1,31 @@
+import { Component } from '@angular/core';
+import { Router } from '@angular/router';
+import { NavController } from '@ionic/angular';
+import { CloudObject } from 'src/lib/ncloud';
+
+@Component({
+  selector: 'app-page-selectlist',
+  templateUrl: './page-selectlist.page.html',
+  styleUrls: ['./page-selectlist.page.scss'],
+})
+export class PageSelectlistPage {
+  searchQuery : string = '';
+  searchResults: CloudObject[] = [];
+  constructor(private navCtrl: NavController,private router:Router) {
+    const navigation = this.router.getCurrentNavigation();
+    if (navigation?.extras?.state) {
+      this.searchResults = navigation.extras.state['searchResults'];
+      console.log('Received search results:', this.searchResults);
+    }
+   
+  }
+
+  goToDetail(recipeId : any) {
+    this.navCtrl.navigateForward(`/tabs/tab1/page-selectlist/page-selectlist-detail/${recipeId}`);
+    console.log('Navigating to page-collections-detail');
+  }
+
+  // goBack() {
+  //   this.navCtrl.navigateBack(['/tabs/tab1']);
+  // }
+}

+ 32 - 28
myapp/src/app/tab1/tab1-routing.module.ts

@@ -1,30 +1,34 @@
-import { NgModule } from '@angular/core';
-import { RouterModule, Routes } from '@angular/router';
-import { Tab1Page } from './tab1.page';
-
-const routes: Routes = [
-  {
-    path: '',
-    component: Tab1Page,
-  },
-  // {
-  //   path: 'page-aichat',
-  //   //loadChildren: () => import('./page-aichat/page-aichat.module').then( m => m.PageAichatPageModule)
-  // },
-  {
-    path: 'page-type',
-    loadChildren: () => import('./page-type/page-type.module').then( m => m.PageTypePageModule)
-  },
-  {
-    path: 'page-detail/:recipeId',
-    loadChildren: () => import('./page-detail/page-detail.module').then( m => m.PageDetailPageModule)
+import { NgModule } from '@angular/core';
+import { RouterModule, Routes } from '@angular/router';
+import { Tab1Page } from './tab1.page';
+
+const routes: Routes = [
+  {
+    path: '',
+    component: Tab1Page,
+  },
+  // {
+  //   path: 'page-aichat',
+  //   //loadChildren: () => import('./page-aichat/page-aichat.module').then( m => m.PageAichatPageModule)
+  // },
+  {
+    path: 'page-type',
+    loadChildren: () => import('./page-type/page-type.module').then( m => m.PageTypePageModule)
+  },
+  {
+    path: 'page-detail/:recipeId',
+    loadChildren: () => import('./page-detail/page-detail.module').then( m => m.PageDetailPageModule)
+  },
  {
+    path: 'page-selectlist',
+    loadChildren: () => import('./page-selectlist/page-selectlist.module').then( m => m.PageSelectlistPageModule)
   },
 
-
-];
-
-@NgModule({
-  imports: [RouterModule.forChild(routes)],
-  exports: [RouterModule]
-})
-export class Tab1PageRoutingModule {}
+
+
+];
+
+@NgModule({
+  imports: [RouterModule.forChild(routes)],
+  exports: [RouterModule]
+})
+export class Tab1PageRoutingModule {}

+ 1 - 1
myapp/src/app/tab1/tab1.page.html

@@ -26,7 +26,7 @@
           slot="end" 
           fill="clear" 
           class="search-button" 
-          (click)="performSearch()"
+          (click)="selectRecipe()"
           aria-label="搜索"
         >
           <ion-icon slot="icon-only" name="search"></ion-icon>

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

@@ -41,7 +41,7 @@
   }
   
   .search-btn {
-    --background: #ff6b6b;
+    --background: #2dd55b;;
     --color: white;
   }
   
@@ -65,7 +65,7 @@
   
   .category-icon {
     font-size: 2rem;
-    color: #ff6b6b;
+    color: #2dd55b;;
     margin-bottom: 0.5rem;
   }
   
@@ -118,7 +118,7 @@
   .user-info-card {
     margin: 1rem;
     border-radius: 0.5rem;
-    background-color: #ff6b6b;
+    background-color: #2dd55b;;
     color: white;
   }
   
@@ -134,7 +134,7 @@
     width: 3rem;
     height: 3rem;
     background-color: white;
-    color: #ff6b6b;
+    color: #2dd55b;;
     display: flex;
     align-items: center;
     justify-content: center;
@@ -191,7 +191,7 @@ ion-content {
 }
 
 .search-button {
-  --color: #ff6b6b;
+  --color: #2dd55b;;
 }
 
 /* 分类部分样式 */

+ 26 - 3
myapp/src/app/tab1/tab1.page.ts

@@ -1,5 +1,5 @@
 import { Component, OnInit, Renderer2 } from '@angular/core';
-import { Router } from '@angular/router';
+import { NavigationExtras, Router } from '@angular/router';
 import { NavController } from '@ionic/angular';
 import { CloudObject, CloudQuery } from 'src/lib/ncloud';
 import { IonicModule } from '@ionic/angular'; 
@@ -12,7 +12,6 @@ import { IonicModule } from '@ionic/angular';
 })
 
 export class Tab1Page implements OnInit {
-  searchQuery: string = '';
   categories: any[] = [
     { name: '中式菜系', icon: 'utensils' },
     { name: '西式料理', icon: 'fork-knife' },
@@ -65,7 +64,31 @@ export class Tab1Page implements OnInit {
     console.log("随机选择的组内容:", this.recipeGroup);
 
   }
-
+  searchQuery: string = '';
+  results : Array<CloudObject> = []; // 存储原始每日推荐记录
+  async selectRecipe() {
+    const query = this.searchQuery.trim();
+    if (!query) return;
+  
+    try {
+      const cloudQuery = new CloudQuery("Recipe");
+      cloudQuery.contains("title", query);
+      const results = await cloudQuery.find();
+    
+      this.navCtrl.navigateForward(
+        ["tabs", "tab1", "page-selectlist"], 
+        {
+          state: {
+            searchResults: results
+          }
+        }
+      );
+      
+      console.log("搜索结果:", results);
+    } catch (error) {
+      console.error("搜索失败:", error);
+    }
+  }
 
   login() {
     this.router.navigate(['/login']);

+ 9 - 9
myapp/src/app/tab2/tab2.page.html

@@ -1,7 +1,7 @@
 <ion-header [translucent]="true">
-  <ion-toolbar color="primary">
-    <ion-title>
-      <ion-icon name="restaurant" class="ion-align-self-center"></ion-icon>
+  <ion-toolbar color="success">
+    <ion-title color="light">
+      <ion-icon name="restaurant" class="ion-align-self-center" ></ion-icon>
       营养搭配
     </ion-title>
   </ion-toolbar>
@@ -45,12 +45,12 @@
       
       <div class="credentials">
         <ion-item lines="none" class="credential-item">
-          <ion-icon slot="start" name="library" color="primary"></ion-icon>
-          <ion-label>《本草厨房》作者</ion-label>
+          <ion-icon slot="start" name="library" color="success"></ion-icon>
+          <ion-label >《本草厨房》作者</ion-label>
         </ion-item>
         <ion-item lines="none" class="credential-item">
-          <ion-icon slot="start" name="tv" color="primary"></ion-icon>
-          <ion-label>央视《健康中国》嘉宾</ion-label>
+          <ion-icon slot="start" name="tv" color="success"></ion-icon>
+          <ion-label >央视《健康中国》嘉宾</ion-label>
         </ion-item>
       </div>
     </ion-card-content>
@@ -85,8 +85,8 @@
       <ion-grid>
         <ion-row>
           <ion-col size="12">
-            <ion-button (click)="openConsult()" expand="block" color="primary" class="consult-button">
-              <ion-icon name="chatbubbles" slot="start"></ion-icon>
+            <ion-button (click)="openConsult()" expand="block" color="success" class="consult-button" 1>
+              <ion-icon name="chatbubbles" slot="start" color = "light"></ion-icon>
               立即咨询
             </ion-button>
           </ion-col>

+ 2 - 2
myapp/src/app/tab3/page-collections/page-collections.page.html

@@ -1,9 +1,9 @@
 <ion-header [translucent]="true">
-  <ion-toolbar color="primary">
+  <ion-toolbar color="success">
     <ion-buttons slot="start">
       <ion-back-button defaultHref="/" text="返回"></ion-back-button>
     </ion-buttons>
-    <ion-title>我的收藏</ion-title>
+    <ion-title color = "light">我的收藏</ion-title>
     <ion-buttons slot="end">
       <ion-button (click)="loadRecipeFavoriteList()">
         <ion-icon slot="icon-only" name="refresh" class="refresh-icon"></ion-icon>

+ 2 - 2
myapp/src/app/tab3/page-records/page-records.page.html

@@ -1,9 +1,9 @@
 <ion-header [translucent]="true">
-  <ion-toolbar color="primary">
+  <ion-toolbar color="success">
     <ion-buttons slot="start">
       <ion-back-button defaultHref="/" text="返回"></ion-back-button>
     </ion-buttons>
-    <ion-title>浏览历史</ion-title>
+    <ion-title color = "light">浏览历史</ion-title>
     <ion-buttons slot="end">
       <ion-button ><!-- (click)="clearHistory()" -->
         <ion-icon slot="icon-only" name="trash-outline"></ion-icon>

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

@@ -1,6 +1,6 @@
 <ion-header [translucent]="true">
   <ion-toolbar color="success">
-    <ion-title>我的空间</ion-title>
+    <ion-title color ="light">我的空间</ion-title>
     <ion-buttons slot="end">
       <ion-button (click)="handleAction('settings')">
         <ion-icon slot="icon-only" name="settings"></ion-icon>

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

@@ -137,6 +137,12 @@ export class CloudQuery {
         this.queryParams["where"][key] = value;
     }
 
+    contains(key: string, value: string) {
+        if (!this.queryParams["where"]) this.queryParams["where"] = {};
+        this.queryParams["where"][key] = { "$regex": value, "$options": "i" }; // 相当于 LIKE '%value%'
+        return this;
+    }
+
     async get(id: string) {
         const url = serverURL + `/classes/${this.className}/${id}?`;