Files

萌芽小店 · 前端

基于 Vue 3 + Vite 构建的数字商品销售平台前端,采用组件化模块架构。

技术依赖

版本 用途
vue ^3.x 核心框架
vite ^5.x 构建工具
vue-router ^4.x 路由管理
pinia ^2.x 状态管理
axios ^1.6 HTTP 请求
markdown-it ^14 Markdown 渲染

目录结构

src/
├── assets/
│   └── styles.css           # 全局 CSS 变量与公共样式
├── router/
│   └── index.js             # 路由配置(含维护模式守卫)
├── modules/
│   ├── shared/
│   │   ├── api.js           # 所有 API 请求封装
│   │   ├── auth.js          # 认证状态Pinia store
│   │   └── useWishlist.js   # 收藏夹 Composable
│   ├── store/
│   │   ├── StorePage.vue    # 商品列表页
│   │   ├── ProductDetail.vue # 商品详情页
│   │   ├── CheckoutPage.vue  # 结算页
│   │   └── components/
│   │       └── ProductCard.vue # 商品卡片组件
│   ├── admin/
│   │   ├── AdminPage.vue    # 管理后台(编排层)
│   │   └── components/
│   │       ├── AdminTokenRow.vue      # 令牌输入
│   │       ├── AdminMaintenanceRow.vue # 维护模式开关
│   │       ├── AdminProductTable.vue  # 商品列表表格
│   │       ├── AdminProductModal.vue  # 商品编辑弹窗
│   │       ├── AdminOrderTable.vue    # 订单记录表格
│   │       └── AdminChatPanel.vue     # 用户聊天管理
│   ├── user/
│   │   └── MyOrdersPage.vue  # 我的订单
│   ├── wishlist/
│   │   └── WishlistPage.vue  # 收藏夹页面
│   ├── maintenance/
│   │   └── MaintenancePage.vue # 站点维护页面
│   └── chat/
│       └── ChatWidget.vue    # 用户悬浮聊天窗口
└── App.vue                   # 根组件(全局布局 + 导航)

路由列表

路径 组件 说明
/ StorePage 商品列表
/product/:id ProductDetail 商品详情
/product/:id/checkout CheckoutPage 结算页
/my/orders MyOrdersPage 我的订单(需登录)
/wishlist WishlistPage 收藏夹(需登录)
/admin AdminPage 管理后台(需令牌)
/maintenance MaintenancePage 维护中页面

路由守卫

  • 维护模式beforeEach 检查 GET /api/site/maintenance,若站点维护中则重定向到 /maintenance(管理员访问 /admin 时豁免)
  • 豁免路径:/maintenance/wishlist/admin

认证流程

使用 SproutGate OAuth 服务:

  1. 未登录用户点击「萌芽账号登录」,跳转到 https://auth.shumengya.top/login?callback=<当前页>
  2. 登录成功后回调携带 token存入 localStorage
  3. authStatereactive 对象)全局共享 tokenaccountusernameavatarUrl
  4. 所有需要认证的 API 请求在 Authorization: Bearer <token> 头部携带 token

主要功能模块

商品列表StorePage

  • 视图模式(viewMode):全部 / 免费 / 新上架 / 最多购买 / 最多浏览 / 价格最高 / 价格最低
  • 搜索:实时过滤商品名称
  • 分页:桌面 20 条/页4×5手机 10 条/页5×2
  • 响应式布局:window.innerWidth <= 900 切换为双列

结算页CheckoutPage

  • 展示商品信息与价格
  • 数量输入,最大值受 product.maxPerAccount 限制
  • 若商品开启 showNote:展示备注文本框
  • 若商品开启 showContact:展示手机号和邮箱输入框
  • 手动发货商品:展示蓝色提示条,确认后显示"等待发货中"
  • 自动发货商品:确认后展示卡密内容

收藏夹useWishlist Composable

import { wishlistIds, wishlistCount, inWishlist, loadWishlist, toggleWishlist } from './useWishlist'
  • 数据存储在后端,通过 API 同步
  • App.vue 在登录状态变化时自动调用 loadWishlist()
  • 收藏状态通过 wishlistSetcomputed Set提供 O(1) 查找

客服聊天ChatWidget

  • 仅已登录用户显示(右下角悬浮按钮)
  • 每 5 秒轮询新消息
  • 客户端和服务端均限制每秒最多发送 1 条消息

开发启动

npm install
npm run dev       # 开发服务器 :5173
npm run build     # 生产构建 → dist/
npm run preview   # 预览构建结果

环境变量

在项目根目录创建 .env.local

VITE_API_BASE_URL=http://localhost:8080

生产部署时设置实际 API 地址。

全局样式

src/assets/styles.css 定义了全局 CSS 变量:

:root {
  --accent: #91a8d0;      /* 主题色 */
  --accent-2: #b8c8e4;    /* 渐变色 */
  --text: #2c2c3a;        /* 文字色 */
  --muted: #8e8e9e;       /* 次要文字 */
  --line: rgba(0,0,0,0.08); /* 边框色 */
  --radius: 8px;          /* 圆角 */
}

字体使用楷体KaiTi / STKaitifallback 到系统衬线字体。

构建与部署

npm run build

产物在 dist/ 目录,为静态文件,部署到 Nginx / CDN 时需配置:

location / {
    try_files $uri $uri/ /index.html;  # SPA 路由支持
}

location /api/ {
    proxy_pass http://localhost:8080;   # 反向代理到后端
}