# 萌芽小店 · 前端

基于 **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. `authState`（reactive 对象）全局共享 `token`、`account`、`username`、`avatarUrl`
4. 所有需要认证的 API 请求在 `Authorization: Bearer <token>` 头部携带 token

## 主要功能模块

### 商品列表（StorePage）

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

### 结算页（CheckoutPage）

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

### 收藏夹（useWishlist Composable）

```js
import { wishlistIds, wishlistCount, inWishlist, loadWishlist, toggleWishlist } from './useWishlist'
```

- 数据存储在后端，通过 API 同步
- `App.vue` 在登录状态变化时自动调用 `loadWishlist()`
- 收藏状态通过 `wishlistSet`（computed Set）提供 O(1) 查找

### 客服聊天（ChatWidget）

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

## 开发启动

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

### 环境变量

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

```env
VITE_API_BASE_URL=http://localhost:8080
```

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

## 全局样式

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

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

字体使用楷体（KaiTi / STKaiti），fallback 到系统衬线字体。

## 构建与部署

```bash
npm run build
```

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

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

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