电商网站是Web开发中最复杂的项目类型之一,它涉及商品管理、购物车、订单处理、支付集成等多个核心模块,是学习全栈开发的综合实践项目。
东巴文(db-w.cn) 认为:电商网站不仅是技术挑战,更是商业平台。好的电商网站应该让购物变得简单愉快,让商家轻松管理商品和订单。
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>项目规划 - 东巴文</title>
<style>
body {
font-family: 'Segoe UI', sans-serif;
padding: 20px;
background: #f5f5f5;
}
.container {
max-width: 800px;
margin: 0 auto;
background: white;
padding: 30px;
border-radius: 10px;
}
h1 {
color: #667eea;
margin-bottom: 20px;
}
h2 {
color: #764ba2;
margin: 30px 0 15px;
border-left: 4px solid #764ba2;
padding-left: 15px;
}
.goal-card {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
padding: 20px;
margin: 15px 0;
border-radius: 10px;
}
.goal-card h3 {
margin-bottom: 10px;
}
.info-table {
width: 100%;
border-collapse: collapse;
margin: 20px 0;
}
.info-table th,
.info-table td {
padding: 12px;
text-align: left;
border: 1px solid #ddd;
}
.info-table th {
background: #667eea;
color: white;
}
</style>
</head>
<body>
<div class="container">
<h1>项目规划</h1>
<h2>项目目标</h2>
<div class="goal-card">
<h3>🎯 核心目标</h3>
<ul>
<li>实现商品展示和分类浏览</li>
<li>支持购物车和结算流程</li>
<li>集成支付系统</li>
<li>实现订单管理和物流跟踪</li>
</ul>
</div>
<div class="goal-card">
<h3>🎯 次要目标</h3>
<ul>
<li>支持商品搜索和筛选</li>
<li>实现用户评价系统</li>
<li>添加优惠券和促销功能</li>
<li>提供数据统计和分析</li>
</ul>
</div>
<h2>技术选型</h2>
<table class="info-table">
<thead>
<tr>
<th>技术层</th>
<th>技术选择</th>
<th>说明</th>
</tr>
</thead>
<tbody>
<tr>
<td>前端</td>
<td>HTML5 + CSS3 + JavaScript</td>
<td>原生技术,性能优化</td>
</tr>
<tr>
<td>后端</td>
<td>Node.js + Express</td>
<td>适合高并发场景</td>
</tr>
<tr>
<td>数据库</td>
<td>MongoDB / PostgreSQL</td>
<td>灵活的文档数据库或关系数据库</td>
</tr>
<tr>
<td>支付</td>
<td>支付宝 / 微信支付</td>
<td>主流支付方式</td>
</tr>
<tr>
<td>部署</td>
<td>云服务器 + CDN</td>
<td>高可用架构</td>
</tr>
</tbody>
</table>
<h2>项目范围</h2>
<ul>
<li><strong>用户角色:</strong> 买家、商家、管理员</li>
<li><strong>核心功能:</strong> 商品管理、购物车、订单、支付</li>
<li><strong>开发周期:</strong> 8-12周</li>
<li><strong>团队规模:</strong> 3-5人</li>
</ul>
<div style="background: #fff3cd; padding: 15px; border-radius: 5px; margin-top: 20px;">
<strong>东巴文提示:</strong>电商系统复杂度高,建议分阶段开发。先实现核心的购物流程,再逐步添加促销、评价等高级功能。
</div>
</div>
</body>
</html>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>需求分析 - 东巴文</title>
<style>
body {
font-family: 'Segoe UI', sans-serif;
padding: 20px;
background: #f5f5f5;
}
.container {
max-width: 800px;
margin: 0 auto;
background: white;
padding: 30px;
border-radius: 10px;
}
h1 {
color: #667eea;
margin-bottom: 20px;
}
h2 {
color: #764ba2;
margin: 30px 0 15px;
border-left: 4px solid #764ba2;
padding-left: 15px;
}
.feature-list {
background: #f8f9fa;
padding: 20px;
border: 2px solid #ddd;
margin: 15px 0;
border-radius: 10px;
}
.feature-list h3 {
color: #667eea;
margin-bottom: 10px;
}
.feature-item {
background: white;
padding: 15px;
margin: 10px 0;
border-left: 4px solid #667eea;
}
.info-table {
width: 100%;
border-collapse: collapse;
margin: 20px 0;
}
.info-table th,
.info-table td {
padding: 12px;
text-align: left;
border: 1px solid #ddd;
}
.info-table th {
background: #667eea;
color: white;
}
</style>
</head>
<body>
<div class="container">
<h1>需求分析</h1>
<h2>功能需求</h2>
<div class="feature-list">
<h3>🛍️ 商品管理</h3>
<div class="feature-item">
<strong>功能:</strong>
<ul>
<li>商品发布、编辑、删除</li>
<li>商品分类和标签</li>
<li>商品图片和视频</li>
<li>商品规格(SKU)</li>
<li>库存管理</li>
<li>商品排序和推荐</li>
</ul>
</div>
</div>
<div class="feature-list">
<h3>🛒 购物车</h3>
<div class="feature-item">
<strong>功能:</strong>
<ul>
<li>添加商品到购物车</li>
<li>修改商品数量</li>
<li>删除购物车商品</li>
<li>选择商品规格</li>
<li>计算总价</li>
<li>保存购物车状态</li>
</ul>
</div>
</div>
<div class="feature-list">
<h3>📦 订单管理</h3>
<div class="feature-item">
<strong>功能:</strong>
<ul>
<li>创建订单</li>
<li>订单状态管理</li>
<li>物流跟踪</li>
<li>订单查询</li>
<li>退款退货</li>
<li>订单导出</li>
</ul>
</div>
</div>
<div class="feature-list">
<h3>💳 支付系统</h3>
<div class="feature-item">
<strong>功能:</strong>
<ul>
<li>多种支付方式</li>
<li>支付状态回调</li>
<li>支付安全验证</li>
<li>退款处理</li>
<li>支付记录</li>
</ul>
</div>
</div>
<div class="feature-list">
<h3>👤 用户管理</h3>
<div class="feature-item">
<strong>功能:</strong>
<ul>
<li>用户注册和登录</li>
<li>收货地址管理</li>
<li>订单历史</li>
<li>收藏夹</li>
<li>用户等级</li>
</ul>
</div>
</div>
<h2>非功能需求</h2>
<table class="info-table">
<thead>
<tr>
<th>需求类型</th>
<th>具体要求</th>
<th>优先级</th>
</tr>
</thead>
<tbody>
<tr>
<td>性能</td>
<td>页面加载 < 2秒,支持高并发</td>
<td>高</td>
</tr>
<tr>
<td>安全</td>
<td>支付安全,数据加密,防攻击</td>
<td>高</td>
</tr>
<tr>
<td>可用性</td>
<td>响应式设计,移动端优先</td>
<td>高</td>
</tr>
<tr>
<td>可扩展性</td>
<td>支持横向扩展,微服务架构</td>
<td>中</td>
</tr>
<tr>
<td>可靠性</td>
<td>99.9%可用性,数据备份</td>
<td>高</td>
</tr>
</tbody>
</table>
<div style="background: #fff3cd; padding: 15px; border-radius: 5px; margin-top: 20px;">
<strong>东巴文提示:</strong>电商系统要特别注意安全性和性能。支付环节必须安全可靠,高并发场景要做好性能优化。
</div>
</div>
</body>
</html>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>数据库设计 - 东巴文</title>
<style>
body {
font-family: 'Segoe UI', sans-serif;
padding: 20px;
background: #f5f5f5;
}
.container {
max-width: 800px;
margin: 0 auto;
background: white;
padding: 30px;
border-radius: 10px;
}
h1 {
color: #667eea;
margin-bottom: 20px;
}
h2 {
color: #764ba2;
margin: 30px 0 15px;
border-left: 4px solid #764ba2;
padding-left: 15px;
}
.db-schema {
background: #f8f9fa;
padding: 20px;
border: 2px solid #ddd;
margin: 15px 0;
border-radius: 10px;
}
.db-schema h3 {
color: #667eea;
margin-bottom: 10px;
}
.code-block {
background: #2d2d2d;
color: #f8f8f2;
padding: 15px;
border-radius: 5px;
overflow-x: auto;
margin: 10px 0;
}
</style>
</head>
<body>
<div class="container">
<h1>数据库设计</h1>
<h2>数据模型</h2>
<div class="db-schema">
<h3>商品表(Products)</h3>
<div class="code-block">
<pre>
{
"_id": ObjectId,
"name": String, // 商品名称
"description": String, // 商品描述
"price": Number, // 价格
"original_price": Number, // 原价
"category_id": ObjectId, // 分类ID
"brand": String, // 品牌
"images": [String], // 商品图片
"main_image": String, // 主图
"skus": [{ // SKU列表
"sku_id": String,
"specs": { // 规格
"颜色": "红色",
"尺寸": "L"
},
"price": Number,
"stock": Number,
"sku_code": String
}],
"status": String, // 状态(on_sale, off_sale)
"sales_count": Number, // 销量
"view_count": Number, // 浏览量
"tags": [String], // 标签
"created_at": Date,
"updated_at": Date
}
</pre>
</div>
</div>
<div class="db-schema">
<h3>订单表(Orders)</h3>
<div class="code-block">
<pre>
{
"_id": ObjectId,
"order_no": String, // 订单号
"user_id": ObjectId, // 用户ID
"items": [{ // 订单商品
"product_id": ObjectId,
"sku_id": String,
"product_name": String,
"sku_specs": Object,
"price": Number,
"quantity": Number,
"total": Number
}],
"total_amount": Number, // 订单总额
"discount_amount": Number, // 优惠金额
"pay_amount": Number, // 实付金额
"status": String, // 订单状态
"payment_method": String, // 支付方式
"payment_status": String, // 支付状态
"payment_time": Date, // 支付时间
"shipping_address": { // 收货地址
"name": String,
"phone": String,
"province": String,
"city": String,
"district": String,
"address": String
},
"shipping_method": String, // 配送方式
"shipping_no": String, // 物流单号
"shipping_status": String, // 物流状态
"created_at": Date,
"updated_at": Date
}
</pre>
</div>
</div>
<div class="db-schema">
<h3>购物车表(Carts)</h3>
<div class="code-block">
<pre>
{
"_id": ObjectId,
"user_id": ObjectId, // 用户ID
"items": [{ // 购物车商品
"product_id": ObjectId,
"sku_id": String,
"quantity": Number,
"selected": Boolean, // 是否选中
"added_at": Date
}],
"created_at": Date,
"updated_at": Date
}
</pre>
</div>
</div>
<div class="db-schema">
<h3>用户表(Users)</h3>
<div class="code-block">
<pre>
{
"_id": ObjectId,
"username": String,
"email": String,
"phone": String,
"password": String, // 加密密码
"avatar": String,
"addresses": [{ // 收货地址
"name": String,
"phone": String,
"province": String,
"city": String,
"district": String,
"address": String,
"is_default": Boolean
}],
"favorites": [ObjectId], // 收藏商品
"level": Number, // 用户等级
"points": Number, // 积分
"created_at": Date,
"updated_at": Date
}
</pre>
</div>
</div>
<h2>索引设计</h2>
<ul>
<li><strong>商品表:</strong> name(全文索引), category_id, brand, status</li>
<li><strong>订单表:</strong> order_no(唯一), user_id, status, created_at</li>
<li><strong>购物车表:</strong> user_id(唯一)</li>
<li><strong>用户表:</strong> username(唯一), email(唯一), phone(唯一)</li>
</ul>
<div style="background: #fff3cd; padding: 15px; border-radius: 5px; margin-top: 20px;">
<strong>东巴文提示:</strong>电商数据库设计要考虑事务一致性。订单创建、库存扣减、支付状态更新等操作要保证原子性,避免数据不一致。
</div>
</div>
</body>
</html>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>商品展示 - 东巴文</title>
<style>
body {
font-family: 'Segoe UI', sans-serif;
padding: 20px;
background: #f5f5f5;
}
.container {
max-width: 800px;
margin: 0 auto;
background: white;
padding: 30px;
border-radius: 10px;
}
h1 {
color: #667eea;
margin-bottom: 20px;
}
h2 {
color: #764ba2;
margin: 30px 0 15px;
border-left: 4px solid #764ba2;
padding-left: 15px;
}
.product-demo {
background: #f8f9fa;
padding: 20px;
border: 2px solid #ddd;
margin: 15px 0;
border-radius: 10px;
}
.product-demo h3 {
color: #667eea;
margin-bottom: 10px;
}
.code-block {
background: #2d2d2d;
color: #f8f8f2;
padding: 15px;
border-radius: 5px;
overflow-x: auto;
margin: 10px 0;
}
</style>
</head>
<body>
<div class="container">
<h1>商品展示</h1>
<h2>商品列表页</h2>
<div class="product-demo">
<h3>HTML结构</h3>
<div class="code-block">
<pre>
<!-- 商品列表 -->
<div class="product-list">
<!-- 筛选栏 -->
<div class="filter-bar">
<div class="filter-group">
<label>分类:</label>
<select id="category-filter">
<option value="">全部分类</option>
<option value="electronics">电子产品</option>
<option value="clothing">服装</option>
</select>
</div>
<div class="filter-group">
<label>价格:</label>
<input type="number" id="min-price" placeholder="最低价">
<span>-</span>
<input type="number" id="max-price" placeholder="最高价">
</div>
<div class="filter-group">
<label>排序:</label>
<select id="sort-filter">
<option value="default">默认排序</option>
<option value="price-asc">价格从低到高</option>
<option value="price-desc">价格从高到低</option>
<option value="sales">销量优先</option>
</select>
</div>
</div>
<!-- 商品网格 -->
<div class="product-grid">
<div class="product-card">
<div class="product-image">
<img src="product.jpg" alt="商品图片">
<span class="product-badge">热卖</span>
</div>
<div class="product-info">
<h3 class="product-name">商品名称</h3>
<p class="product-desc">商品描述...</p>
<div class="product-price">
<span class="current-price">¥99.00</span>
<span class="original-price">¥199.00</span>
</div>
<div class="product-meta">
<span class="sales">已售 1000</span>
<span class="rating">⭐ 4.8</span>
</div>
</div>
</div>
</div>
<!-- 分页 -->
<div class="pagination">
<button class="prev-btn">上一页</button>
<span class="page-info">第 1 页 / 共 10 页</span>
<button class="next-btn">下一页</button>
</div>
</div>
</pre>
</div>
</div>
<h2>商品详情页</h2>
<div class="product-demo">
<h3>HTML结构</h3>
<div class="code-block">
<pre>
<!-- 商品详情 -->
<div class="product-detail">
<!-- 商品图片轮播 -->
<div class="product-gallery">
<div class="main-image">
<img id="main-image" src="product-1.jpg" alt="商品主图">
</div>
<div class="thumbnail-list">
<img src="product-1.jpg" class="thumbnail active">
<img src="product-2.jpg" class="thumbnail">
<img src="product-3.jpg" class="thumbnail">
</div>
</div>
<!-- 商品信息 -->
<div class="product-info">
<h1 class="product-title">商品标题</h1>
<p class="product-subtitle">商品副标题</p>
<div class="price-section">
<span class="label">价格:</span>
<span class="current-price">¥99.00</span>
<span class="original-price">¥199.00</span>
</div>
<!-- 规格选择 -->
<div class="specs-section">
<div class="spec-group">
<span class="label">颜色:</span>
<div class="spec-options">
<button class="spec-btn active">红色</button>
<button class="spec-btn">蓝色</button>
<button class="spec-btn">黑色</button>
</div>
</div>
<div class="spec-group">
<span class="label">尺寸:</span>
<div class="spec-options">
<button class="spec-btn">S</button>
<button class="spec-btn active">M</button>
<button class="spec-btn">L</button>
</div>
</div>
</div>
<!-- 数量选择 -->
<div class="quantity-section">
<span class="label">数量:</span>
<div class="quantity-control">
<button class="minus-btn">-</button>
<input type="number" value="1" min="1" max="99">
<button class="plus-btn">+</button>
</div>
<span class="stock-info">库存: 999件</span>
</div>
<!-- 操作按钮 -->
<div class="action-buttons">
<button class="add-cart-btn">加入购物车</button>
<button class="buy-now-btn">立即购买</button>
</div>
</div>
</div>
</pre>
</div>
</div>
<h2>图片轮播</h2>
<div class="product-demo">
<h3>JavaScript实现</h3>
<div class="code-block">
<pre>
// 图片轮播
class ImageGallery {
constructor() {
this.mainImage = document.getElementById('main-image');
this.thumbnails = document.querySelectorAll('.thumbnail');
this.currentIndex = 0;
this.init();
}
init() {
// 缩略图点击
this.thumbnails.forEach((thumb, index) => {
thumb.addEventListener('click', () => {
this.switchImage(index);
});
});
// 鼠标悬停放大
this.mainImage.addEventListener('mouseenter', () => {
this.enableZoom();
});
this.mainImage.addEventListener('mouseleave', () => {
this.disableZoom();
});
}
switchImage(index) {
// 更新主图
this.mainImage.src = this.thumbnails[index].src;
// 更新缩略图状态
this.thumbnails.forEach(t => t.classList.remove('active'));
this.thumbnails[index].classList.add('active');
this.currentIndex = index;
}
enableZoom() {
// 实现图片放大镜效果
// ...
}
disableZoom() {
// 关闭放大镜效果
// ...
}
}
// 初始化
new ImageGallery();
</pre>
</div>
</div>
<div style="background: #fff3cd; padding: 15px; border-radius: 5px; margin-top: 20px;">
<strong>东巴文提示:</strong>商品展示要注重用户体验。清晰的图片、详细的信息、便捷的筛选,让用户快速找到心仪的商品。
</div>
</div>
</body>
</html>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>购物车实现 - 东巴文</title>
<style>
body {
font-family: 'Segoe UI', sans-serif;
padding: 20px;
background: #f5f5f5;
}
.container {
max-width: 800px;
margin: 0 auto;
background: white;
padding: 30px;
border-radius: 10px;
}
h1 {
color: #667eea;
margin-bottom: 20px;
}
h2 {
color: #764ba2;
margin: 30px 0 15px;
border-left: 4px solid #764ba2;
padding-left: 15px;
}
.cart-demo {
background: #f8f9fa;
padding: 20px;
border: 2px solid #ddd;
margin: 15px 0;
border-radius: 10px;
}
.cart-demo h3 {
color: #667eea;
margin-bottom: 10px;
}
.code-block {
background: #2d2d2d;
color: #f8f8f2;
padding: 15px;
border-radius: 5px;
overflow-x: auto;
margin: 10px 0;
}
</style>
</head>
<body>
<div class="container">
<h1>购物车实现</h1>
<h2>购物车页面</h2>
<div class="cart-demo">
<h3>HTML结构</h3>
<div class="code-block">
<pre>
<!-- 购物车 -->
<div class="shopping-cart">
<!-- 购物车列表 -->
<div class="cart-list">
<!-- 购物车项 -->
<div class="cart-item">
<div class="item-checkbox">
<input type="checkbox" checked>
</div>
<div class="item-image">
<img src="product.jpg" alt="商品图片">
</div>
<div class="item-info">
<h3 class="item-name">商品名称</h3>
<p class="item-specs">颜色: 红色 | 尺寸: L</p>
</div>
<div class="item-price">
<span class="price">¥99.00</span>
</div>
<div class="item-quantity">
<button class="minus-btn">-</button>
<input type="number" value="1" min="1">
<button class="plus-btn">+</button>
</div>
<div class="item-subtotal">
<span class="subtotal">¥99.00</span>
</div>
<div class="item-actions">
<button class="delete-btn">删除</button>
<button class="favorite-btn">移入收藏</button>
</div>
</div>
</div>
<!-- 结算栏 -->
<div class="cart-footer">
<div class="select-all">
<input type="checkbox" id="select-all">
<label for="select-all">全选</label>
</div>
<div class="cart-summary">
<span class="selected-count">已选 <strong>2</strong> 件</span>
<span class="total-price">合计: <strong>¥198.00</strong></span>
</div>
<button class="checkout-btn">去结算</button>
</div>
</div>
</pre>
</div>
</div>
<h2>购物车逻辑</h2>
<div class="cart-demo">
<h3>JavaScript实现</h3>
<div class="code-block">
<pre>
// 购物车管理
class ShoppingCart {
constructor() {
this.items = [];
this.init();
}
init() {
this.loadCart();
this.bindEvents();
}
// 加载购物车数据
async loadCart() {
try {
const response = await fetch('/api/cart', {
headers: {
'Authorization': `Bearer ${getToken()}`
}
});
const result = await response.json();
if (result.success) {
this.items = result.data.items;
this.render();
}
} catch (error) {
console.error('加载购物车失败:', error);
}
}
// 添加商品到购物车
async addToCart(productId, skuId, quantity = 1) {
try {
const response = await fetch('/api/cart/items', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${getToken()}`
},
body: JSON.stringify({
product_id: productId,
sku_id: skuId,
quantity: quantity
})
});
const result = await response.json();
if (result.success) {
this.items = result.data.items;
this.render();
this.showNotification('添加成功');
} else {
this.showNotification(result.message, 'error');
}
} catch (error) {
console.error('添加到购物车失败:', error);
}
}
// 更新商品数量
async updateQuantity(itemId, quantity) {
try {
const response = await fetch(`/api/cart/items/${itemId}`, {
method: 'PUT',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${getToken()}`
},
body: JSON.stringify({ quantity })
});
const result = await response.json();
if (result.success) {
this.items = result.data.items;
this.render();
}
} catch (error) {
console.error('更新数量失败:', error);
}
}
// 删除商品
async removeItem(itemId) {
if (!confirm('确定要删除这个商品吗?')) return;
try {
const response = await fetch(`/api/cart/items/${itemId}`, {
method: 'DELETE',
headers: {
'Authorization': `Bearer ${getToken()}`
}
});
const result = await response.json();
if (result.success) {
this.items = result.data.items;
this.render();
}
} catch (error) {
console.error('删除商品失败:', error);
}
}
// 计算总价
calculateTotal() {
const selectedItems = this.items.filter(item => item.selected);
const total = selectedItems.reduce((sum, item) => {
return sum + (item.price * item.quantity);
}, 0);
return total.toFixed(2);
}
// 渲染购物车
render() {
const cartList = document.querySelector('.cart-list');
const totalPrice = document.querySelector('.total-price strong');
const selectedCount = document.querySelector('.selected-count strong');
// 渲染商品列表
cartList.innerHTML = this.items.map(item => `
<div class="cart-item" data-id="${item._id}">
<!-- 商品信息 -->
</div>
`).join('');
// 更新总价
totalPrice.textContent = `¥${this.calculateTotal()}`;
// 更新选中数量
const selectedItems = this.items.filter(item => item.selected);
selectedCount.textContent = selectedItems.length;
}
// 绑定事件
bindEvents() {
// 全选
document.getElementById('select-all').addEventListener('change', (e) => {
this.toggleSelectAll(e.target.checked);
});
// 数量增减
document.querySelector('.cart-list').addEventListener('click', (e) => {
const item = e.target.closest('.cart-item');
const itemId = item.dataset.id;
if (e.target.classList.contains('minus-btn')) {
this.updateQuantity(itemId, -1);
} else if (e.target.classList.contains('plus-btn')) {
this.updateQuantity(itemId, 1);
} else if (e.target.classList.contains('delete-btn')) {
this.removeItem(itemId);
}
});
}
}
// 初始化
const cart = new ShoppingCart();
</pre>
</div>
</div>
<h2>购物车同步</h2>
<div class="cart-demo">
<h3>本地存储同步</h3>
<div class="code-block">
<pre>
// 购物车本地存储
class CartStorage {
constructor() {
this.storageKey = 'shopping_cart';
}
// 获取本地购物车
getLocalCart() {
const cartData = localStorage.getItem(this.storageKey);
return cartData ? JSON.parse(cartData) : [];
}
// 保存到本地
saveLocalCart(items) {
localStorage.setItem(this.storageKey, JSON.stringify(items));
}
// 登录后同步
async syncAfterLogin() {
const localItems = this.getLocalCart();
if (localItems.length > 0) {
try {
// 合并本地购物车到服务器
const response = await fetch('/api/cart/sync', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${getToken()}`
},
body: JSON.stringify({ items: localItems })
});
const result = await response.json();
if (result.success) {
// 清空本地购物车
localStorage.removeItem(this.storageKey);
return result.data.items;
}
} catch (error) {
console.error('同步购物车失败:', error);
}
}
return [];
}
}
</pre>
</div>
</div>
<div style="background: #fff3cd; padding: 15px; border-radius: 5px; margin-top: 20px;">
<strong>东巴文提示:</strong>购物车要支持未登录状态。使用本地存储保存购物车数据,登录后自动同步到服务器,提升用户体验。
</div>
</div>
</body>
</html>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>订单处理 - 东巴文</title>
<style>
body {
font-family: 'Segoe UI', sans-serif;
padding: 20px;
background: #f5f5f5;
}
.container {
max-width: 800px;
margin: 0 auto;
background: white;
padding: 30px;
border-radius: 10px;
}
h1 {
color: #667eea;
margin-bottom: 20px;
}
h2 {
color: #764ba2;
margin: 30px 0 15px;
border-left: 4px solid #764ba2;
padding-left: 15px;
}
.order-demo {
background: #f8f9fa;
padding: 20px;
border: 2px solid #ddd;
margin: 15px 0;
border-radius: 10px;
}
.order-demo h3 {
color: #667eea;
margin-bottom: 10px;
}
.code-block {
background: #2d2d2d;
color: #f8f8f2;
padding: 15px;
border-radius: 5px;
overflow-x: auto;
margin: 10px 0;
}
</style>
</head>
<body>
<div class="container">
<h1>订单处理</h1>
<h2>订单状态流转</h2>
<div class="order-demo">
<h3>状态机设计</h3>
<div class="code-block">
<pre>
订单状态流转:
1. 待支付 (pending_payment)
↓ 用户支付
2. 待发货 (pending_shipment)
↓ 商家发货
3. 待收货 (pending_receipt)
↓ 用户确认收货
4. 已完成 (completed)
特殊情况:
- 取消订单 (cancelled)
- 退款中 (refunding)
- 已退款 (refunded)
</pre>
</div>
</div>
<h2>创建订单</h2>
<div class="order-demo">
<h3>后端实现</h3>
<div class="code-block">
<pre>
// 创建订单
app.post('/api/orders', authMiddleware, async (req, res) => {
const session = await mongoose.startSession();
session.startTransaction();
try {
const { items, shipping_address, payment_method } = req.body;
// 1. 验证商品和库存
const orderItems = [];
for (const item of items) {
const product = await Product.findById(item.product_id).session(session);
if (!product) {
throw new Error('商品不存在');
}
const sku = product.skus.find(s => s.sku_id === item.sku_id);
if (!sku || sku.stock < item.quantity) {
throw new Error('库存不足');
}
orderItems.push({
product_id: product._id,
sku_id: item.sku_id,
product_name: product.name,
sku_specs: sku.specs,
price: sku.price,
quantity: item.quantity,
total: sku.price * item.quantity
});
}
// 2. 计算订单金额
const totalAmount = orderItems.reduce((sum, item) => sum + item.total, 0);
// 3. 创建订单
const order = await Order.create([{
order_no: generateOrderNo(),
user_id: req.user.id,
items: orderItems,
total_amount: totalAmount,
pay_amount: totalAmount,
status: 'pending_payment',
payment_method,
shipping_address
}], { session });
// 4. 扣减库存
for (const item of items) {
await Product.updateOne(
{ _id: item.product_id, 'skus.sku_id': item.sku_id },
{ $inc: { 'skus.$.stock': -item.quantity } },
{ session }
);
}
// 5. 清空购物车
await Cart.updateOne(
{ user_id: req.user.id },
{ $pull: { items: { product_id: { $in: items.map(i => i.product_id) } } } },
{ session }
);
await session.commitTransaction();
res.json({
success: true,
data: {
order: order[0]
}
});
} catch (error) {
await session.abortTransaction();
res.status(400).json({
success: false,
message: error.message
});
} finally {
session.endSession();
}
});
</pre>
</div>
</div>
<h2>订单查询</h2>
<div class="order-demo">
<h3>前端实现</h3>
<div class="code-block">
<pre>
<!-- 订单列表 -->
<div class="order-list">
<!-- 订单筛选 -->
<div class="order-tabs">
<button class="tab-btn active" data-status="all">全部订单</button>
<button class="tab-btn" data-status="pending_payment">待支付</button>
<button class="tab-btn" data-status="pending_shipment">待发货</button>
<button class="tab-btn" data-status="pending_receipt">待收货</button>
</div>
<!-- 订单项 -->
<div class="order-item">
<div class="order-header">
<span class="order-no">订单号: 202401010001</span>
<span class="order-status">待支付</span>
</div>
<div class="order-products">
<div class="product-item">
<img src="product.jpg" alt="商品">
<div class="product-info">
<h4>商品名称</h4>
<p>规格: 红色 L</p>
</div>
<div class="product-price">
<span>¥99.00</span>
<span>x1</span>
</div>
</div>
</div>
<div class="order-footer">
<div class="order-total">
共 1 件商品, 合计: <strong>¥99.00</strong>
</div>
<div class="order-actions">
<button class="cancel-btn">取消订单</button>
<button class="pay-btn">立即支付</button>
</div>
</div>
</div>
</div>
<script>
// 加载订单列表
async function loadOrders(status = 'all') {
try {
const url = status === 'all'
? '/api/orders'
: `/api/orders?status=${status}`;
const response = await fetch(url, {
headers: {
'Authorization': `Bearer ${getToken()}`
}
});
const result = await response.json();
if (result.success) {
renderOrders(result.data.orders);
}
} catch (error) {
console.error('加载订单失败:', error);
}
}
// 取消订单
async function cancelOrder(orderId) {
if (!confirm('确定要取消这个订单吗?')) return;
try {
const response = await fetch(`/api/orders/${orderId}/cancel`, {
method: 'PUT',
headers: {
'Authorization': `Bearer ${getToken()}`
}
});
const result = await response.json();
if (result.success) {
loadOrders();
} else {
alert(result.message);
}
} catch (error) {
console.error('取消订单失败:', error);
}
}
</script>
</pre>
</div>
</div>
<h2>物流跟踪</h2>
<div class="order-demo">
<h3>物流信息展示</h3>
<div class="code-block">
<pre>
<!-- 物流跟踪 -->
<div class="shipping-tracking">
<div class="tracking-header">
<h3>物流信息</h3>
<p>物流公司: 顺丰快递</p>
<p>运单号: SF1234567890</p>
</div>
<div class="tracking-timeline">
<div class="timeline-item active">
<div class="timeline-dot"></div>
<div class="timeline-content">
<p class="timeline-title">已签收</p>
<p class="timeline-desc">您的快递已签收,签收人: 本人</p>
<p class="timeline-time">2024-01-05 14:30:00</p>
</div>
</div>
<div class="timeline-item">
<div class="timeline-dot"></div>
<div class="timeline-content">
<p class="timeline-title">派送中</p>
<p class="timeline-desc">快递员正在派送中</p>
<p class="timeline-time">2024-01-05 09:00:00</p>
</div>
</div>
<div class="timeline-item">
<div class="timeline-dot"></div>
<div class="timeline-content">
<p class="timeline-title">运输中</p>
<p class="timeline-desc">快件已到达北京分拨中心</p>
<p class="timeline-time">2024-01-04 18:00:00</p>
</div>
</div>
</div>
</div>
</pre>
</div>
</div>
<div style="background: #fff3cd; padding: 15px; border-radius: 5px; margin-top: 20px;">
<strong>东巴文提示:</strong>订单处理要保证数据一致性。使用数据库事务确保订单创建、库存扣减、购物车清空等操作的原子性,避免数据不一致问题。
</div>
</div>
</body>
</html>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>支付集成 - 东巴文</title>
<style>
body {
font-family: 'Segoe UI', sans-serif;
padding: 20px;
background: #f5f5f5;
}
.container {
max-width: 800px;
margin: 0 auto;
background: white;
padding: 30px;
border-radius: 10px;
}
h1 {
color: #667eea;
margin-bottom: 20px;
}
h2 {
color: #764ba2;
margin: 30px 0 15px;
border-left: 4px solid #764ba2;
padding-left: 15px;
}
.payment-demo {
background: #f8f9fa;
padding: 20px;
border: 2px solid #ddd;
margin: 15px 0;
border-radius: 10px;
}
.payment-demo h3 {
color: #667eea;
margin-bottom: 10px;
}
.code-block {
background: #2d2d2d;
color: #f8f8f2;
padding: 15px;
border-radius: 5px;
overflow-x: auto;
margin: 10px 0;
}
</style>
</head>
<body>
<div class="container">
<h1>支付集成</h1>
<h2>支付方式选择</h2>
<div class="payment-demo">
<h3>HTML结构</h3>
<div class="code-block">
<pre>
<!-- 支付方式选择 -->
<div class="payment-methods">
<h3>选择支付方式</h3>
<div class="method-list">
<label class="method-item">
<input type="radio" name="payment" value="alipay" checked>
<img src="alipay-logo.png" alt="支付宝">
<span>支付宝</span>
</label>
<label class="method-item">
<input type="radio" name="payment" value="wechat">
<img src="wechat-logo.png" alt="微信支付">
<span>微信支付</span>
</label>
<label class="method-item">
<input type="radio" name="payment" value="balance">
<span class="icon">💰</span>
<span>余额支付</span>
<span class="balance">(余额: ¥100.00)</span>
</label>
</div>
<div class="payment-amount">
<span>支付金额:</span>
<strong class="amount">¥99.00</strong>
</div>
<button class="pay-btn" onclick="initiatePayment()">确认支付</button>
</div>
</pre>
</div>
</div>
<h2>支付宝集成</h2>
<div class="payment-demo">
<h3>后端实现</h3>
<div class="code-block">
<pre>
const AlipaySdk = require('alipay-sdk').default;
const alipaySdk = new AlipaySdk({
appId: process.env.ALIPAY_APP_ID,
privateKey: process.env.ALIPAY_PRIVATE_KEY,
alipayPublicKey: process.env.ALIPAY_PUBLIC_KEY
});
// 创建支付宝订单
app.post('/api/payment/alipay', authMiddleware, async (req, res) => {
try {
const { order_id } = req.body;
// 查询订单
const order = await Order.findById(order_id);
if (!order || order.user_id.toString() !== req.user.id) {
return res.status(400).json({
success: false,
message: '订单不存在'
});
}
if (order.status !== 'pending_payment') {
return res.status(400).json({
success: false,
message: '订单状态不正确'
});
}
// 创建支付宝订单
const result = alipaySdk.pageExec(
'alipay.trade.page.pay',
{
notify_url: 'https://example.com/api/payment/alipay/notify',
return_url: 'https://example.com/payment/success',
bizContent: {
out_trade_no: order.order_no,
product_code: 'FAST_INSTANT_TRADE_PAY',
total_amount: order.pay_amount.toFixed(2),
subject: `订单 ${order.order_no}`,
body: '商品描述'
}
}
);
res.json({
success: true,
data: {
payment_url: result
}
});
} catch (error) {
console.error('创建支付订单失败:', error);
res.status(500).json({
success: false,
message: '创建支付订单失败'
});
}
});
// 支付宝回调
app.post('/api/payment/alipay/notify', async (req, res) => {
try {
// 验证签名
const signVerified = alipaySdk.checkNotifySign(req.body);
if (!signVerified) {
return res.send('fail');
}
const orderNo = req.body.out_trade_no;
const tradeStatus = req.body.trade_status;
// 支付成功
if (tradeStatus === 'TRADE_SUCCESS' || tradeStatus === 'TRADE_FINISHED') {
// 更新订单状态
await Order.findOneAndUpdate(
{ order_no: orderNo },
{
status: 'pending_shipment',
payment_status: 'paid',
payment_time: new Date(),
transaction_id: req.body.trade_no
}
);
// 发送支付成功通知
// ...
}
res.send('success');
} catch (error) {
console.error('处理支付回调失败:', error);
res.send('fail');
}
});
</pre>
</div>
</div>
<h2>微信支付集成</h2>
<div class="payment-demo">
<h3>后端实现</h3>
<div class="code-block">
<pre>
const Wechatpay = require('wechatpay-node-v3');
const pay = new Wechatpay({
appid: process.env.WECHAT_APP_ID,
mchid: process.env.WECHAT_MCH_ID,
publicKey: Buffer.from(process.env.WECHAT_PUBLIC_KEY),
privateKey: Buffer.from(process.env.WECHAT_PRIVATE_KEY)
});
// 创建微信支付订单
app.post('/api/payment/wechat', authMiddleware, async (req, res) => {
try {
const { order_id } = req.body;
const order = await Order.findById(order_id);
if (!order || order.user_id.toString() !== req.user.id) {
return res.status(400).json({
success: false,
message: '订单不存在'
});
}
// 创建微信支付订单
const result = await pay.transactions_native({
description: `订单 ${order.order_no}`,
out_trade_no: order.order_no,
notify_url: 'https://example.com/api/payment/wechat/notify',
amount: {
total: Math.round(order.pay_amount * 100), // 单位:分
currency: 'CNY'
}
});
res.json({
success: true,
data: {
qr_code: result.code_url
}
});
} catch (error) {
console.error('创建微信支付订单失败:', error);
res.status(500).json({
success: false,
message: '创建支付订单失败'
});
}
});
// 微信支付回调
app.post('/api/payment/wechat/notify', async (req, res) => {
try {
// 验证签名
const signature = req.headers['wechatpay-signature'];
const timestamp = req.headers['wechatpay-timestamp'];
const nonce = req.headers['wechatpay-nonce'];
// 解密通知数据
const decrypted = pay.decipher_gcm(
req.body.resource,
process.env.WECHAT_API_V3_KEY
);
const { out_trade_no, transaction_id, trade_state } = decrypted;
// 支付成功
if (trade_state === 'SUCCESS') {
await Order.findOneAndUpdate(
{ order_no: out_trade_no },
{
status: 'pending_shipment',
payment_status: 'paid',
payment_time: new Date(),
transaction_id
}
);
}
res.json({ code: 'SUCCESS', message: '成功' });
} catch (error) {
console.error('处理微信支付回调失败:', error);
res.json({ code: 'FAIL', message: '失败' });
}
});
</pre>
</div>
</div>
<h2>支付安全</h2>
<div class="payment-demo">
<h3>安全措施</h3>
<ul>
<li>✅ 使用HTTPS加密传输</li>
<li>✅ 验证支付回调签名</li>
<li>✅ 防止重复支付</li>
<li>✅ 订单金额验证</li>
<li>✅ 支付超时处理</li>
<li>✅ 敏感信息加密存储</li>
</ul>
</div>
<div style="background: #fff3cd; padding: 15px; border-radius: 5px; margin-top: 20px;">
<strong>东巴文提示:</strong>支付集成要特别注意安全性。验证回调签名、防止重复支付、处理超时订单,确保资金安全。
</div>
</div>
</body>
</html>
东巴文(db-w.cn) 提醒:电商系统是最复杂的Web应用之一。从简单开始,逐步完善功能,特别注重安全性和性能。记住,好的电商网站应该让购物变得简单愉快。