Sfoglia il codice sorgente

搜索界面上传

0235697 16 ore fa
parent
commit
c814a85bdc

+ 49 - 0
picture-web/package-lock.json

@@ -16,6 +16,9 @@
         "@angular/material": "^20.0.4",
         "@angular/platform-browser": "^20.0.0",
         "@angular/router": "^20.0.0",
+        "@fortawesome/angular-fontawesome": "^2.0.1",
+        "@fortawesome/fontawesome-svg-core": "^6.7.2",
+        "@fortawesome/free-solid-svg-icons": "^6.7.2",
         "@types/swiper": "^6.0.0",
         "rxjs": "~7.8.0",
         "sweetalert2": "^11.22.2",
@@ -1249,6 +1252,52 @@
         "node": ">=18"
       }
     },
+    "node_modules/@fortawesome/angular-fontawesome": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/@fortawesome/angular-fontawesome/-/angular-fontawesome-2.0.1.tgz",
+      "integrity": "sha512-IdklZkuw+WS2GQWhFnr1EX/tOALnrKaj4YGnUmPaUg2Uf+Amj8Xi+M/qDrr915YJ5MaDxd9tZ1kqOHRcvQqq2A==",
+      "license": "MIT",
+      "dependencies": {
+        "@fortawesome/fontawesome-svg-core": "^6.7.2",
+        "tslib": "^2.8.1"
+      },
+      "peerDependencies": {
+        "@angular/core": "^20.0.0"
+      }
+    },
+    "node_modules/@fortawesome/fontawesome-common-types": {
+      "version": "6.7.2",
+      "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-6.7.2.tgz",
+      "integrity": "sha512-Zs+YeHUC5fkt7Mg1l6XTniei3k4bwG/yo3iFUtZWd/pMx9g3fdvkSK9E0FOC+++phXOka78uJcYb8JaFkW52Xg==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/@fortawesome/fontawesome-svg-core": {
+      "version": "6.7.2",
+      "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-6.7.2.tgz",
+      "integrity": "sha512-yxtOBWDrdi5DD5o1pmVdq3WMCvnobT0LU6R8RyyVXPvFRd2o79/0NCuQoCjNTeZz9EzA9xS3JxNWfv54RIHFEA==",
+      "license": "MIT",
+      "dependencies": {
+        "@fortawesome/fontawesome-common-types": "6.7.2"
+      },
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/@fortawesome/free-solid-svg-icons": {
+      "version": "6.7.2",
+      "resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-6.7.2.tgz",
+      "integrity": "sha512-GsBrnOzU8uj0LECDfD5zomZJIjrPhIlWU82AHwa2s40FKH+kcxQaBvBo3Z4TxyZHIyX8XTDxsyA33/Vx9eFuQA==",
+      "license": "(CC-BY-4.0 AND MIT)",
+      "dependencies": {
+        "@fortawesome/fontawesome-common-types": "6.7.2"
+      },
+      "engines": {
+        "node": ">=6"
+      }
+    },
     "node_modules/@inquirer/checkbox": {
       "version": "4.1.8",
       "resolved": "https://registry.npmmirror.com/@inquirer/checkbox/-/checkbox-4.1.8.tgz",

+ 3 - 0
picture-web/package.json

@@ -28,6 +28,9 @@
     "@angular/material": "^20.0.4",
     "@angular/platform-browser": "^20.0.0",
     "@angular/router": "^20.0.0",
+    "@fortawesome/angular-fontawesome": "^2.0.1",
+    "@fortawesome/fontawesome-svg-core": "^6.7.2",
+    "@fortawesome/free-solid-svg-icons": "^6.7.2",
     "@types/swiper": "^6.0.0",
     "rxjs": "~7.8.0",
     "sweetalert2": "^11.22.2",

+ 118 - 1
picture-web/src/modules/first-home/image-search/image-search.html

@@ -1 +1,118 @@
-<p>image-search works!</p>
+<!-- image-search.html -->
+<div class="container">
+  <!-- 顶部搜索栏 -->
+  <header class="search-header">
+    <div class="header-top">
+      <div class="back-btn" (click)="backAction()">
+        <fa-icon [icon]="faArrowLeft"></fa-icon>
+      </div>
+      <div class="app-name">播菜汪</div>
+      <div style="width: 36px;"></div> <!-- 占位保持对称 -->
+    </div>
+    
+    <div class="search-bar">
+      <fa-icon [icon]="faSearch"></fa-icon>
+      <input 
+        type="text" 
+        [(ngModel)]="searchInput" 
+        placeholder="搜索美食图片素材..." 
+        (keyup.enter)="onSearch()"
+      >
+    </div>
+  </header>
+  
+  <!-- 主内容区 -->
+  <main class="main-content">
+    <!-- 历史搜索 -->
+    <div class="section history-section" *ngIf="searchHistory.length > 0">
+      <div class="section-title">
+        <div><fa-icon [icon]="faHistory"></fa-icon> 历史搜索</div>
+        <button class="clear-btn" (click)="clearHistory()">清空</button>
+      </div>
+      <div class="history-list">
+        <div 
+          class="history-item" 
+          *ngFor="let item of searchHistory; let i = index"
+          (click)="performSearch(item)"
+        >
+          <span>{{ item }}</span>
+          <span class="delete-btn" (click)="deleteHistoryItem(i); $event.stopPropagation()">
+            <fa-icon [icon]="faTimes"></fa-icon>
+          </span>
+        </div>
+      </div>
+    </div>
+    
+    <!-- 搜索发现 -->
+    <div class="section">
+      <div class="section-title">
+        <div><fa-icon [icon]="faCompass"></fa-icon> 搜索发现</div>
+      </div>
+      <div class="discovery-grid">
+        <div 
+          class="grid-item" 
+          *ngFor="let item of discoveryItems"
+          (click)="onDiscoveryClick(item)"
+        >
+          {{ item }}
+        </div>
+      </div>
+    </div>
+    
+    <!-- 大家都在搜 -->
+    <div class="section">
+      <div class="section-title">
+        <div><fa-icon [icon]="faFire"></fa-icon> 大家都在搜</div>
+      </div>
+      <div class="hot-list">
+        <div 
+          class="hot-item" 
+          *ngFor="let item of popularSearches; let i = index"
+          (click)="onPopularSearchClick(item)"
+        >
+          <div class="hot-index" [class.top3]="i < 3">{{ i + 1 }}</div>
+          <div class="hot-keyword">
+            {{ item.keyword }}
+            <span class="hot-tag" *ngIf="item.tag">{{ item.tag }}</span>
+          </div>
+        </div>
+      </div>
+    </div>
+    
+    <!-- 美食热搜 -->
+    <div class="section">
+      <div class="section-title">
+        <div><fa-icon [icon]="faUtensils"></fa-icon> 美食热搜</div>
+      </div>
+      <div class="hot-list">
+        <div 
+          class="hot-item" 
+          *ngFor="let item of foodTrends; let i = index"
+          (click)="onFoodTrendClick(item)"
+        >
+          <div class="hot-index" [class.top3]="i < 3">{{ i + 1 }}</div>
+          <div class="hot-keyword">
+            {{ item.keyword }}
+            <span class="hot-tag" *ngIf="item.tag">{{ item.tag }}</span>
+          </div>
+        </div>
+      </div>
+    </div>
+    
+    <!-- 分类标签 -->
+    <div class="section">
+      <div class="section-title">
+        <div><fa-icon [icon]="faTags"></fa-icon> 热门分类</div>
+      </div>
+      <div class="category-tags">
+        <div 
+          class="tag" 
+          *ngFor="let category of categories"
+          (click)="onCategoryClick(category)"
+        >
+          {{ category }}
+        </div>
+      </div>
+    </div>
+  </main>
+</div>

+ 323 - 0
picture-web/src/modules/first-home/image-search/image-search.scss

@@ -0,0 +1,323 @@
+// image-search.scss
+:host {
+  display: block;
+  min-height: 100vh;
+  background: linear-gradient(135deg, #fff9f0, #fff0f5);
+  color: #333;
+  line-height: 1.6;
+  padding-bottom: 20px;
+}
+
+.container {
+  max-width: 100%;
+  padding: 0 15px;
+  margin: 0 auto;
+}
+
+/* 顶部搜索栏 */
+.search-header {
+  background: linear-gradient(135deg, #ff6b6b, #ff8e53);
+  padding: 15px 15px 20px;
+  position: sticky;
+  top: 0;
+  z-index: 100;
+  box-shadow: 0 2px 15px rgba(0,0,0,0.15);
+  border-radius: 0 0 20px 20px;
+}
+
+.header-top {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  margin-bottom: 15px;
+}
+
+.back-btn {
+  background: rgba(255,255,255,0.3);
+  width: 36px;
+  height: 36px;
+  border-radius: 50%;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  color: white;
+  font-size: 18px;
+  cursor: pointer;
+  transition: all 0.3s;
+
+  &:hover {
+    background: rgba(255,255,255,0.5);
+    transform: scale(1.05);
+  }
+}
+
+.app-name {
+  color: white;
+  font-size: 22px;
+  font-weight: bold;
+  letter-spacing: 1px;
+  text-shadow: 0 2px 4px rgba(0,0,0,0.2);
+}
+
+.search-bar {
+  display: flex;
+  background: white;
+  border-radius: 30px;
+  padding: 10px 20px;
+  box-shadow: 0 4px 15px rgba(0,0,0,0.15);
+  align-items: center;
+
+  fa-icon {
+    color: #ff6b6b;
+    margin-right: 12px;
+    font-size: 18px;
+  }
+
+  input {
+    flex: 1;
+    border: none;
+    outline: none;
+    font-size: 16px;
+    padding: 5px 0;
+    background: transparent;
+
+    &::placeholder {
+      color: #bbb;
+    }
+  }
+}
+
+/* 主内容区 */
+.main-content {
+  padding: 20px 15px;
+  background: white;
+  border-radius: 25px;
+  margin-top: 15px;
+  box-shadow: 0 5px 20px rgba(0,0,0,0.08);
+  position: relative;
+
+  &::before {
+    content: "";
+    position: absolute;
+    top: -15px;
+    left: 50%;
+    transform: translateX(-50%);
+    width: 50px;
+    height: 6px;
+    background: #ddd;
+    border-radius: 3px;
+  }
+}
+
+.section-title {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  margin: 25px 0 18px;
+  font-size: 18px;
+  font-weight: bold;
+  color: #333;
+  padding-bottom: 8px;
+  border-bottom: 2px solid #fff0f0;
+
+  fa-icon {
+    color: #ff6b6b;
+    margin-right: 10px;
+  }
+}
+
+.clear-btn {
+  background: none;
+  border: none;
+  color: #999;
+  font-size: 14px;
+  cursor: pointer;
+  transition: all 0.3s;
+  padding: 5px 10px;
+  border-radius: 15px;
+
+  &:hover {
+    background: #fff0f0;
+    color: #ff6b6b;
+  }
+}
+
+/* 历史搜索 */
+.history-list {
+  display: flex;
+  flex-wrap: wrap;
+  gap: 15px;
+  margin-bottom: 10px;
+}
+
+.history-item {
+  background: #f9f9f9;
+  border-radius: 25px;
+  padding: 10px 20px;
+  font-size: 15px;
+  display: flex;
+  align-items: center;
+  border: 1px solid #eee;
+  cursor: pointer;
+  transition: all 0.3s;
+  box-shadow: 0 2px 8px rgba(0,0,0,0.05);
+
+  &:hover {
+    background: #fff5f5;
+    border-color: #ffcccc;
+    transform: translateY(-2px);
+    box-shadow: 0 4px 12px rgba(255,107,107,0.15);
+  }
+
+  .delete-btn {
+    margin-left: 10px;
+    color: #bbb;
+    font-size: 14px;
+    transition: all 0.3s;
+
+    &:hover {
+      color: #ff6b6b;
+    }
+  }
+}
+
+/* 搜索发现 */
+.discovery-grid {
+  display: grid;
+  grid-template-columns: repeat(4, 1fr);
+  gap: 15px;
+  margin-bottom: 25px;
+}
+
+.grid-item {
+  background: linear-gradient(135deg, #f8f9ff, #fff8f8);
+  border-radius: 15px;
+  padding: 15px 8px;
+  text-align: center;
+  font-size: 14px;
+  border: 1px solid #f0f0f0;
+  cursor: pointer;
+  transition: all 0.3s;
+  box-shadow: 0 3px 8px rgba(0,0,0,0.03);
+
+  &:hover {
+    background: linear-gradient(135deg, #f0f3ff, #ffecec);
+    border-color: #ffcccc;
+    transform: translateY(-3px);
+    box-shadow: 0 5px 15px rgba(255,107,107,0.15);
+  }
+}
+
+/* 热搜列表 */
+.hot-list {
+  background: linear-gradient(135deg, #f9f9f9, #fcf5f5);
+  border-radius: 20px;
+  overflow: hidden;
+  margin-bottom: 25px;
+  box-shadow: 0 3px 10px rgba(0,0,0,0.03);
+}
+
+.hot-item {
+  display: flex;
+  padding: 15px 20px;
+  border-bottom: 1px solid #f0f0f0;
+  cursor: pointer;
+  transition: all 0.3s;
+  align-items: center;
+
+  &:last-child {
+    border-bottom: none;
+  }
+
+  &:hover {
+    background: #fff5f5;
+  }
+}
+
+.hot-index {
+  width: 26px;
+  height: 26px;
+  background: #f0f0f0;
+  border-radius: 8px;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  margin-right: 15px;
+  font-size: 14px;
+  color: #666;
+  font-weight: bold;
+
+  &.top3 {
+    background: linear-gradient(135deg, #ffd6d6, #ff8e8e);
+    color: white;
+  }
+}
+
+.hot-keyword {
+  flex: 1;
+  font-size: 16px;
+}
+
+.hot-tag {
+  background: #fff0f0;
+  color: #ff6b6b;
+  border-radius: 15px;
+  padding: 4px 10px;
+  font-size: 12px;
+  margin-left: 10px;
+}
+
+/* 分类标签 */
+.category-tags {
+  display: flex;
+  flex-wrap: wrap;
+  gap: 12px;
+  margin-top: 25px;
+}
+
+.tag {
+  background: linear-gradient(135deg, #f0f7ff, #e6f7ff);
+  color: #4a90e2;
+  border-radius: 20px;
+  padding: 8px 20px;
+  font-size: 15px;
+  cursor: pointer;
+  transition: all 0.3s;
+  border: 1px solid #e0f0ff;
+  box-shadow: 0 2px 6px rgba(0,0,0,0.03);
+
+  &:hover {
+    background: linear-gradient(135deg, #4a90e2, #6ba8e6);
+    color: white;
+    transform: translateY(-2px);
+    box-shadow: 0 5px 12px rgba(74,144,226,0.2);
+  }
+}
+
+/* 响应式调整 */
+@media (max-width: 480px) {
+  .discovery-grid {
+    grid-template-columns: repeat(3, 1fr);
+  }
+}
+
+@media (max-width: 360px) {
+  .discovery-grid {
+    grid-template-columns: repeat(2, 1fr);
+  }
+  
+  .history-item {
+    padding: 8px 15px;
+    font-size: 14px;
+  }
+}
+
+/* 动画效果 */
+@keyframes fadeIn {
+  from { opacity: 0; transform: translateY(10px); }
+  to { opacity: 1; transform: translateY(0); }
+}
+
+.section {
+  animation: fadeIn 0.5s ease-out;
+}

+ 127 - 5
picture-web/src/modules/first-home/image-search/image-search.ts

@@ -1,11 +1,133 @@
-import { Component } from '@angular/core';
+// image-search.ts
+import { Component, OnInit } from '@angular/core';
+import { CommonModule } from '@angular/common';
+import { FormsModule } from '@angular/forms';
+import { FontAwesomeModule } from '@fortawesome/angular-fontawesome';
+import { 
+  faArrowLeft, 
+  faSearch, 
+  faHistory, 
+  faCompass, 
+  faFire, 
+  faUtensils, 
+  faTags, 
+  faTimes 
+} from '@fortawesome/free-solid-svg-icons';
 
 @Component({
   selector: 'app-image-search',
-  imports: [],
+  standalone: true,
+  imports: [CommonModule, FormsModule, FontAwesomeModule],
   templateUrl: './image-search.html',
-  styleUrl: './image-search.scss'
+  styleUrls: ['./image-search.scss']
 })
-export class ImageSearch {
+export class ImageSearchComponent implements OnInit {
+  // FontAwesome 图标
+  faArrowLeft = faArrowLeft;
+  faSearch = faSearch;
+  faHistory = faHistory;
+  faCompass = faCompass;
+  faFire = faFire;
+  faUtensils = faUtensils;
+  faTags = faTags;
+  faTimes = faTimes;
 
-}
+  searchInput = '';
+  searchHistory: string[] = [];
+
+  // 搜索发现项
+  discoveryItems = [
+    '美食摄影', '中餐高清', '食材特写', '饮品素材',
+    '节日美食', '菜单设计', '火锅图片', '菜品展示'
+  ];
+
+  // 大家都在搜
+  popularSearches = [
+    { keyword: '高级料理图片素材', tag: '热' },
+    { keyword: '夏日饮品视觉素材', tag: '新' },
+    { keyword: '美食摄影技巧', tag: '' },
+    { keyword: '中餐厅投影素材', tag: '' },
+    { keyword: '食物特写高清', tag: '' }
+  ];
+
+  // 美食热搜
+  foodTrends = [
+    { keyword: '火锅美食素材包', tag: '爆' },
+    { keyword: '甜品视觉图集', tag: '' },
+    { keyword: '海鲜大餐高清', tag: '' },
+    { keyword: '中式点心素材', tag: '' },
+    { keyword: '西餐摆盘艺术', tag: '' }
+  ];
+
+  // 热门分类
+  categories = ['中餐', '西餐', '日料', '甜点', '饮品', '烧烤', '海鲜', '素食'];
+
+  ngOnInit() {
+    this.loadSearchHistory();
+  }
+
+  loadSearchHistory() {
+    const history = localStorage.getItem('foodSearchHistory');
+    this.searchHistory = history ? JSON.parse(history) : [];
+  }
+
+  backAction() {
+    // 实际应用中这里应该是 router.navigate 或其他导航逻辑
+    alert('返回上一页面');
+  }
+
+  clearHistory() {
+    if (this.searchHistory.length === 0) return;
+    
+    if (confirm('确定要清空所有搜索历史吗?')) {
+      this.searchHistory = [];
+      localStorage.removeItem('foodSearchHistory');
+    }
+  }
+
+  deleteHistoryItem(index: number) {
+    this.searchHistory.splice(index, 1);
+    localStorage.setItem('foodSearchHistory', JSON.stringify(this.searchHistory));
+  }
+
+  performSearch(query: string) {
+    if (!query.trim()) return;
+    
+    // 添加到历史记录
+    if (!this.searchHistory.includes(query)) {
+      this.searchHistory.unshift(query);
+      // 最多保留10条记录
+      if (this.searchHistory.length > 10) {
+        this.searchHistory.pop();
+      }
+      localStorage.setItem('foodSearchHistory', JSON.stringify(this.searchHistory));
+    }
+    
+    // 执行搜索(模拟)
+    alert(`正在搜索: ${query}\n将显示相关美食图片素材`);
+  }
+
+  onSearch() {
+    this.performSearch(this.searchInput.trim());
+  }
+
+  onDiscoveryClick(item: string) {
+    this.searchInput = item;
+    this.performSearch(item);
+  }
+
+  onPopularSearchClick(item: { keyword: string }) {
+    this.searchInput = item.keyword;
+    this.performSearch(item.keyword);
+  }
+
+  onFoodTrendClick(item: { keyword: string }) {
+    this.searchInput = item.keyword;
+    this.performSearch(item.keyword);
+  }
+
+  onCategoryClick(category: string) {
+    this.searchInput = `${category}图片素材`;
+    this.performSearch(`${category}图片素材`);
+  }
+}