普通视图

发现新文章,点击刷新页面。
今天 — 2025年12月6日首页

全栈项目:宠物用品购物系统及后台管理

作者 温暖全栈
2025年12月6日 16:20

基于Vue3和Node.js的宠物用品购物系统设计与实现

一、项目描述

随着互联网技术的快速发展和宠物经济的持续升温,宠物用品电商平台已成为宠物主人购买宠物用品的主要渠道。设计并实现了一个基于Vue3和Node.js的全栈宠物用品购物系统,该系统采用前后端分离架构,包含用户购物系统和后台管理系统两个子系统。

系统前端采用Vue 3框架,结合TypeScript、Pinia状态管理、Vue Router路由管理和Element UI Plus组件库,实现了响应式的用户界面和流畅的交互体验。后端采用Node.js和Express框架,使用MongoDB作为数据库,通过JWT实现用户身份认证,构建了RESTful风格的API接口。系统实现了用户注册登录、商品浏览搜索、购物车管理、订单处理、社交互动、后台管理等核心功能。

1. 项目截图

2. 技术栈

前端

  • Vue 3 + TypeScript
  • Vue Router 4 (路由管理)
  • Pinia (状态管理)
  • Element UI Plus (UI组件库)
  • Axios (HTTP请求)

后端

  • Node.js + Express (服务器框架)
  • MongoDB + Mongoose (数据库)
  • JWT (身份验证)
  • Multer (文件上传)
  • Bcryptjs (密码加密)

二、项目启动

前置要求

  • Node.js >= 16
  • pnpm >= 8
  • MongoDB >= 5.0

1.安装依赖

# 安装根目录依赖
pnpm install

2. 启动 MongoDB

确保 MongoDB 服务已启动并运行在 localhost:27017

3. 导入测试数据

pnpm run import

这将自动导入:

  • ✅ 4个测试用户(1个管理员 + 3个普通用户)
  • ✅ 完整的商品分类体系
  • ✅ 10个示例商品
  • ✅ 用户地址数据
  • ✅ 订单数据
  • ✅ 社交帖子数据

4. 启动开发服务器

pnpm run dev

启动后访问:

三、项目总体设计

1. 系统架构设计

1.1 架构模式选择

本系统采用前后端分离的架构模式,具有以下优势:

1. 职责分离

  • 前端专注于用户界面和交互体验
  • 后端专注于业务逻辑和数据处理
  • 前后端可以独立开发、测试、部署

2. 技术独立

  • 前端可以选择最适合的框架和技术
  • 后端可以选择最适合的语言和框架
  • 技术栈升级互不影响

3. 团队协作

  • 前端团队和后端团队可以并行开发
  • 通过API接口约定进行协作
  • 提高开发效率

4. 可扩展性

  • 前端和后端可以独立扩展
  • 支持多端应用(Web、移动端、小程序)
  • 便于向微服务架构演进
1.2 系统架构图
┌─────────────────────────────────────────────────────────┐
│                      客户端层                             │
│  ┌──────────────┐         ┌──────────────┐              │
│  │  用户系统     │         │  管理系统     │              │
│  │  (Vue 3)     │         │  (Vue 3)     │              │
│  └──────────────┘         └──────────────┘              │
└─────────────────────────────────────────────────────────┘
                          │
                          │ HTTP/HTTPS
                          │ RESTful API
                          ▼
┌─────────────────────────────────────────────────────────┐
│                      服务端层                             │
│  ┌──────────────────────────────────────────────────┐   │
│  │              Express 应用服务器                    │   │
│  │  ┌──────────┐  ┌──────────┐  ┌──────────┐       │   │
│  │  │ 路由层    │  │ 中间件层  │  │ 控制器层  │       │   │
│  │  └──────────┘  └──────────┘  └──────────┘       │   │
│  └──────────────────────────────────────────────────┘   │
└─────────────────────────────────────────────────────────┘
                          │
                          │ Mongoose ODM
                          ▼
┌─────────────────────────────────────────────────────────┐
│                      数据层                               │
│  ┌──────────────────────────────────────────────────┐   │
│  │              MongoDB 数据库                        │   │
│  │  ┌──────────┐  ┌──────────┐  ┌──────────┐       │   │
│  │  │ 用户集合  │  │ 商品集合  │  │ 订单集合  │       │   │
│  │  └──────────┘  └──────────┘  └──────────┘       │   │
│  └──────────────────────────────────────────────────┘   │
└─────────────────────────────────────────────────────────┘
1.3技术架构

前端架构

用户系统 / 管理系统
├── Vue 3 (核心框架)
├── TypeScript (类型系统)
├── Pinia (状态管理)
├── Vue Router (路由管理)
├── Element UI Plus (UI组件库)
├── Axios (HTTP客户端)
└── Vite (构建工具)

后端架构

API服务器
├── Node.js (运行环境)
├── Express (Web框架)
├── MongoDB (数据库)
├── Mongoose (ODM)
├── JWT (身份认证)
├── Bcrypt (密码加密)
└── Multer (文件上传)

2. 系统功能模块设计

用户购物系统功能模块

用户购物系统
├── 用户管理模块
│   ├── 用户注册
│   ├── 用户登录
│   ├── 个人信息管理
│   └── 收货地址管理
├── 商品展示模块
│   ├── 首页展示
│   ├── 商品列表
│   ├── 商品详情
│   └── 商品搜索
├── 购物功能模块
│   ├── 购物车管理
│   ├── 订单创建
│   ├── 订单查询
│   └── 订单评价
└── 社交功能模块
    ├── 动态发布
    ├── 动态浏览
    ├── 点赞评论
    └── 用户关注

后台管理系统功能模块

后台管理系统
├── 系统概览模块
│   ├── 数据统计
│   ├── 销售图表
│   └── 订单统计
├── 商品管理模块
│   ├── 商品列表
│   ├── 商品编辑
│   ├── 分类管理
│   └── 库存管理
├── 订单管理模块
│   ├── 订单列表
│   ├── 订单详情
│   ├── 发货处理
│   └── 退款处理
├── 用户管理模块
│   ├── 用户列表
│   ├── 用户详情
│   └── 用户状态管理
└── 数据统计模块
    ├── 销售统计
    ├── 商品排行
    └── 用户分析

3. 数据库设计

系统主要包含以下实体:

  1. 用户(User) :存储用户基本信息和统计数据
  2. 商品(Product) :存储商品信息、价格、库存等
  3. 订单(Order) :存储订单详情、支付信息、物流状态
  4. 动态(Post) :存储用户发布的社交动态
  5. 评论(Comment) :存储动态评论信息
  6. 地址(Address) :存储用户收货地址

实体关系:

  • 一个用户可以有多个订单(1:N)
  • 一个订单包含多个商品(N:M)
  • 一个用户可以发布多个动态(1:N)
  • 一个动态可以有多个评论(1:N)
  • 一个用户可以有多个收货地址(1:N)

四、用户认证模块设计

1. 功能流程图

用户注册流程:
用户填写信息 → 前端验证 → 发送注册请求 → 后端验证 → 密码加密 → 
存入数据库 → 生成 Token → 返回用户信息和 Token → 前端存储 Token → 
自动登录 → 跳转首页

用户登录流程:
用户输入账号密码 → 前端验证 → 发送登录请求 → 后端查询用户 → 
验证密码 → 生成 Token → 返回用户信息和 Token → 前端存储 Token → 
跳转首页

核心技术点:

  1. 密码加密(bcrypt)

bcrypt 是一种专门为密码存储设计的哈希算法,具有以下特点:

  • 加盐(Salt) :自动生成随机盐值,防止彩虹表攻击
  • 慢速哈希:计算速度慢,增加暴力破解难度
  • 自适应:可调整计算复杂度,应对硬件性能提升
// 密码加密实现
import bcrypt from 'bcryptjs';

// 注册时加密密码
const hashPassword = async (password) => {
  // 生成盐值,10 是成本因子(cost factor)
  // 成本因子越高,计算越慢,安全性越高
  const salt = await bcrypt.genSalt(10);
  
  // 使用盐值加密密码
  const hashedPassword = await bcrypt.hash(password, salt);
  
  return hashedPassword;
};

// 登录时验证密码
const verifyPassword = async (inputPassword, storedPassword) => {
  // bcrypt.compare 会自动提取盐值进行比较
  const isMatch = await bcrypt.compare(inputPassword, storedPassword);
  
  return isMatch;
};

为什么不使用 MD5 或 SHA?

  • MD5 和 SHA 是快速哈希算法,容易被暴力破解
  • 没有内置盐值机制,需要手动实现
  • bcrypt 专为密码设计,更安全

2. JWT 身份认证

JWT(JSON Web Token)是一种无状态的身份认证方案,特别适合前后端分离架构。

JWT 结构:

JWT = Header.Payload.Signature

Header(头部):
{
  "alg": "HS256",  // 签名算法
  "typ": "JWT"     // Token 类型
}

Payload(载荷):
{
  "userId": "64f8a1b2c3d4e5f6a7b8c9d0",
  "username": "testuser",
  "role": "user",
  "iat": 1704067200,  // 签发时间
  "exp": 1704672000   // 过期时间
}

Signature(签名):
HMACSHA256(
  base64UrlEncode(header) + "." + base64UrlEncode(payload),
  secret
)

JWT 工作流程:

1. 用户登录成功
   ↓
2. 服务器生成 JWT Token
   - 将用户信息编码到 Payload
   - 使用密钥签名,防止篡改
   ↓
3. 返回 Token 给客户端
   ↓
4. 客户端存储 Token(localStorage 或 sessionStorage)
   ↓
5. 后续请求携带 Token
   - 在 HTTP Header 中添加:Authorization: Bearer <token>6. 服务器验证 Token
   - 验证签名是否有效
   - 检查是否过期
   - 提取用户信息
   ↓
7. 处理业务逻辑

JWT 实现代码:

import jwt from 'jsonwebtoken';

// 密钥(生产环境应使用环境变量)
const JWT_SECRET = process.env.JWT_SECRET || 'your-secret-key';

// 生成 Token
const generateToken = (user) => {
  const payload = {
    userId: user._id,
    username: user.username,
    role: user.role
  };
  
  // 签发 Token,设置 7 天过期
  const token = jwt.sign(payload, JWT_SECRET, {
    expiresIn: '7d'
  });
  
  return token;
};

// 验证 Token 中间件
const authenticateToken = async (req, res, next) => {
  try {
    // 从请求头获取 Token
    const authHeader = req.headers.authorization;
    const token = authHeader && authHeader.split(' ')[1]; // Bearer <token>
    
    if (!token) {
      return res.status(401).json({
        success: false,
        message: '访问令牌缺失'
      });
    }
    
    // 验证 Token
    const decoded = jwt.verify(token, JWT_SECRET);
    
    // 查询用户是否存在且状态正常
    const user = await User.findById(decoded.userId);
    if (!user || user.status !== 'active') {
      return res.status(401).json({
        success: false,
        message: '用户不存在或已被禁用'
      });
    }
    
    // 将用户信息附加到请求对象
    req.user = {
      userId: decoded.userId,
      username: decoded.username,
      role: decoded.role
    };
    
    next();
  } catch (error) {
    if (error.name === 'TokenExpiredError') {
      return res.status(401).json({
        success: false,
        message: '令牌已过期,请重新登录'
      });
    }
    
    return res.status(401).json({
      success: false,
      message: '无效的访问令牌'
    });
  }
};

JWT vs Session 对比:

特性 JWT Session
存储位置 客户端 服务器
扩展性 好(无状态) 差(需要共享 Session)
性能 好(无需查询) 一般(需要查询 Session)
安全性 一般(Token 泄露风险) 好(服务器控制)
适用场景 前后端分离、微服务 传统 Web 应用

JWT 安全注意事项:

  1. 不要在 Payload 中存储敏感信息(密码、信用卡号等)
  2. 使用 HTTPS 传输,防止 Token 被窃取
  3. 设置合理的过期时间
  4. 实现 Token 刷新机制
  5. 考虑使用 Refresh Token 提升安全性
昨天 — 2025年12月5日首页

全栈项目:闲置二手交易系统(二)

作者 温暖全栈
2025年12月5日 15:08

四、系统架构图

1. 系统架构图

┌─────────────────────────────────────────────────────────┐
│                      用户浏览器                          │
│                    (Vue 3 + Vite)                       │
└────────────────┬────────────────────────────────────────┘
                 │
                 │ HTTP/WebSocket
                 │
┌────────────────▼────────────────────────────────────────┐
│                    Nginx (可选)                          │
│                   反向代理/负载均衡                       │
└────────────────┬────────────────────────────────────────┘
                 │
        ┌────────┴────────┐
        │                 │
┌───────▼──────┐  ┌──────▼────────┐
│  前端服务     │  │   后端服务     │
│  (Port 3000) │  │  (Port 5000)  │
│              │  │   Express     │
└──────────────┘  └───────┬───────┘
                          │
                  ┌───────┼───────┐
                  │       │       │
          ┌───────▼──┐ ┌──▼────┐ ┌▼────────┐
          │ MongoDB  │ │Socket │ │ 文件存储 │
          │ 数据库   │ │  IO   │ │ /uploads│
          └──────────┘ └───────┘ └─────────┘

2. 前端架构

目录结构

frontend/
├── src/
│   ├── components/          # 可复用组件
│   │   ├── admin/          # 管理后台组件
│   │   ├── AppNavbar.vue   # 导航栏
│   │   ├── ChatBox.vue     # 聊天框
│   │   ├── ChatList.vue    # 聊天列表
│   │   ├── ProductCard.vue # 商品卡片
│   │   └── ...
│   ├── views/              # 页面组件
│   │   ├── Home.vue        # 首页
│   │   ├── Login.vue       # 登录页
│   │   ├── Products.vue    # 商品列表
│   │   ├── ProductDetail.vue # 商品详情
│   │   ├── Chat.vue        # 聊天页
│   │   ├── Admin.vue       # 管理后台
│   │   └── ...
│   ├── stores/             # 状态管理
│   │   ├── user.ts         # 用户状态
│   │   └── product.ts      # 商品状态
│   ├── router/             # 路由配置
│   │   └── index.ts
│   ├── utils/              # 工具函数
│   │   ├── api.ts          # API封装
│   │   ├── validation.ts   # 表单验证
│   │   └── dateUtils.ts    # 日期工具
│   ├── types/              # TypeScript类型
│   │   └── index.ts
│   ├── test/               # 测试文件
│   ├── App.vue             # 根组件
│   └── main.ts             # 入口文件
├── public/                 # 静态资源
├── package.json
└── vite.config.ts

组件设计原则

  1. 单一职责:每个组件只负责一个功能
  2. 可复用性:通用组件抽离到components目录
  3. Props验证:使用TypeScript进行类型约束
  4. 事件命名:使用kebab-case命名自定义事件
  5. 样式隔离:使用scoped样式

Vue 3 核心特性深度解析

Composition API 的设计理念:

Vue 3 引入 Composition API 是为了解决 Options API 在大型项目中的几个痛点:

  1. 逻辑复用困难 - Options API 中相关逻辑分散在不同选项中
  2. 类型推导不友好 - TypeScript 支持不够完善
  3. 代码组织混乱 - 大组件中相关代码被迫分离
// 使用 <script setup> 语法 - 这是 Vue 3.2+ 的语法糖
<script setup lang="ts">
import { ref, computed, onMounted } from 'vue'

// 1. 响应式数据 - ref 用于基本类型
// ref 会返回一个响应式的引用对象,通过 .value 访问值
const count = ref(0)

// 2. 计算属性 - 自动追踪依赖,缓存结果
// 只有当依赖的响应式数据变化时才会重新计算
const doubleCount = computed(() => count.value * 2)

// 3. 生命周期钩子 - 在 setup 中直接调用
// 相比 Options API,名称前加了 'on' 前缀
onMounted(() => {
  console.log('组件已挂载')
  // 这里可以进行 DOM 操作、发起 API 请求等
})
</script>

响应式系统深入理解:

Vue 3 使用 Proxy 实现响应式,相比 Vue 2 的 Object.defineProperty 有以下优势:

  • 可以监听数组索引和长度变化
  • 可以监听对象属性的添加和删除
  • 性能更好,不需要递归遍历所有属性
// ref() - 用于基本类型的响应式
// 原理:将值包装在一个对象中,通过 .value 访问
const count = ref(0)
count.value++ // 触发响应式更新

// reactive() - 用于对象的响应式
// 原理:使用 Proxy 代理整个对象
const state = reactive({
  user: { name: 'John', age: 25 },
  products: []
})
state.user.name = 'Jane' // 直接修改,自动触发更新

// computed() - 计算属性
// 特点:1. 惰性求值 2. 缓存结果 3. 自动依赖追踪
const fullName = computed(() => {
  console.log('计算执行') // 只在依赖变化时执行
  return `${state.user.name} (${state.user.age})`
})

// watch() - 侦听器,用于执行副作用
// 可以侦听单个或多个响应式数据源
watch(count, (newVal, oldVal) => {
  console.log(`count 从 ${oldVal} 变为 ${newVal}`)
  // 可以在这里执行异步操作、API 调用等
})

// watchEffect() - 自动追踪依赖的侦听器
// 立即执行,自动收集依赖
watchEffect(() => {
  console.log(`当前 count: ${count.value}`)
  // 任何在这里使用的响应式数据变化都会触发重新执行
})

3. 后端架构

目录结构

backend/
├── models/                 # 数据模型
│   ├── User.js            # 用户模型
│   ├── Product.js         # 商品模型
│   ├── Order.js           # 订单模型
│   └── Message.js         # 消息模型
├── routes/                # 路由处理
│   ├── auth.js            # 认证路由
│   ├── products.js        # 商品路由
│   ├── orders.js          # 订单路由
│   ├── messages.js        # 消息路由
│   ├── users.js           # 用户路由
│   └── admin.js           # 管理员路由
├── middleware/            # 中间件
│   ├── auth.js            # 认证中间件
│   ├── admin.js           # 管理员中间件
│   └── upload.js          # 文件上传中间件
├── socket/                # Socket.IO处理
│   └── socketHandler.js   # Socket事件处理
├── utils/                 # 工具函数
│   └── helpers.js
├── scripts/               # 脚本文件
│   ├── init-admin.js      # 初始化管理员
│   └── import-data.js     # 导入测试数据
├── uploads/               # 文件上传目录
├── server.js              # 服务器入口
├── .env                   # 环境变量
└── package.json

后端技术知识点

Express 框架

基础路由:

const express = require('express')
const app = express()

// 中间件
app.use(express.json())
app.use(express.urlencoded({ extended: true }))

// 路由
app.get('/api/products', async (req, res) => {
  try {
    const products = await Product.find()
    res.json({ success: true, data: products })
  } catch (error) {
    res.status(500).json({ success: false, message: error.message })
  }
})

中间件系统:

// 日志中间件
app.use((req, res, next) => {
  console.log(`${req.method} ${req.url}`)
  next()
})

// 错误处理中间件
app.use((err, req, res, next) => {
  console.error(err.stack)
  res.status(500).json({ message: '服务器错误' })
})

4. 数据库设计

数据模型关系图

┌─────────────┐         ┌─────────────┐
│    User     │◄───────►│   Product   │
│             │ 1     * │             │
│  - _id      │         │  - _id      │
│  - username │         │  - title    │
│  - password │         │  - price    │
│  - email    │         │  - seller   │
│  - avatar   │         │  - status   │
│  - role     │         └─────────────┘
│  - followers│                │
│  - following│                │ *
│  - favorites│                │
└─────────────┘                │
       │ 1                     │
       │                       │
       │ *                     │ 1
┌─────────────┐         ┌─────────────┐
│   Message   │         │    Order    │
│             │         │             │
│  - _id      │         │  - _id      │
│  - sender   │         │  - buyer    │
│  - receiver │         │  - seller   │
│  - content  │         │  - product  │
│  - isRead   │         │  - status   │
└─────────────┘         │  - amount   │
                        └─────────────┘

为什么选择 MongoDB:

MongoDB 是一个 NoSQL 文档数据库,特别适合本项目的原因:

  1. 灵活的数据模型 - 文档结构可以随需求变化,不需要预定义严格的表结构
  2. 嵌套文档支持 - 可以直接存储复杂的嵌套数据(如商品评论、用户关注列表)
  3. 水平扩展 - 支持分片,易于扩展
  4. JSON 格式 - 与 JavaScript 天然契合
  5. 高性能 - 对于读多写少的场景性能优秀

Mongoose Schema 设计原理:

Mongoose 是 MongoDB 的 ODM(Object Document Mapping),提供了数据建模、验证、查询构建等功能。

五、 快速启动指南 🚀

前置要求

  • Node.js >= 16.0.0
  • pnpm >= 8.0.0
  • MongoDB(需要启动服务)

三步启动项目

第一步:安装依赖

pnpm install

第二步:导入测试数据

pnpm run import

输出示例:

✅ MongoDB连接成功
✅ 数据库已清空
✅ 创建了 5 个用户
✅ 创建了 15 个商品
✅ 创建了 5 个订单
✅ 创建了 7 条消息

✅ 数据导入完成!
📊 数据统计:
   - 用户: 5
   - 商品: 15
   - 订单: 5
   - 消息: 7

💡 测试账号:
   管理员: admin / admin123
   普通用户: 张三 / 123456
   普通用户: 李四 / 123456

第三步:启动开发服务器

pnpm run dev

这会同时启动:

❌
❌