fastapi+angular外卖系统
说明:
fastapi+angular外卖系统
1.美食分类(粥,粉,面,炸鸡,炒菜,西餐,奶茶等等)
2.商家列表 (kfc,兰州拉面,湘菜馆,早餐店,重庆小面,潮汕砂锅粥,蜜雪冰城等等)
商家item:
商家店名,评分,月销量,人均价格,起送价格,配送费价格,店铺位置,商家标签,商家分类
3.商家详情页
商家店名,评分,月销量
菜品分类(比如炒饭,拉面,盖饭,单人套餐,双人套餐,米线,酒水饮料)
菜品列表
菜品item:
菜品名,评分,月销量,菜品标签,菜品分类,菜品价格
显示评价列表,包括用户评分和评价内容
商家详情,包括店铺位置,商家联系电话,营业时间,订餐注意事项,店铺政策
4.结算页
填写用户名,用户联系电话,收货地址,
商品详细清单 店铺名,菜品名,购买数量,菜品单价,配送费,打包费,总金额,提交订单功能
5.订单详情页
订单单号,订单状态(已完成,已退款,待接单,待配送),店铺名称,菜品名称,购买数量,菜品单价,配送费,打包费,总金额
配送信息,订单下单时间,配送完成时间,配送地址,骑手名,骑手联系电话,支付方式,备注信息等等
6.评价表
用户对菜品的评价
效果图:

json:
/* Merchant List Endpoint - GET http://localhost:8000/merchants */
{"data": [{"id": 7,"name": "Haidilao Hot Pot","rating": 4.9,"monthly_sales": 4000,"avg_price": 80.0,"min_order_price": 50.0,"delivery_fee": 0.0,"location": "3F Food Court","tags": "Hot Pot,24/7","contact_phone": "13800138444","business_hours": "24/7","notice": "Free delivery","policy": "Service first","categories": "Hot Pot"},// Other merchants follow similar pattern...]
}/* Food Categories Endpoint - GET http://localhost:8000/categories */
{"data": [{"id": 7, "name": "Bubble Tea"},{"id": 10, "name": "Japanese"},{"id": 8, "name": "Hot Pot"},// Other categories...]
}/* Merchant Details - GET http://localhost:8000/merchants/1 */
{"merchant": {"id": 1,"name": "KFC","rating": 4.5,"monthly_sales": 2000,"avg_price": 35.0,"min_order_price": 20.0,"delivery_fee": 5.0,"location": "People's Square, City Center","tags": "Fast Food,24/7","contact_phone": "13800138000","business_hours": "07:00-23:00","notice": "Order during business hours","policy": "Unconditional refund"},"categories": [{"id": 1,"name": "Fried Chicken Meals","dishes": "[{\"id\": 1, \"name\": \"Spicy Chicken Burger Meal\", \"tags\": \"Popular\", \"price\": 35.00, \"sales\": 800, \"rating\": 4.50}]"}],"reviews": [{"rating": 4.8,"content": "The burger was delicious!","review_time": "2024-03-01T13:00:00","dish_name": "Spicy Chicken Burger Meal"}]
}/* Create Order - POST http://localhost:8000/orders */
Request Body:
{"customer_name": "Wang Xiaoming","customer_phone": "13800138000","delivery_address": "No.123 Zhangjiang Road, Pudong, Shanghai","merchant_id": 1,"payment_method": "Alipay","items": [{"dish_id": 1, "quantity": 2, "price": 35.00},{"dish_id": 2, "quantity": 1, "price": 40.00}],"note": "Need invoice, no chili please"
}Response:
{"order_id": 14}/* Order Details - GET http://localhost:8000/orders/1 */
{"order": {"id": 1,"customer_name": "Zhang San","status": "Completed","payment_method": "WeChat Pay","merchant_name": "KFC"},"items": [{"dish_name": "Spicy Chicken Burger Meal", "quantity": 2},{"dish_name": "Orleans Wings Meal", "quantity": 1}]
}/* Dish Reviews - GET http://localhost:8000/dishes/1/reviews */
[{"rating": 4.8,"content": "Perfectly crispy chicken!","review_time": "2024-03-01T13:00:00","quantity": 2}
]
网络请求: C:\Users\wangrusheng\WebstormProjects\untitled4\src\app\services\merchant.service.ts
// merchant.service.ts
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';@Injectable({providedIn: 'root'
})
export class MerchantService {private apiUrl = 'http://localhost:8000';constructor(private http: HttpClient) { }getCategories(): Observable<any> {return this.http.get(`${this.apiUrl}/categories`);}getMerchants(categoryId?: number, page = 1, sortBy = 'rating'): Observable<any> {const params: any = {page: page.toString(),sort_by: sortBy};if (categoryId) params.category_id = categoryId.toString();return this.http.get(`${this.apiUrl}/merchants`, { params });}getMerchantDetail(id: number): Observable<any> {console.log("getMerchantDetail",id)return this.http.get(`${this.apiUrl}/merchants/${id}`);}createOrder(orderData: any): Observable<any> {return this.http.post(`${this.apiUrl}/orders`, orderData);}getOrderDetail(id: number): Observable<any> {return this.http.get(`${this.apiUrl}/orders/${id}`);}submitReview(reviewData: any): Observable<any> {return this.http.post(`${this.apiUrl}/reviews`, reviewData);}
}
step1:sql
-- 1. 美食分类表
CREATE TABLE category (id INT PRIMARY KEY AUTO_INCREMENT,name VARCHAR(50) NOT NULL UNIQUE
);select *from category-- 2. 商家表
CREATE TABLE merchant (id INT PRIMARY KEY AUTO_INCREMENT,name VARCHAR(100) NOT NULL,rating DECIMAL(3,2) DEFAULT 0.00,monthly_sales INT DEFAULT 0,avg_price DECIMAL(8,2) DEFAULT 0.00,min_order_price DECIMAL(8,2) DEFAULT 0.00,delivery_fee DECIMAL(8,2) DEFAULT 0.00,location VARCHAR(255),tags VARCHAR(255),contact_phone VARCHAR(20),business_hours VARCHAR(100),notice TEXT,policy TEXT
);-- 商家分类关联表
CREATE TABLE merchant_category (merchant_id INT,category_id INT,PRIMARY KEY (merchant_id, category_id),FOREIGN KEY (merchant_id) REFERENCES merchant(id),FOREIGN KEY (category_id) REFERENCES category(id)
);-- 3. 菜品分类表
CREATE TABLE dish_category (id INT PRIMARY KEY AUTO_INCREMENT,merchant_id INT NOT NULL,name VARCHAR(50) NOT NULL,FOREIGN KEY (merchant_id) REFERENCES merchant(id)
);-- 4. 菜品表
CREATE TABLE dish (id INT PRIMARY KEY AUTO_INCREMENT,merchant_id INT NOT NULL,category_id INT NOT NULL,name VARCHAR(100) NOT NULL,rating DECIMAL(3,2) DEFAULT 0.00,monthly_sales INT DEFAULT 0,tags VARCHAR(255),price DECIMAL(8,2) NOT NULL,FOREIGN KEY (merchant_id) REFERENCES merchant(id),FOREIGN KEY (category_id) REFERENCES dish_category(id)
);-- 5. 订单表
CREATE TABLE `order` (id INT PRIMARY KEY AUTO_INCREMENT,customer_name VARCHAR(100) NOT NULL,customer_phone VARCHAR(20) NOT NULL,delivery_address VARCHAR(255) NOT NULL,merchant_id INT NOT NULL,total_amount DECIMAL(10,2) NOT NULL,delivery_fee DECIMAL(8,2) DEFAULT 0.00,packing_fee DECIMAL(8,2) DEFAULT 0.00,status ENUM('已完成','已退款','待接单','待配送') DEFAULT '待接单',order_time DATETIME NOT NULL,complete_time DATETIME,rider_name VARCHAR(100),rider_phone VARCHAR(20),payment_method VARCHAR(50),note TEXT,FOREIGN KEY (merchant_id) REFERENCES merchant(id)
);select *from db_school.order;-- 6. 订单明细表
CREATE TABLE order_item (id INT PRIMARY KEY AUTO_INCREMENT,order_id INT NOT NULL,dish_id INT NOT NULL,quantity INT NOT NULL,price DECIMAL(8,2) NOT NULL,FOREIGN KEY (order_id) REFERENCES `order`(id),FOREIGN KEY (dish_id) REFERENCES dish(id)
);-- 7. 评价表
CREATE TABLE review (id INT PRIMARY KEY AUTO_INCREMENT,order_item_id INT NOT NULL UNIQUE,rating DECIMAL(3,2) NOT NULL,content TEXT,review_time DATETIME NOT NULL,FOREIGN KEY (order_item_id) REFERENCES order_item(id)
);-- Insert food categories
INSERT INTO category (name) VALUES
('Porridge'),('Rice Noodles'),('Noodles'),('Fried Chicken'),('Stir-Fry'),('Western Food'),('Bubble Tea');INSERT INTO category (name) VALUES
('Hot Pot'), ('BBQ'), ('Japanese Cuisine');-- Insert merchant data
INSERT INTO merchant (name, rating, monthly_sales, avg_price, min_order_price, delivery_fee, location, tags, contact_phone, business_hours, notice, policy) VALUES
('KFC', 4.5, 2000, 35.00, 20.00, 5.00, 'People''s Square, City Center', 'Fast Food,24/7 Service', '13800138000', '07:00-23:00', 'Please order during business hours', 'Unconditional refund'),
('Lanzhou Beef Noodles', 4.7, 1500, 20.00, 15.00, 3.00, '100 Zhongshan Road', 'Noodles,Halal', '13900139000', '08:00-22:00', 'Advance reservation recommended', 'Free packaging'),
('Mixue Ice Cream & Tea', 4.6, 3000, 10.00, 0.00, 0.00, '50 Jiefang Road', 'Bubble Tea,Desserts', '13700137000', '09:00-22:00', 'Minimum order ¥10', 'Made fresh');-- Additional merchants...
INSERT INTO merchant (name, rating, monthly_sales, avg_price, min_order_price, delivery_fee, location, tags, contact_phone, business_hours, notice, policy) VALUES
('McDonald''s', 4.6, 2500, 30.00, 20.00, 4.00, '5 Commercial Street', 'Fast Food,Burgers', '13800138111', '07:00-23:30', '24/7 delivery', 'Coupons accepted'),
('Pizza Hut', 4.4, 1800, 50.00, 30.00, 6.00, 'City Center Plaza', 'Pizza,Western Food', '13800138222', '10:00-22:00', 'Happy Hour deals', 'Utensils provided'),
('Starbucks', 4.7, 3000, 35.00, 0.00, 5.00, '1F Shopping Mall', 'Coffee,Desserts', '13800138333', '08:00-21:00', 'Takeaway discounts', 'Eco-cup discount'),
('Haidilao Hot Pot', 4.9, 4000, 80.00, 50.00, 0.00, '3F Food Court', 'Hot Pot,24/7', '13800138444', '24/7', 'Free delivery', 'Service first'),
('Shaxian Snacks', 4.3, 1200, 15.00, 10.00, 2.00, 'Community Street', 'Snacks,Economy', '13800138555', '06:30-22:00', 'Large portions', 'Free rice refill'),
('Zhen Gongfu', 4.5, 1500, 25.00, 15.00, 3.00, 'Near Train Station', 'Fast Food,Steamed Dishes', '13800138666', '09:00-21:00', 'Quick service', 'Self-pickup available'),
('Burger King', 4.6, 2000, 40.00, 25.00, 5.00, 'Block B Commercial Area', 'Burgers,Fries', '13800138777', '08:00-24:00', 'King Meal deals', 'Reward points');-- Special noodle merchants
INSERT INTO merchant (name, rating, monthly_sales, avg_price, min_order_price, delivery_fee, location, tags, contact_phone, business_hours, notice, policy)
VALUES ('Liuzhou Luosifen',4.8,1800,18.00,15.00,2.50,'No.8 Food Street','Luosifen,Authentic','13811112222','09:00-22:00','Customizable spiciness','Free extra bamboo shoots'
);-- Link categories (assuming Rice Noodles category_id=2)
INSERT INTO merchant_category (merchant_id, category_id)
VALUES((SELECT id FROM merchant WHERE name='Liuzhou Luosifen'), 2),((SELECT id FROM merchant WHERE name='Nanning Old Friend Noodles'), 2);-- Insert dish categories
INSERT INTO dish_category (merchant_id, name) VALUES
(1,'Fried Chicken Meals'),(1,'Burger Meals'),
(2,'Signature Noodles'),(2,'Rice Bowls'),
(3,'Classic Bubble Tea'),(3,'Summer Specials');-- Insert dishes
INSERT INTO dish (merchant_id, category_id, name, rating, monthly_sales, tags, price) VALUES
(1,1,'Spicy Chicken Burger Meal',4.5,800,'Popular',35.00),
(1,2,'Orleans Wings Meal',4.6,600,'New',40.00),
(2,3,'Beef Noodles',4.8,500,'Signature',18.00),
(2,4,'Braised Beef Rice Bowl',4.7,300,'Recommended',22.00),
(3,5,'Pearl Milk Tea',4.7,1500,'Classic',8.00),
(3,6,'Strawberry Sundae',4.8,1000,'Seasonal',6.00);-- Insert orders
INSERT INTO `order` (customer_name, customer_phone, delivery_address, merchant_id, total_amount, delivery_fee, packing_fee, status, order_time, payment_method) VALUES
('Zhang San','13800001111','Tech Park Building 1',1,77.00,5.00,2.00,'Completed','2024-03-01 12:00:00','WeChat Pay'),
('Li Si','13900002222','University Dorm 3',2,40.00,3.00,1.00,'Pending Delivery','2024-03-02 18:30:00','Alipay');-- Insert reviews
INSERT INTO review (order_item_id, rating, content, review_time) VALUES
(1,4.8,'Burgers were delicious!','2024-03-01 13:00:00'),
(3,4.9,'Very authentic noodles','2024-03-02 19:00:00');
step2:fastapi
from fastapi import FastAPI, HTTPException
from fastapi.middleware.cors import CORSMiddleware
import pymysql.cursors
from typing import List, Optional
from pydantic import BaseModel
from datetime import datetime
app = FastAPI()# CORS配置
app.add_middleware(CORSMiddleware,allow_origins=["*"],allow_credentials=True,allow_methods=["*"],allow_headers=["*"],
)# 数据库配置(根据实际情况修改)
DB_CONFIG = {'host': 'localhost','user': 'root','password': '123456','db': 'db_school','charset': 'utf8mb4','cursorclass': pymysql.cursors.DictCursor
}# 基础数据模型
class Category(BaseModel):id: intname: strclass MerchantBase(BaseModel):name: strrating: floatmonthly_sales: intavg_price: float# API 请求模型
class CreateOrderItem(BaseModel):dish_id: intquantity: intprice: floatclass CreateOrder(BaseModel):customer_name: strcustomer_phone: strdelivery_address: strmerchant_id: intitems: List[CreateOrderItem]payment_method: strnote: Optional[str] = Nonedef db_query(query: str, params=None, fetch_one=False):try:connection = pymysql.connect(**DB_CONFIG)with connection.cursor() as cursor:cursor.execute(query, params)result = cursor.fetchone() if fetch_one else cursor.fetchall()connection.commit()connection.close()return resultexcept Exception as e:raise HTTPException(status_code=500, detail=str(e))# 1. 获取所有美食分类
@app.get("/categories")
async def get_categories():"""获取所有美食分类"""query = "SELECT id, name FROM category"return {"data": db_query(query)}# 2. 商家列表接口
@app.get("/merchants")
async def get_merchants(category_id: Optional[int] = None,page: int = 1,page_size: int = 10,sort_by: str = 'rating'
):"""获取商家列表(支持分类筛选和排序)"""offset = (page - 1) * page_sizebase_query = """SELECT m.*, GROUP_CONCAT(c.name) AS categories FROM merchant mLEFT JOIN merchant_category mc ON m.id = mc.merchant_idLEFT JOIN category c ON mc.category_id = c.id"""where = []params = []if category_id:where.append("mc.category_id = %s")params.append(category_id)if where:base_query += " WHERE " + " AND ".join(where)base_query += " GROUP BY m.id"# 排序逻辑sort_columns = {'rating': 'm.rating DESC','sales': 'm.monthly_sales DESC','price': 'm.avg_price ASC'}order_by = sort_columns.get(sort_by, 'm.rating DESC')base_query += f" ORDER BY {order_by} LIMIT %s OFFSET %s"params.extend([page_size, offset])return {"data": db_query(base_query, params)}# 3. 商家详情
@app.get("/merchants/{merchant_id}")
async def get_merchant_detail(merchant_id: int):"""获取商家详细信息"""# 商家基本信息merchant = db_query("SELECT * FROM merchant WHERE id = %s", (merchant_id,), True)if not merchant:raise HTTPException(404, "商家不存在")# 菜品分类及菜品categories = db_query("""SELECT dc.id, dc.name, (SELECT JSON_ARRAYAGG(JSON_OBJECT('id',d.id,'name',d.name,'price',d.price,'rating',d.rating,'sales',d.monthly_sales,'tags',d.tags)) FROM dish d WHERE d.category_id = dc.id) AS dishesFROM dish_category dc WHERE dc.merchant_id = %s""", (merchant_id,))# 评价reviews = db_query("""SELECT r.rating, r.content, r.review_time, d.name AS dish_nameFROM review rJOIN order_item oi ON r.order_item_id = oi.idJOIN dish d ON oi.dish_id = d.idWHERE d.merchant_id = %s ORDER BY r.review_time DESC LIMIT 10""", (merchant_id,))return {"merchant": merchant,"categories": categories,"reviews": reviews}# 4. 创建订单接口
@app.post("/orders")
async def create_order(order_data: CreateOrder):"""创建新订单"""connection = pymysql.connect(**DB_CONFIG)try:with connection.cursor() as cursor:# 计算总金额total = sum(item.price * item.quantity for item in order_data.items)# 获取商家配送费cursor.execute("SELECT delivery_fee, min_order_price FROM merchant WHERE id = %s",(order_data.merchant_id,))merchant_info = cursor.fetchone()if not merchant_info:raise HTTPException(status_code=404, detail="Merchant not found")if total < merchant_info['min_order_price']:raise HTTPException(status_code=400,detail=f"订单金额需达到{merchant_info['min_order_price']}元")# 创建订单order_query = """INSERT INTO `order` (customer_name, customer_phone, delivery_address,merchant_id, total_amount, delivery_fee, status, order_time, payment_method, note) VALUES (%s,%s,%s,%s,%s,%s,%s,%s,%s,%s)"""order_params = (order_data.customer_name,order_data.customer_phone,order_data.delivery_address,order_data.merchant_id,total,merchant_info['delivery_fee'],'待接单',datetime.now(),order_data.payment_method,order_data.note)cursor.execute(order_query, order_params)order_id = cursor.lastrowid# 创建订单明细for item in order_data.items:cursor.execute("""INSERT INTO order_item (order_id, dish_id, quantity, price)VALUES (%s,%s,%s,%s)""", (order_id, item.dish_id, item.quantity, item.price))connection.commit()return {"order_id": order_id}except Exception as e:connection.rollback()raise HTTPException(status_code=500, detail=str(e))finally:connection.close()# 5. 订单详情接口
@app.get("/orders/{order_id}")
async def get_order_detail(order_id: int):"""获取订单详情"""order_query = """SELECT o.*, m.name AS merchant_name FROM `order` oJOIN merchant m ON o.merchant_id = m.idWHERE o.id = %s"""order = db_query(order_query, (order_id,), fetch_one=True)if not order:raise HTTPException(status_code=404, detail="订单不存在")items_query = """SELECT oi.*, d.name AS dish_name FROM order_item oiJOIN dish d ON oi.dish_id = d.idWHERE oi.order_id = %s"""items = db_query(items_query, (order_id,))return {"order": order, "items": items}# 6. 获取菜品评价
@app.get("/dishes/{dish_id}/reviews")
async def get_dish_reviews(dish_id: int):"""获取菜品评价"""return db_query("""SELECT r.rating, r.content, r.review_time, oi.quantity FROM review rJOIN order_item oi ON r.order_item_id = oi.idWHERE oi.dish_id = %sORDER BY r.review_time DESC""", (dish_id,))if __name__ == "__main__":import uvicornuvicorn.run(app, host="0.0.0.0", port=8000)
step3:商家列表 C:\Users\wangrusheng\WebstormProjects\untitled4\src\app\merchants-list\merchants-list.component.html
import { Component, OnInit } from '@angular/core';import { MerchantService} from '../services/merchant.service';
import {NgForOf, NgIf} from '@angular/common';
import {RouterLink} from '@angular/router';@Component({selector: 'app-merchants-list',imports: [NgForOf,NgIf,RouterLink],templateUrl: './merchants-list.component.html',styleUrl: './merchants-list.component.css'
})
export class MerchantsListComponent implements OnInit {categories: any[] = [];merchants: any[] = [];selectedCategoryId: number | null = null;isLoading = false;constructor(private merchantService: MerchantService) { }ngOnInit() {this.loadCategories();this.loadMerchants(); // 初始加载全部商家}// 加载分类数据loadCategories() {this.merchantService.getCategories().subscribe(res => {this.categories = res.data;});}// 加载商家数据loadMerchants(categoryId?: number) {this.isLoading = true;this.merchantService.getMerchants(categoryId).subscribe({next: (res) => {this.merchants = res.data;this.isLoading = false;},error: () => {this.isLoading = false;alert('加载商家失败,请重试');}});}// 分类选择处理selectCategory(categoryId: number | null) {this.selectedCategoryId = categoryId;this.loadMerchants(categoryId ?? undefined);}
}
<!-- takeout.component.html -->
<div class="container"><!-- 左侧分类导航 --><div class="categories-sidebar"><h3>美食分类</h3><ul><li*ngFor="let category of categories"[class.active]="selectedCategoryId === category.id"(click)="selectCategory(category.id)">{{category.name}}</li><li[class.active]="!selectedCategoryId"(click)="selectCategory(null)">全部商家</li></ul></div><!-- 右侧商家列表 --><div class="merchant-list"><!-- 加载状态 --><div *ngIf="isLoading" class="loading">加载中...</div><!-- 商家列表 --><div *ngFor="let merchant of merchants" class="merchant-card"><div class="merchant-header"><h3>{{merchant.name}}</h3><span class="rating">{{merchant.rating}} ★</span></div><div class="merchant-info"><div class="meta"><span>月售 {{merchant.monthly_sales}}</span><span>起送 ¥{{merchant.min_order_price}}</span><span>配送 ¥{{merchant.delivery_fee}}</span></div><a [routerLink]="['/merchants-detail', merchant.id]" class="detail-link">查看详情</a><div class="tags"><span *ngFor="let tag of merchant.tags.split(',')">{{tag}}</span></div></div></div></div>
</div>
/* takeout.component.css */
.container {display: grid;grid-template-columns: 200px 1fr;gap: 20px;padding: 20px;
}.categories-sidebar {background: #f5f5f5;padding: 15px;border-radius: 8px;
}.categories-sidebar ul {list-style: none;padding: 0;margin: 0;
}.categories-sidebar li {padding: 10px;cursor: pointer;border-radius: 4px;margin-bottom: 5px;transition: all 0.2s;
}.categories-sidebar li:hover {background: #eee;
}.categories-sidebar li.active {background: #007bff;color: white;
}.merchant-list {display: grid;gap: 15px;
}.merchant-card {padding: 20px;border: 1px solid #ddd;border-radius: 8px;
}.merchant-header {display: flex;justify-content: space-between;align-items: center;margin-bottom: 10px;
}.rating {color: #ffd700;font-weight: bold;
}.meta span {margin-right: 15px;color: #666;
}.tags span {display: inline-block;background: #f0f0f0;padding: 4px 8px;border-radius: 4px;margin: 5px 5px 0 0;font-size: 0.9em;
}.loading {text-align: center;padding: 20px;color: #666;
}
step4:商家详情 C:\Users\wangrusheng\WebstormProjects\untitled4\src\app\merchants-detail\merchants-detail.component.css
// merchants-detail.component.ts
import { Component, OnInit } from '@angular/core';
import {ActivatedRoute, RouterLink} from '@angular/router';
import { MerchantService } from '../services/merchant.service';
import { DatePipe, NgFor, NgIf } from '@angular/common';@Component({selector: 'app-merchants-detail',standalone: true,imports: [NgIf, NgFor, DatePipe, RouterLink],templateUrl: './merchants-detail.component.html',styleUrls: ['./merchants-detail.component.css']
})
export class MerchantsDetailComponent implements OnInit {merchantDetail: any;isLoading = true;errorMessage = '';constructor(private route: ActivatedRoute,private merchantService: MerchantService) { }ngOnInit() {const id = this.route.snapshot.paramMap.get('id');if (id) {this.loadMerchantDetail(+id);} else {this.errorMessage = '无效的商家ID';this.isLoading = false;}}loadMerchantDetail(id: number) {this.merchantService.getMerchantDetail(id).subscribe({next: (res) => {this.merchantDetail = {...res,categories: res.categories.map((cat: any) => ({...cat,dishes: JSON.parse(cat.dishes)}))};this.isLoading = false;},error: (err) => {this.errorMessage = '加载商家详情失败,请稍后重试';this.isLoading = false;}});}getRatingStars(rating: number): string {return '★'.repeat(Math.round(rating));}
}<!-- merchants-detail.component.html -->
<div class="merchant-container"><!-- 加载状态 --><div *ngIf="isLoading" class="loading">加载中...</div><!-- 错误提示 --><div *ngIf="errorMessage" class="error">{{ errorMessage }}</div><!-- 商家详情内容 --><div *ngIf="merchantDetail" class="merchant-content"><!-- 商家基本信息 --><section class="merchant-info"><h1>{{ merchantDetail.merchant.name }}</h1><div class="stats"><span class="rating">{{ getRatingStars(merchantDetail.merchant.rating) }}<em>({{ merchantDetail.merchant.rating }})</em></span><span>月售 {{ merchantDetail.merchant.monthly_sales }}</span><span>人均 ¥{{ merchantDetail.merchant.avg_price }}</span></div><div class="details"><div class="detail-item"><label>起送价:</label><span>¥{{ merchantDetail.merchant.min_order_price }}</span></div><div class="detail-item"><label>配送费:</label><span>¥{{ merchantDetail.merchant.delivery_fee }}</span></div><div class="detail-item"><label>营业时间:</label><span>{{ merchantDetail.merchant.business_hours }}</span></div><div class="detail-item"><label>联系电话:</label><a href="tel:{{ merchantDetail.merchant.contact_phone }}">{{ merchantDetail.merchant.contact_phone }}</a></div><div class="detail-item"><label>地址:</label><address>{{ merchantDetail.merchant.location }}</address></div></div><div class="tags"><span *ngFor="let tag of merchantDetail.merchant.tags.split(',')"class="tag">{{ tag }}</span></div></section><!-- 菜品分类 --><!-- merchants-detail.component.html --><section *ngFor="let category of merchantDetail.categories" class="menu-category"><h2>{{ category.name }}</h2><div class="dishes"><div *ngFor="let dish of category.dishes" class="dish-card"><!-- 其他菜品信息 --><div class="dish-info"><h3>{{ dish.name }}</h3><div class="dish-meta"><span class="price">¥{{ dish.price }}</span><span class="sales">月售 {{ dish.sales }}</span><span class="dish-rating">{{ getRatingStars(dish.rating) }}</span></div><div class="dish-tags"><span *ngFor="let tag of dish.tags.split(',')"class="tag">{{ tag }}</span></div><button class="book-button"[routerLink]="['/merchants-order']"[state]="{orderData: {dish: dish,merchant: merchantDetail.merchant}}">立即购买</button></div></div></div></section><!-- 用户评价 --><section class="reviews"><h2>用户评价 ({{ merchantDetail.reviews.length }})</h2><div *ngFor="let review of merchantDetail.reviews" class="review-card"><div class="review-header"><span class="rating">{{ getRatingStars(review.rating) }}</span><span class="dish">{{ review.dish_name }}</span><time [title]="review.review_time | date:'long'">{{ review.review_time | date:'yyyy-MM-dd HH:mm' }}</time></div><p class="content">{{ review.content }}</p></div></section></div>
</div>/* merchants-detail.component.css */
.merchant-container {max-width: 1200px;margin: 20px auto;padding: 20px;
}.loading, .error {text-align: center;padding: 40px;font-size: 1.2rem;
}.error {color: #dc3545;
}.merchant-content {background: #fff;border-radius: 8px;box-shadow: 0 2px 8px rgba(0,0,0,0.1);padding: 24px;
}.merchant-info h1 {color: #333;margin-bottom: 16px;
}.stats {display: flex;gap: 20px;margin-bottom: 24px;color: #666;
}.rating {color: #ffd700;font-size: 1.2em;
}
.rating em {color: #666;font-style: normal;font-size: 0.9em;margin-left: 8px;
}.details {display: grid;grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));gap: 16px;margin-bottom: 24px;
}.detail-item {display: flex;justify-content: space-between;padding: 8px 0;border-bottom: 1px solid #eee;
}.detail-item label {color: #999;
}.tags {display: flex;gap: 8px;flex-wrap: wrap;
}.tag {background: #f0f0f0;padding: 4px 12px;border-radius: 12px;font-size: 0.9em;color: #666;
}/* 菜品分类样式 */
.menu-category {margin: 32px 0;border-top: 2px solid #eee;padding-top: 24px;
}.menu-category h2 {color: #444;margin-bottom: 16px;
}.dishes {display: grid;grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));gap: 20px;
}.dish-card {border: 1px solid #eee;border-radius: 8px;padding: 16px;transition: transform 0.2s;
}.dish-card:hover {transform: translateY(-2px);
}.dish-meta {display: flex;gap: 12px;margin: 8px 0;color: #666;
}.price {color: #e4393c;font-weight: bold;
}.dish-rating {color: #ffd700;
}/* 评价样式 */
.reviews {margin-top: 40px;
}.review-card {padding: 16px;border: 1px solid #eee;border-radius: 8px;margin-bottom: 16px;
}.review-header {display: flex;gap: 12px;align-items: center;margin-bottom: 8px;color: #666;
}.review-header time {font-size: 0.9em;color: #999;
}.content {color: #333;line-height: 1.6;
}
step5:立即购买C:\Users\wangrusheng\WebstormProjects\untitled4\src\app\merchants-order\merchants-order.component.css
// merchants-order.component.ts
import { Component, OnInit } from '@angular/core';
import { Router, ActivatedRoute } from '@angular/router';
import {FormBuilder, FormGroup, ReactiveFormsModule, Validators} from '@angular/forms';
import {Location, NgIf} from '@angular/common';
import { MerchantService } from '../services/merchant.service';// 类型定义
interface Dish {id: number;name: string;price: number;// 其他字段根据实际API响应添加
}interface Merchant {id: number;name: string;delivery_fee: number;location: string;// 其他字段根据实际API响应添加
}interface OrderState {orderData: {dish: Dish;merchant: Merchant;};
}@Component({selector: 'app-merchants-order',templateUrl: './merchants-order.component.html',imports: [ReactiveFormsModule,NgIf],styleUrls: ['./merchants-order.component.css']
})
export class MerchantsOrderComponent implements OnInit {orderForm: FormGroup;selectedDish?: Dish;merchant?: Merchant;loading = false;constructor(private fb: FormBuilder,private location: Location,private router: Router,private route: ActivatedRoute,private merchantService: MerchantService) {this.orderForm = this.fb.group({customer_name: ['', [Validators.required, Validators.minLength(2)]],customer_phone: ['', [Validators.required, Validators.pattern(/^1[3-9]\d{9}$/)]],delivery_address: ['', [Validators.required, Validators.minLength(5)]],payment_method: ['alipay', Validators.required],note: [''],quantity: [1, [Validators.required, Validators.min(1), Validators.max(10)]]});}ngOnInit(): void {this.handleRouteState();this.setupFormListeners();}private handleRouteState(): void {const state = this.location.getState() as OrderState;console.log('路由状态:', state);if (state?.orderData?.dish && state?.orderData?.merchant) {this.selectedDish = state.orderData.dish;this.merchant = state.orderData.merchant;this.initFormWithFallbackData();} else {console.warn('无效的路由状态,尝试通过参数加载');this.loadFromQueryParams();}}private loadFromQueryParams(): void {this.route.queryParams.subscribe(params => {if (params['merchantId'] && params['dishId']) {this.merchantService.getMerchantDetail(params['merchantId']).subscribe({next: merchant => {this.merchant = merchant;this.selectedDish = this.findDishInCategories(merchant.categories, params['dishId']);if (!this.selectedDish) {this.redirectToMerchantList();}},error: () => this.redirectToMerchantList()});} else {this.redirectToMerchantList();}});}private findDishInCategories(categories: any[], dishId: string): Dish | undefined {for (const category of categories) {const dishes = JSON.parse(category.dishes);const found = dishes.find((d: any) => d.id === +dishId);if (found) return found;}return undefined;}private initFormWithFallbackData(): void {this.orderForm.patchValue({delivery_address: this.merchant?.location || ''});}private setupFormListeners(): void {this.orderForm.get('quantity')?.valueChanges.subscribe(value => {if (value > 10) {this.orderForm.get('quantity')?.setValue(10);}});}get totalAmount(): string {if (!this.selectedDish || !this.merchant) return '0.00';const quantity = this.orderForm.get('quantity')?.value || 1;return (this.selectedDish.price * quantity + this.merchant.delivery_fee).toFixed(2);}onSubmit(): void {if (this.orderForm.invalid || !this.selectedDish || !this.merchant) return;const orderData = {...this.orderForm.value,merchant_id: this.merchant.id,items: [{dish_id: this.selectedDish.id,quantity: this.orderForm.value.quantity,price: this.selectedDish.price}]};this.loading = true;this.merchantService.createOrder(orderData).subscribe({next: (res) => {this.router.navigate(['/merchants-order-detail', res.order_id]);this.loading = false;},error: (err) => {console.error('订单提交失败:', err);alert(`提交失败: ${err.error?.detail || '服务器错误'}`);this.loading = false;}});}private redirectToMerchantList(): void {this.router.navigate(['/merchants'], {queryParamsHandling: 'preserve'});}
}<!-- merchants-order.component.html -->
<div class="order-container"><h2>确认订单</h2><form *ngIf="merchant && selectedDish" [formGroup]="orderForm" (ngSubmit)="onSubmit()"><!-- 商家信息 --><div class="merchant-info"><h3>{{ merchant.name }}</h3><p>{{ merchant.location }}</p></div><!-- 商品信息 --><div class="dish-info"><h4>{{ selectedDish.name }}</h4><div class="price-quantity"><span class="price">¥{{ selectedDish.price }}</span><div class="quantity-control"><label>数量:</label><input type="number" formControlName="quantity" min="1"></div></div></div><!-- 订单表单 --><div class="form-section"><div class="form-group"><label>收货人姓名</label><input type="text" formControlName="customer_name"><div *ngIf="orderForm.get('customer_name')?.errors?.['required']" class="error">姓名不能为空</div></div><div class="form-group"><label>联系电话</label><input type="tel" formControlName="customer_phone"><div *ngIf="orderForm.get('customer_phone')?.errors?.['required']" class="error">电话不能为空</div><div *ngIf="orderForm.get('customer_phone')?.errors?.['pattern']" class="error">请输入有效的手机号</div></div><div class="form-group"><label>配送地址</label><textarea formControlName="delivery_address"></textarea><div *ngIf="orderForm.get('delivery_address')?.errors?.['required']" class="error">地址不能为空</div></div><div class="form-group"><label>支付方式</label><select formControlName="payment_method"><option value="alipay">支付宝</option><option value="wechat">微信支付</option><option value="cash">货到付款</option></select></div><div class="form-group"><label>备注</label><textarea formControlName="note"></textarea></div></div><!-- 费用汇总 --><div class="price-summary"><div class="summary-item"><span>商品总额:</span>
<!-- <span>¥{{ (selectedDish.price * orderForm.value.quantity).toFixed(2) }}</span>--></div><div class="summary-item"><span>配送费:</span><span>¥{{ merchant.delivery_fee }}</span></div><div class="summary-item total"><span>总计:</span><span>¥{{ totalAmount }}</span></div></div><button type="submit" [disabled]="orderForm.invalid || loading" class="submit-btn">{{ loading ? '提交中...' : '提交订单' }}</button></form>
</div>.order-container {max-width: 600px;margin: 20px auto;padding: 20px;background: #fff;border-radius: 8px;box-shadow: 0 2px 8px rgba(0,0,0,0.1);
}.merchant-info {margin-bottom: 20px;padding-bottom: 15px;border-bottom: 1px solid #eee;
}.dish-info {margin-bottom: 20px;
}.form-group {margin-bottom: 15px;
}.form-group label {display: block;margin-bottom: 5px;font-weight: bold;
}.form-group input,
.form-group textarea,
.form-group select {width: 100%;padding: 8px;border: 1px solid #ddd;border-radius: 4px;
}.error {color: #dc3545;font-size: 0.9em;margin-top: 5px;
}.price-summary {margin-top: 20px;padding: 15px;background: #f8f9fa;border-radius: 4px;
}.summary-item {display: flex;justify-content: space-between;margin-bottom: 10px;
}.total {font-weight: bold;font-size: 1.1em;
}.submit-btn {width: 100%;padding: 12px;background: #007bff;color: white;border: none;border-radius: 4px;cursor: pointer;margin-top: 20px;
}.submit-btn:disabled {background: #6c757d;cursor: not-allowed;
}
step6:订单详情C:\Users\wangrusheng\WebstormProjects\untitled4\src\app\merchants-order-detail\merchants-order-detail.component.css
// merchants-order-detail.component.ts
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { MerchantService } from '../services/merchant.service';
import { DatePipe, CurrencyPipe, NgIf, NgFor } from '@angular/common';interface OrderItem {id: number;dish_name: string;quantity: number;price: number;
}interface OrderDetail {id: number;customer_name: string;customer_phone: string;delivery_address: string;total_amount: number;delivery_fee: number;packing_fee: number;status: string;order_time: string;complete_time: string | null;rider_name: string | null;rider_phone: string | null;payment_method: string;note: string | null;merchant_name: string;
}@Component({selector: 'app-merchants-order-detail',standalone: true,imports: [NgIf, NgFor, DatePipe, CurrencyPipe],templateUrl: './merchants-order-detail.component.html',styleUrls: ['./merchants-order-detail.component.css']
})
export class MerchantsOrderDetailComponent implements OnInit {orderId!: number;orderId2!: number;order!: OrderDetail;items: OrderItem[] = [];isLoading = true;errorMessage = '';constructor(private route: ActivatedRoute,private router: Router,private merchantService: MerchantService) {}ngOnInit(): void {this.route.params.subscribe(params => {this.orderId = +params['order_id'];this.orderId2 = params['order_id'];console.log('从路由获取的order_id:', this.orderId+"==="+this.orderId2);this.loadOrderDetail();});}loadOrderDetail(): void {this.isLoading = true;this.merchantService.getOrderDetail(this.orderId).subscribe({next: (res) => {this.order = res.order;this.items = res.items;this.isLoading = false;},error: (err) => {console.error('加载失败:', err);this.errorMessage = '无法加载订单详情,请稍后重试';this.isLoading = false;}});}getStatusClass(): string {switch(this.order.status) {case '已完成': return 'status-completed';case '待接单': return 'status-pending';case '配送中': return 'status-delivering';default: return 'status-default';}}
}<!-- merchants-order-detail.component.html -->
<div class="order-detail-container"><!-- 加载状态 --><div *ngIf="isLoading" class="loading">加载中...</div><!-- 错误提示 --><div *ngIf="errorMessage" class="error">{{ errorMessage }}</div><!-- 订单详情 --><div *ngIf="order" class="order-content"><!-- 订单头信息 --><div class="order-header"><h2>订单号:{{ order.id }}</h2><span [class]="getStatusClass()">{{ order.status }}</span></div><!-- 基本信息 --><div class="section"><h3>订单信息</h3><div class="info-grid"><div class="info-item"><label>下单时间:</label><span>{{ order.order_time | date:'yyyy-MM-dd HH:mm' }}</span></div><div class="info-item"><label>商家名称:</label><span>{{ order.merchant_name }}</span></div><div class="info-item"><label>支付方式:</label><span>{{ order.payment_method }}</span></div></div></div><!-- 商品清单 --><div class="section"><h3>商品清单</h3><table class="item-table"><thead><tr><th>商品名称</th><th>单价</th><th>数量</th><th>小计</th></tr></thead><tbody><tr *ngFor="let item of items"><td>{{ item.dish_name }}</td><td>{{ item.price | currency:'CNY':'symbol':'1.2-2' }}</td><td>{{ item.quantity }}</td><td>{{ item.price * item.quantity | currency:'CNY':'symbol':'1.2-2' }}</td></tr></tbody></table></div><!-- 费用明细 --><div class="section"><h3>费用明细</h3><div class="fee-details"><div class="fee-item"><span>商品总额:</span><span>{{ order.total_amount - order.delivery_fee - order.packing_fee | currency:'CNY':'symbol':'1.2-2' }}</span></div><div class="fee-item"><span>配送费:</span><span>{{ order.delivery_fee | currency:'CNY':'symbol':'1.2-2' }}</span></div><div class="fee-item"><span>包装费:</span><span>{{ order.packing_fee | currency:'CNY':'symbol':'1.2-2' }}</span></div><div class="fee-item total"><span>实付金额:</span><span>{{ order.total_amount | currency:'CNY':'symbol':'1.2-2' }}</span></div></div></div><!-- 配送信息 --><div class="section"><h3>配送信息</h3><div class="delivery-info"><p>收货人:{{ order.customer_name }}</p><p>联系电话:{{ order.customer_phone }}</p><p>配送地址:{{ order.delivery_address }}</p><div *ngIf="order.rider_name" class="rider-info"><p>骑手:{{ order.rider_name }}</p><p>骑手电话:{{ order.rider_phone }}</p></div></div></div><!-- 备注信息 --><div *ngIf="order.note" class="section"><h3>订单备注</h3><p class="note">{{ order.note }}</p></div></div>
</div>/* merchants-order-detail.component.css */
.order-detail-container {max-width: 1200px;margin: 20px auto;padding: 20px;background: #fff;border-radius: 8px;box-shadow: 0 2px 8px rgba(0,0,0,0.1);
}.loading, .error {text-align: center;padding: 40px;font-size: 1.2rem;
}.error {color: #dc3545;
}.order-header {display: flex;justify-content: space-between;align-items: center;margin-bottom: 20px;padding-bottom: 15px;border-bottom: 1px solid #eee;
}.section {margin-bottom: 30px;padding: 15px;background: #f8f9fa;border-radius: 6px;
}.info-grid {display: grid;grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));gap: 15px;
}.item-table {width: 100%;border-collapse: collapse;margin-top: 10px;
}.item-table th,
.item-table td {padding: 12px;text-align: left;border-bottom: 1px solid #eee;
}.item-table th {background: #f8f9fa;
}.fee-details {max-width: 400px;
}.fee-item {display: flex;justify-content: space-between;margin-bottom: 10px;
}.fee-item.total {font-weight: bold;border-top: 1px solid #eee;padding-top: 10px;font-size: 1.1em;
}.note {color: #666;line-height: 1.6;
}/* 状态标签样式 */
.status-completed { color: #28a745; }
.status-pending { color: #ffc107; }
.status-delivering { color: #17a2b8; }
.status-default { color: #6c757d; }
end
相关文章:
fastapi+angular外卖系统
说明: fastapiangular外卖系统 1.美食分类(粥,粉,面,炸鸡,炒菜,西餐,奶茶等等) 2.商家列表 (kfc,兰州拉面,湘菜馆,早餐店…...
Oracle静默安装方法
Web服务器上面的Linux一般是不会有图形界面的,所有通过图形界面来安装Linux的方式在没有图形界面的Linux上面是行不通的,我们要使用的安装方式叫做Linux的静默安装。即在没有图形界面的Linux上面安装。 1. 下载地址 http://www.oracle.com/technetwork…...
鸿蒙路由 HMRouter 配置及使用 三 全局拦截器使用
1、前期准备 简单封装一个用户首选项的工具类 import { preferences } from "kit.ArkData";// 用户首选项方法封装 export class Preferences {private myPreferences: preferences.Preferences | null null;// 初始化init(context: Context, options: preference…...
计算机视觉——深入理解卷积神经网络与使用卷积神经网络创建图像分类算法
引言 卷积神经网络(Convolutional Neural Networks,简称 CNNs)是一种深度学习架构,专门用于处理具有网格结构的数据,如图像、视频等。它们在计算机视觉领域取得了巨大成功,成为图像分类、目标检测、图像分…...
永磁同步电机无速度算法--拓展卡尔曼滤波器
一、原理介绍 以扩展卡尔曼滤波算法为基础,建立基于EKF算法的估算转子位置和转速的离散模型。 实时性是扩展卡尔曼滤波器的一种特征,所以它可实时跟踪系统的状态并进行有效的输出,同时,它可以减少干扰、抑制噪声,其效…...
电机控制常见面试问题(十五)
文章目录 一、电机气隙二、电气时间三.电机三环控制详解四.驱动板跳线意义 一、电机气隙 电机气隙是定子和转子之间的空隙,防止钉子转子运转时物理接触,此外,气隙是磁路的重要环节,磁场需通过气隙传递能量,但其较高的…...
a2字幕分享
1. 沟通communication Hey everybody Welcome to this A2 English listening practice video. You can use this video to practice your listening and comprehension as I speak. Before we start, remember to download the Listening Time podcast and become a member a…...
基于cat1的多传感器融合的贵重资产管理解决方案项目说明书
一、产品需求 在物流运输中,搭载 Cat 1 模块的贵重货物跟踪设备,可将货物的位置、震动、温湿度等数据及时传输给物流调度中心,以便及时应对运输途中可能出现的问题,如路线偏离、货物受损风险等 。而且,Cat 1 依托成熟的…...
deepseek使用记录23——我们的遭遇
世界观设定 时间:近未来2035年,全球进入"数字绩效社会"地点:重庆赛博朋克风格的"云端之城",外卖骑手被称为"数据蜂鸟"核心科技:情感区块链系统,人类情绪波动可转化为能量币…...
【CF】Day9——Codeforces Round 953 (Div. 2) BCD
B. New Bakery 题目: 思路: 被标签害了,用什么二分( 很简单的思维题,首先如果a > b,那么全选a就行了,还搞啥活动 否则就选 b - a 天来搞活动,为什么? 首先如果我…...
PEFT简介
以下是关于 PEFT(Parameter-Efficient Fine-tuning) 的简介,涵盖其定义、核心思想、常见方法及应用场景: 1. 什么是PEFT? PEFT(参数高效微调)是机器学习领域的一种技术,专为预训练大…...
harmonyOS NEXT开发与前端开发深度对比分析
文章目录 1. 技术体系概览1.1 技术栈对比1.2 生态对比 2. 开发范式比较2.1 鸿蒙开发范式2.2 前端开发范式 3. 框架特性对比3.1 鸿蒙 Next 框架特性3.2 前端框架特性 4. 性能优化对比4.1 鸿蒙性能优化4.2 前端性能优化 5. 开发工具对比5.1 鸿蒙开发工具5.2 前端开发工具 6. 学习…...
Unity小框架之单例模式基类
单例模式(Singleton Pattern)是一种常用的创建型设计模式,其核心目标是确保一个类只有一个实例,并提供一个全局访问点。它常用于需要控制资源访问、共享配置或管理全局状态的场景(如数据库连接池、日志管理器、应用配置…...
随机过程的基本概念机有限维分布的数字特征
随机过程的基本概念及有限维分布的数字特征:从理论到应用 在现代科学与技术的众多领域中,随机过程的身影无处不在,它如同一位神秘的幕后操纵者,影响着我们生活的方方面面。今天,咱们就一起来深入探究随机过程的基本概…...
langchain如何并行调用运行接口
文章目录 概要并行化步骤 概要 RunnableParallel 原语本质上是一个字典,其值是运行接口(或可以被强制转换为运行接口的事物,如函数)。它并行运行所有值,并且每个值都使用 RunnableParallel 的整体输入进行调用。最终返…...
如何理解语义web中提到本体的概念
在语义Web(Semantic Web)中,“本体”(Ontology)是一个核心概念,它源自哲学中的“存在论”,但在计算机科学中被重新定义为一种形式化的、共享的领域知识模型。本体的核心目标是解决数据之间的语义…...
基于大模型的声带息肉预测及诊疗方案优化研究报告
目录 一、引言 1.1 研究背景与目的 1.2 研究意义与创新点 二、大模型预测原理与方法 2.1 大模型技术概述 2.2 数据收集与处理 2.3 模型构建与训练 2.4 模型评估指标 三、术前预测与评估 3.1 息肉特征预测 3.1.1 大小与位置预测 3.1.2 形态与性质预测 3.2 患者身体…...
cesium 实现万级管网数据渲染,及pickImageryLayerFeatures原生方法改写
需求背景解决效果getFeatureInfo 需求背景 在用 geoserver 渲染图层时,会自动触发 GetFeatureInfo ,与服务器通信,在万级海量数据渲染下,这个性能消耗就可以感受到了 需要考虑的点: 1.通过enablePickFeatures…...
基于金融产品深度学习推荐算法详解【附源码】
深度学习算法说明 1、简介 神经网络协同过滤模型(NCF) 为了解决启发式推荐算法的问题,基于神经网络的协同过滤算法诞生了,神经网络的协同过滤算法可以 通过将用户和物品的特征向量作为输入,来预测用户对新物品的评分,从而解决…...
【Linux】centos配置可用的yum源
在 CentOS 系统中配置可用的 YUM 源(仓库)是保持系统更新和软件包管理的重要步骤。下面是一些步骤和示例,帮助你配置可用的 YUM 源: 1. 备份当前 YUM 仓库配置 首先,备份你当前的 YUM 仓库配置文件,以防万…...
LVS + Keepalived 高可用集群
一、LVSKeepalived 原理 1.1.LVS 负载均衡原理 LVS(Linux Virtual Server)是一种基于 Linux 内核的负载均衡技术,它通过 IPVS(IP Virtual Server)模块来实现。LVS 可以将客户端的请求分发到多个后端服务器上…...
PHP与数据库连接常见问题及解决办法
PHP与数据库连接常见问题及解决办法 在现代Web开发中,PHP与数据库的连接是不可或缺的一部分。无论是构建动态网站、内容管理系统(CMS)还是电子商务平台,PHP与数据库的交互都是核心功能之一。然而,在实际开发过程中&am…...
HarmonyOS-应用程序框架基础
应用程序框架与应用模型的区别 应用框架可以看做是应用模型的一种实现方式,开发人员可以用应用模型来描述应用程序的结构和行为的描述,然后使用应用程序框架来实现这些描述。 应用模型 应用模型是一个应用程序的模型,它是一种抽象的描述&a…...
使用 Doris 和 LakeSoul
作为一种全新的开放式的数据管理架构,湖仓一体(Data Lakehouse)融合了数据仓库的高性能、实时性以及数据湖的低成本、灵活性等优势,帮助用户更加便捷地满足各种数据处理分析的需求,在企业的大数据体系中已经得到越来越…...
【C语言】函数和数组实践与应用:开发简单的扫雷游戏
【C语言】函数和数组实践与应用:开发简单的扫雷游戏 1.扫雷游戏分析和设计1.1扫雷游戏的功能说明(游戏规则)1.2游戏的分析与设计1.2.1游戏的分析1.2.2 文件结构设计 2. 代码实现2.1 game.h文件2.2 game.c文件2.3 test.c文件 3. 游戏运行效果4…...
国内Mac,nimi安装homebrew完整过程
安装命令: 常规安装脚本: /bin/zsh -c "$(curl -fsSL https://gitee.com/cunkai/HomebrewCN/raw/master/Homebrew.sh)" 极速安装脚本: /bin/zsh -c "$(curl -fsSL https://gitee.com/cunkai/HomebrewCN/raw/master/Homebrew.…...
C++基础——从C语言快速入门
目录 输入输出 标准输出流 ( cout ) 标准输入流 ( cin ) 标准错误流 ( cerr ) 和标准日志流 ( clog ) 编程示例 基本变量类型 宽字符的用法 climits 如何使用 编程示例 注意事项 流程控制 条件语句 循环语句 跳转语句 函数 函数的基本结构 编程示例 函数的组成…...
玩转python:通俗易懂掌握高级数据结构-collections模块之Counter
引言 Counter是Python中collections模块提供的一个强大工具,用于统计可哈希对象的出现次数。它非常适合用于频率统计、词频分析、数据聚合等场景。本文将详细介绍Counter的关键用法和特性,并通过8个丰富的案例帮助读者掌握其应用。 关键用法和特性表格 …...
Windows远程桌面黑屏怎么办?
在使用Windows远程桌面连接另一台电脑时,用户经常会遇到Windows远程桌面黑屏的问题。那么,该如何有效地解决Windows远程桌面黑屏的问题呢?遇到远程桌面连接黑屏的问题时,可以通过在本地组策略编辑器中禁用WDDM图形显示驱动来解决。…...
82.HarmonyOS NEXT 性能优化指南:从理论到实践
温馨提示:本篇博客的详细代码已发布到 git : https://gitcode.com/nutpi/HarmonyosNext 可以下载运行哦! HarmonyOS NEXT 性能优化指南:从理论到实践 文章目录 HarmonyOS NEXT 性能优化指南:从理论到实践1. 性能优化概述1.1 性能指…...
