FastUI电商应用:购物车与结账流程实现
【免费下载链接】FastUI Build better UIs faster. 项目地址: https://gitcode.com/GitHub_Trending/fa/FastUI
概述
在当今电商时代,流畅的购物车和结账体验是提升转化率的关键因素。FastUI作为一个声明式的Python Web UI框架,为开发者提供了构建现代化电商界面的强大工具。本文将深入探讨如何使用FastUI实现完整的电商购物车和结账流程。
核心概念
FastUI电商架构
技术栈组成
| 组件类型 | 技术实现 | 作用描述 |
|---|---|---|
| 前端组件 | FastUI React组件 | 渲染购物车界面和结账表单 |
| 后端逻辑 | FastAPI + Pydantic | 处理业务逻辑和数据验证 |
| 数据模型 | Pydantic模型 | 定义商品、订单、用户等数据结构 |
| 状态管理 | FastUI事件系统 | 处理用户交互和页面跳转 |
购物车实现
商品数据模型
from pydantic import BaseModel, Field
from typing import List, Optional
from datetime import datetime
class Product(BaseModel):
id: int = Field(title="商品ID")
name: str = Field(title="商品名称")
price: float = Field(title="价格", ge=0)
stock: int = Field(title="库存", ge=0)
description: Optional[str] = Field(title="商品描述")
image_url: Optional[str] = Field(title="图片链接")
class CartItem(BaseModel):
product: Product
quantity: int = Field(title="数量", ge=1)
added_at: datetime = Field(title="添加时间", default_factory=datetime.now)
@property
def total_price(self) -> float:
return self.product.price * self.quantity
class ShoppingCart(BaseModel):
items: List[CartItem] = Field(default_factory=list, title="购物车商品")
user_id: Optional[int] = Field(title="用户ID")
@property
def total_items(self) -> int:
return sum(item.quantity for item in self.items)
@property
def total_amount(self) -> float:
return sum(item.total_price for item in self.items)
def add_item(self, product: Product, quantity: int = 1):
"""添加商品到购物车"""
for item in self.items:
if item.product.id == product.id:
item.quantity += quantity
return
self.items.append(CartItem(product=product, quantity=quantity))
def remove_item(self, product_id: int):
"""从购物车移除商品"""
self.items = [item for item in self.items if item.product.id != product_id]
def update_quantity(self, product_id: int, quantity: int):
"""更新商品数量"""
for item in self.items:
if item.product.id == product_id:
if quantity <= 0:
self.remove_item(product_id)
else:
item.quantity = quantity
return
购物车界面组件
from fastapi import APIRouter, Request
from fastui import AnyComponent, FastUI
from fastui import components as c
from fastui.events import GoToEvent, BackEvent
from fastui.components.display import DisplayLookup, DisplayMode
router = APIRouter()
# 模拟商品数据
products = [
Product(id=1, name="智能手机", price=2999.0, stock=100, description="最新款智能手机"),
Product(id=2, name="笔记本电脑", price=5999.0, stock=50, description="高性能笔记本电脑"),
Product(id=3, name="无线耳机", price=399.0, stock=200, description="高品质无线耳机"),
]
# 用户购物车状态(实际应用中应使用数据库或缓存)
user_carts = {}
@router.get('/cart', response_model=FastUI, response_model_exclude_none=True)
async def cart_view(request: Request):
"""购物车页面"""
# 获取或创建用户购物车
session_id = request.cookies.get("session_id", "default")
cart = user_carts.get(session_id, ShoppingCart())
cart_components = []
if cart.items:
# 购物车商品列表
cart_components.extend([
c.Table(
data=cart.items,
columns=[
DisplayLookup(field='product.name', title='商品名称'),
DisplayLookup(field='product.price', title='单价', mode=DisplayMode.currency),
DisplayLookup(field='quantity', title='数量'),
DisplayLookup(field='total_price', title='小计', mode=DisplayMode.currency),
c.Display(
components=[
c.Button(
text="-",
on_click=GoToEvent(url=f'/api/cart/decrease/{item.product.id}'),
class_name='btn-sm btn-outline-secondary'
),
c.Button(
text="+",
on_click=GoToEvent(url=f'/api/cart/increase/{item.product.id}'),
class_name='btn-sm btn-outline-primary'
),
c.Button(
text="删除",
on_click=GoToEvent(url=f'/api/cart/remove/{item.product.id}'),
class_name='btn-sm btn-outline-danger'
)
]
)
]
),
c.Div(
components=[
c.Text(text=f"总计: {cart.total_amount:.2f}元", class_name='h4'),
c.Button(
text="去结算",
on_click=GoToEvent(url='/checkout'),
class_name='btn-primary btn-lg'
)
],
class_name='text-end mt-4'
)
])
else:
# 空购物车提示
cart_components.append(
c.Div(
components=[
c.Heading(text="购物车为空", level=3),
c.Paragraph(text="您还没有添加任何商品到购物车"),
c.Button(
text="继续购物",
on_click=GoToEvent(url='/products'),
class_name='btn-primary'
)
],
class_name='text-center py-5'
)
)
return [
c.Page(
components=[
c.Heading(text="购物车", level=2),
*cart_components
]
)
]
结账流程实现
订单数据模型
from enum import Enum
from pydantic import EmailStr, validator
class OrderStatus(str, Enum):
PENDING = "pending" # 待支付
PAID = "paid" # 已支付
SHIPPED = "shipped" # 已发货
COMPLETED = "completed" # 已完成
CANCELLED = "cancelled" # 已取消
class PaymentMethod(str, Enum):
ALIPAY = "alipay" # 支付宝
WECHAT = "wechat" # 微信支付
BANK = "bank" # 银行卡
CASH = "cash" # 当面支付
class ShippingAddress(BaseModel):
recipient: str = Field(title="收货人")
phone: str = Field(title="联系号码")
province: str = Field(title="省份")
city: str = Field(title="城市")
district: str = Field(title="区县")
address: str = Field(title="详细地址")
postal_code: str = Field(title="邮政编码")
class Order(BaseModel):
id: str = Field(title="订单号")
user_id: Optional[int] = Field(title="用户ID")
items: List[CartItem] = Field(title="订单商品")
total_amount: float = Field(title="订单总额", ge=0)
shipping_address: ShippingAddress = Field(title="收货地址")
payment_method: PaymentMethod = Field(title="支付方式")
status: OrderStatus = Field(title="订单状态", default=OrderStatus.PENDING)
created_at: datetime = Field(title="创建时间", default_factory=datetime.now)
paid_at: Optional[datetime] = Field(title="支付时间")
@validator('id')
def validate_order_id(cls, v):
if not v.startswith('ORD'):
raise ValueError('订单号必须以ORD开头')
return v
结账表单组件
class CheckoutForm(BaseModel):
recipient: str = Field(title="收货人", min_length=2, max_length=50)
phone: str = Field(title="手机号码", pattern=r'^1[3-9]\d{9}$')
province: str = Field(title="省份")
city: str = Field(title="城市")
district: str = Field(title="区县")
address: str = Field(title="详细地址", min_length=5, max_length=200)
postal_code: str = Field(title="邮政编码", pattern=r'^\d{6}$')
payment_method: PaymentMethod = Field(title="支付方式")
notes: Optional[str] = Field(title="备注", max_length=500)
@router.get('/checkout', response_model=FastUI, response_model_exclude_none=True)
async def checkout_view(request: Request):
"""结账页面"""
session_id = request.cookies.get("session_id", "default")
cart = user_carts.get(session_id, ShoppingCart())
if not cart.items:
return [c.FireEvent(event=GoToEvent(url='/cart'))]
return [
c.Page(
components=[
c.Heading(text="订单结算", level=2),
# 订单摘要
c.Div(
components=[
c.Heading(text="订单信息", level=4),
c.Table(
data=cart.items,
columns=[
DisplayLookup(field='product.name', title='商品'),
DisplayLookup(field='quantity', title='数量'),
DisplayLookup(field='total_price', title='金额', mode=DisplayMode.currency),
]
),
c.Text(text=f"订单总额: {cart.total_amount:.2f}元", class_name='h5 text-end')
],
class_name='mb-4 p-3 border rounded'
),
# 收货信息表单
c.Heading(text="收货信息", level=4),
c.ModelForm(
model=CheckoutForm,
submit_url='/api/checkout/submit',
display_mode='page'
)
]
)
]
订单处理逻辑
from fastui.forms import fastui_form
import uuid
@router.post('/checkout/submit', response_model=FastUI, response_model_exclude_none=True)
async def checkout_submit(
request: Request,
form: Annotated[CheckoutForm, fastui_form(CheckoutForm)]
):
"""处理订单提交"""
session_id = request.cookies.get("session_id", "default")
cart = user_carts.get(session_id)
if not cart or not cart.items:
return [c.FireEvent(event=GoToEvent(url='/cart'))]
# 生成订单
order_id = f"ORD{str(uuid.uuid4())[:8].upper()}"
shipping_address = ShippingAddress(**form.dict())
order = Order(
id=order_id,
items=cart.items.copy(),
total_amount=cart.total_amount,
shipping_address=shipping_address,
payment_method=form.payment_method
)
# 保存订单(实际应用中应保存到数据库)
orders[order_id] = order
# 清空购物车
user_carts[session_id] = ShoppingCart()
# 跳转到支付页面
return [c.FireEvent(event=GoToEvent(url=f'/payment/{order_id}'))]
@router.get('/payment/{order_id}', response_model=FastUI, response_model_exclude_none=True)
async def payment_view(order_id: str):
"""支付页面"""
order = orders.get(order_id)
if not order:
return [c.FireEvent(event=GoToEvent(url='/'))]
payment_methods = {
PaymentMethod.ALIPAY: "支付宝支付",
PaymentMethod.WECHAT: "微信支付",
PaymentMethod.BANK: "银行卡支付",
PaymentMethod.CASH: "当面支付"
}
return [
c.Page(
components=[
c.Heading(text="支付订单", level=2),
c.Div(
components=[
c.Text(text=f"订单号: {order.id}", class_name='h5'),
c.Text(text=f"订单金额: {order.total_amount:.2f}元", class_name='h5'),
c.Text(text=f"支付方式: {payment_methods[order.payment_method]}", class_name='h5')
],
class_name='mb-4 p-3 border rounded'
),
c.Div(
components=[
c.Button(
text="确认支付",
on_click=GoToEvent(url=f'/api/payment/confirm/{order_id}'),
class_name='btn-success btn-lg'
),
c.Button(
text="取消订单",
on_click=GoToEvent(url=f'/api/order/cancel/{order_id}'),
class_name='btn-outline-secondary btn-lg ms-2'
)
],
class_name='text-center'
)
]
)
]
完整电商流程集成
主应用集成
from fastapi import FastAPI
from fastapi.responses import HTMLResponse
from fastui import prebuilt_html
app = FastAPI(title="FastUI电商示例")
# 注册路由
app.include_router(router, prefix="/api")
# 模拟数据存储
orders = {}
user_carts = {}
@app.get('/{path:path}')
async def html_landing() -> HTMLResponse:
"""服务React应用"""
return HTMLResponse(prebuilt_html(title='FastUI电商示例'))
# 购物车操作API
@app.get('/api/cart/increase/{product_id}')
async def increase_cart_item(product_id: int, request: Request):
session_id = request.cookies.get("session_id", "default")
cart = user_carts.get(session_id, ShoppingCart())
product = next((p for p in products if p.id == product_id), None)
if product:
cart.add_item(product)
user_carts[session_id] = cart
return [c.FireEvent(event=GoToEvent(url='/cart'))]
@app.get('/api/cart/decrease/{product_id}')
async def decrease_cart_item(product_id: int, request: Request):
session_id = request.cookies.get("session_id", "default")
cart = user_carts.get(session_id)
if cart:
for item in cart.items:
if item.product.id == product_id:
if item.quantity > 1:
item.quantity -= 1
else:
cart.remove_item(product_id)
break
user_carts[session_id] = cart
return [c.FireEvent(event=GoToEvent(url='/cart'))]
@app.get('/api/cart/remove/{product_id}')
async def remove_cart_item(product_id: int, request: Request):
session_id = request.cookies.get("session_id", "default")
cart = user_carts.get(session_id)
if cart:
cart.remove_item(product_id)
user_carts[session_id] = cart
return [c.FireEvent(event=GoToEvent(url='/cart'))]
最佳实践和优化建议
性能优化策略
安全考虑
- 输入验证:使用Pydantic进行严格的数据验证
- XSS防护:FastUI自动处理HTML转义
- CSRF保护:实现令牌验证机制
- 数据加密:敏感信息加密存储
扩展功能建议
| 功能模块 | 实现方式 | 业务价值 |
|---|---|---|
| 优惠券系统 | 折扣计算组件 | 提升转化率 |
| 库存管理 | 实时库存检查 | 避免超卖 |
| 订单追踪 | 物流状态组件 | 提升用户体验 |
| 会员体系 | 积分和等级系统 | 增加用户粘性 |
总结
通过FastUI构建电商购物车和结账流程,开发者可以享受到声明式编程带来的诸多好处:
- 开发效率:后端定义UI,减少前后端沟通成本
- 类型安全:Pydantic和TypeScript提供完整的类型检查
- 维护性:清晰的业务逻辑分离,便于维护和扩展
- 一致性:统一的组件库确保用户体验的一致性
FastUI为电商应用开发提供了一种现代化的解决方案,特别适合需要快速迭代和高质量代码的电商项目。通过本文介绍的实现方式,您可以快速构建出功能完善、用户体验优秀的电商购物系统。
【免费下载链接】FastUI Build better UIs faster. 项目地址: https://gitcode.com/GitHub_Trending/fa/FastUI
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考



