修改文件结构
This commit is contained in:
44554
.gitignore
vendored
44554
.gitignore
vendored
File diff suppressed because it is too large
Load Diff
375
API_DOCS.md
375
API_DOCS.md
@@ -1,375 +0,0 @@
|
||||
# 📚 API 接口文档
|
||||
|
||||
## 📋 文档说明
|
||||
本文档详细描述了杰邦科项目的所有API接口,包括请求参数、响应格式和错误代码。
|
||||
|
||||
## 🔐 认证方式
|
||||
|
||||
### JWT Token 认证
|
||||
所有需要认证的API必须在请求头中携带Token:
|
||||
```
|
||||
Authorization: Bearer <your_jwt_token>
|
||||
```
|
||||
|
||||
### Token 获取
|
||||
通过登录接口获取Token,Token有效期为7天。
|
||||
|
||||
## 👥 用户模块
|
||||
|
||||
### 用户注册
|
||||
|
||||
**Endpoint:** `POST /api/v1/users/register`
|
||||
|
||||
**请求参数:**
|
||||
```json
|
||||
{
|
||||
"username": "string, required, 3-20字符",
|
||||
"password": "string, required, 6-20字符",
|
||||
"email": "string, optional, 邮箱格式",
|
||||
"phone": "string, optional, 手机号格式"
|
||||
}
|
||||
```
|
||||
|
||||
**响应示例:**
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"message": "注册成功",
|
||||
"data": {
|
||||
"id": 1,
|
||||
"username": "testuser",
|
||||
"email": "test@example.com",
|
||||
"createdAt": "2024-01-01T00:00:00.000Z"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**错误代码:**
|
||||
- `400`: 参数验证失败
|
||||
- `409`: 用户名已存在
|
||||
- `500`: 服务器内部错误
|
||||
|
||||
### 用户登录
|
||||
|
||||
**Endpoint:** `POST /api/v1/users/login`
|
||||
|
||||
**请求参数:**
|
||||
```json
|
||||
{
|
||||
"username": "string, required",
|
||||
"password": "string, required"
|
||||
}
|
||||
```
|
||||
|
||||
**响应示例:**
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"message": "登录成功",
|
||||
"data": {
|
||||
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
|
||||
"user": {
|
||||
"id": 1,
|
||||
"username": "testuser",
|
||||
"email": "test@example.com"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**错误代码:**
|
||||
- `400`: 参数验证失败
|
||||
- `401`: 用户名或密码错误
|
||||
- `500`: 服务器内部错误
|
||||
|
||||
### 获取用户信息
|
||||
|
||||
**Endpoint:** `GET /api/v1/users/profile`
|
||||
|
||||
**请求头:**
|
||||
```
|
||||
Authorization: Bearer <token>
|
||||
```
|
||||
|
||||
**响应示例:**
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"message": "获取成功",
|
||||
"data": {
|
||||
"id": 1,
|
||||
"username": "testuser",
|
||||
"email": "test@example.com",
|
||||
"phone": "13800138000",
|
||||
"createdAt": "2024-01-01T00:00:00.000Z",
|
||||
"updatedAt": "2024-01-01T00:00:00.000Z"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**错误代码:**
|
||||
- `401`: 未授权访问
|
||||
- `404`: 用户不存在
|
||||
- `500`: 服务器内部错误
|
||||
|
||||
## 🛒 订单模块
|
||||
|
||||
### 创建订单
|
||||
|
||||
**Endpoint:** `POST /api/v1/orders`
|
||||
|
||||
**请求头:**
|
||||
```
|
||||
Authorization: Bearer <token>
|
||||
```
|
||||
|
||||
**请求参数:**
|
||||
```json
|
||||
{
|
||||
"items": [
|
||||
{
|
||||
"productId": 1,
|
||||
"quantity": 2,
|
||||
"price": 100.00
|
||||
}
|
||||
],
|
||||
"shippingAddress": {
|
||||
"recipient": "张三",
|
||||
"phone": "13800138000",
|
||||
"address": "北京市朝阳区xxx路xxx号"
|
||||
},
|
||||
"remark": "string, optional"
|
||||
}
|
||||
```
|
||||
|
||||
**响应示例:**
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"message": "订单创建成功",
|
||||
"data": {
|
||||
"id": 1001,
|
||||
"orderNo": "ORDER202401010001",
|
||||
"totalAmount": 200.00,
|
||||
"status": "pending",
|
||||
"createdAt": "2024-01-01T00:00:00.000Z"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 查询订单列表
|
||||
|
||||
**Endpoint:** `GET /api/v1/orders`
|
||||
|
||||
**请求头:**
|
||||
```
|
||||
Authorization: Bearer <token>
|
||||
```
|
||||
|
||||
**查询参数:**
|
||||
```
|
||||
?page=1&limit=10&status=pending
|
||||
```
|
||||
|
||||
| 参数 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| page | number | 页码,默认1 |
|
||||
| limit | number | 每页数量,默认10 |
|
||||
| status | string | 订单状态过滤 |
|
||||
|
||||
**响应示例:**
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"message": "获取成功",
|
||||
"data": {
|
||||
"items": [
|
||||
{
|
||||
"id": 1001,
|
||||
"orderNo": "ORDER202401010001",
|
||||
"totalAmount": 200.00,
|
||||
"status": "pending",
|
||||
"createdAt": "2024-01-01T00:00:00.000Z"
|
||||
}
|
||||
],
|
||||
"pagination": {
|
||||
"page": 1,
|
||||
"limit": 10,
|
||||
"total": 100,
|
||||
"pages": 10
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 📦 商品模块
|
||||
|
||||
### 获取商品列表
|
||||
|
||||
**Endpoint:** `GET /api/v1/products`
|
||||
|
||||
**查询参数:**
|
||||
```
|
||||
?page=1&limit=10&category=electronics&sort=price_desc
|
||||
```
|
||||
|
||||
| 参数 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| page | number | 页码,默认1 |
|
||||
| limit | number | 每页数量,默认10 |
|
||||
| category | string | 商品分类过滤 |
|
||||
| sort | string | 排序方式 |
|
||||
|
||||
**响应示例:**
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"message": "获取成功",
|
||||
"data": {
|
||||
"items": [
|
||||
{
|
||||
"id": 1,
|
||||
"name": "iPhone 15",
|
||||
"price": 5999.00,
|
||||
"originalPrice": 6999.00,
|
||||
"image": "/images/iphone15.jpg",
|
||||
"category": "electronics",
|
||||
"stock": 100,
|
||||
"description": "最新款iPhone手机"
|
||||
}
|
||||
],
|
||||
"pagination": {
|
||||
"page": 1,
|
||||
"limit": 10,
|
||||
"total": 1000,
|
||||
"pages": 100
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 获取商品详情
|
||||
|
||||
**Endpoint:** `GET /api/v1/products/:id`
|
||||
|
||||
**路径参数:**
|
||||
- `id`: 商品ID
|
||||
|
||||
**响应示例:**
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"message": "获取成功",
|
||||
"data": {
|
||||
"id": 1,
|
||||
"name": "iPhone 15",
|
||||
"price": 5999.00,
|
||||
"originalPrice": 6999.00,
|
||||
"images": [
|
||||
"/images/iphone15-1.jpg",
|
||||
"/images/iphone15-2.jpg"
|
||||
],
|
||||
"category": "electronics",
|
||||
"brand": "Apple",
|
||||
"stock": 100,
|
||||
"description": "最新款iPhone手机",
|
||||
"specifications": {
|
||||
"color": "黑色",
|
||||
"storage": "256GB",
|
||||
"screen": "6.1英寸"
|
||||
},
|
||||
"reviews": {
|
||||
"averageRating": 4.8,
|
||||
"totalReviews": 150
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 📊 数据字典
|
||||
|
||||
### 订单状态
|
||||
| 状态值 | 描述 |
|
||||
|--------|------|
|
||||
| pending | 待支付 |
|
||||
| paid | 已支付 |
|
||||
| shipped | 已发货 |
|
||||
| completed | 已完成 |
|
||||
| cancelled | 已取消 |
|
||||
|
||||
### 商品分类
|
||||
| 分类值 | 描述 |
|
||||
|--------|------|
|
||||
| electronics | 电子产品 |
|
||||
| clothing | 服装服饰 |
|
||||
| books | 图书文具 |
|
||||
| home | 家居生活 |
|
||||
| sports | 运动户外 |
|
||||
|
||||
### 错误代码
|
||||
| 代码 | 描述 |
|
||||
|------|------|
|
||||
| 200 | 成功 |
|
||||
| 400 | 请求参数错误 |
|
||||
| 401 | 未授权访问 |
|
||||
| 403 | 禁止访问 |
|
||||
| 404 | 资源不存在 |
|
||||
| 409 | 资源冲突 |
|
||||
| 500 | 服务器内部错误 |
|
||||
| 503 | 服务不可用 |
|
||||
|
||||
## 🔗 API 版本控制
|
||||
|
||||
当前API版本为v1,所有接口前缀为`/api/v1/`。
|
||||
|
||||
版本更新策略:
|
||||
- 向后兼容的修改直接更新
|
||||
- 不兼容的修改创建新版本v2
|
||||
- 旧版本API保持维护至少6个月
|
||||
|
||||
## 📡 接口限流
|
||||
|
||||
### 限流策略
|
||||
- 匿名用户: 60请求/分钟
|
||||
- 认证用户: 120请求/分钟
|
||||
- VIP用户: 300请求/分钟
|
||||
|
||||
### 限流响应
|
||||
当超过限流阈值时返回:
|
||||
```json
|
||||
{
|
||||
"code": 429,
|
||||
"message": "请求过于频繁,请稍后再试",
|
||||
"retryAfter": 60
|
||||
}
|
||||
```
|
||||
|
||||
## 🧪 接口测试
|
||||
|
||||
### 使用curl测试
|
||||
```bash
|
||||
# 用户登录
|
||||
curl -X POST http://localhost:3000/api/v1/users/login \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"username":"testuser","password":"password123"}'
|
||||
|
||||
# 获取用户信息
|
||||
curl -X GET http://localhost:3000/api/v1/users/profile \
|
||||
-H "Authorization: Bearer <token>"
|
||||
```
|
||||
|
||||
### 使用Postman测试
|
||||
1. 导入Postman集合文件
|
||||
2. 设置环境变量(base_url, token等)
|
||||
3. 运行测试用例
|
||||
|
||||
## 📝 更新日志
|
||||
|
||||
### v1.0.0 (2024-01-01)
|
||||
- 用户注册登录接口
|
||||
- 订单管理接口
|
||||
- 商品管理接口
|
||||
- 基础认证系统
|
||||
|
||||
---
|
||||
*最后更新: 2024年* 📅
|
||||
162
README.md
Normal file
162
README.md
Normal file
@@ -0,0 +1,162 @@
|
||||
# 🏗️ 杰邦科项目
|
||||
|
||||
## 📋 项目概述
|
||||
杰邦科是一个综合性的管理系统,包含后台管理、微信小程序和官方网站三个主要模块。
|
||||
|
||||
## 🗂️ 项目结构
|
||||
|
||||
```
|
||||
jiebanke/
|
||||
├── 📁 backend/ # 后端服务 (Node.js + Express)
|
||||
├── 📁 admin-system/ # 后台管理系统 (Vue 3 + Element Plus)
|
||||
├── 📁 website/ # 官方网站 (Vue 3)
|
||||
├── 📁 mini-program/ # 微信小程序矩阵 (原生小程序)
|
||||
├── 📁 docs/ # 项目文档
|
||||
├── 📁 scripts/ # 工具脚本
|
||||
├── 📁 test/ # 测试文件目录
|
||||
└── 📄 README.md # 项目说明 (当前文件)
|
||||
```
|
||||
|
||||
## 🚀 快速开始
|
||||
|
||||
### 环境要求
|
||||
- Node.js 16.x+
|
||||
- MySQL 8.0+
|
||||
- npm 8.x+
|
||||
|
||||
### 安装依赖
|
||||
```bash
|
||||
# 安装后端依赖
|
||||
cd backend && npm install
|
||||
|
||||
# 安装后台管理依赖
|
||||
cd admin-system && npm install
|
||||
|
||||
# 安装官网依赖
|
||||
cd website && npm install
|
||||
|
||||
# 安装小程序依赖
|
||||
cd mini-program && npm install
|
||||
```
|
||||
|
||||
### 启动开发环境
|
||||
```bash
|
||||
# 启动后端服务
|
||||
cd backend && npm run dev
|
||||
|
||||
# 启动后台管理 (新终端)
|
||||
cd admin-system && npm run dev
|
||||
|
||||
# 启动官方网站 (新终端)
|
||||
cd website && npm run dev
|
||||
```
|
||||
|
||||
## 📖 项目文档
|
||||
|
||||
所有详细文档位于 `docs/` 目录:
|
||||
|
||||
- 📄 [架构设计](docs/architecture.md) - 系统架构和技术栈
|
||||
- 📄 [API文档](docs/API_DOCS.md) - 完整的API接口说明
|
||||
- 📄 [部署指南](docs/DEPLOYMENT.md) - 开发、测试、生产环境部署
|
||||
- 📄 [数据库设计](docs/database-design.md) - 数据库表结构和关系
|
||||
- 📄 [需求文档](docs/requirements.md) - 业务需求和功能说明
|
||||
- 📄 [详细设计](docs/detailed_design.md) - 系统详细设计方案
|
||||
- 📄 [开发计划](docs/development_plan.md) - 项目开发进度计划
|
||||
|
||||
## 🛠️ 开发工具
|
||||
|
||||
### 脚本工具
|
||||
项目提供了一些有用的开发脚本:
|
||||
|
||||
```bash
|
||||
# 数据库连接测试
|
||||
cd backend && npm run test-db
|
||||
|
||||
# API接口测试
|
||||
cd backend && npm run test-api
|
||||
|
||||
# 数据库初始化
|
||||
cd backend && npm run db:reset
|
||||
```
|
||||
|
||||
### 环境配置
|
||||
复制环境变量模板并配置:
|
||||
|
||||
```bash
|
||||
# 后端环境配置
|
||||
cp backend/.env.example backend/.env
|
||||
|
||||
# 后台管理环境配置
|
||||
cp admin-system/.env.example admin-system/.env
|
||||
```
|
||||
|
||||
## 🌐 访问地址
|
||||
|
||||
- **后端API**: http://localhost:3000
|
||||
- **后台管理**: http://localhost:3001
|
||||
- **官方网站**: http://localhost:3002
|
||||
- **小程序**: 使用微信开发者工具打开 `mini-program/` 目录
|
||||
|
||||
## 📦 依赖管理
|
||||
|
||||
### 主要技术栈
|
||||
|
||||
**后端**:
|
||||
- Node.js + Express.js
|
||||
- Sequelize ORM
|
||||
- JWT 认证
|
||||
- MySQL 数据库
|
||||
|
||||
**前端**:
|
||||
- Vue 3 + TypeScript
|
||||
- Element Plus UI
|
||||
- Vite 构建工具
|
||||
- Pinia 状态管理
|
||||
|
||||
**小程序**:
|
||||
- 微信原生小程序
|
||||
- Vant Weapp UI
|
||||
- Uni-app 框架
|
||||
|
||||
## 🔧 开发规范
|
||||
|
||||
### 代码风格
|
||||
- 使用 ESLint + Prettier 统一代码风格
|
||||
- 遵循 Git Commit 消息规范
|
||||
- 实行代码审查流程
|
||||
|
||||
### 分支策略
|
||||
- 采用 Git Flow 工作流
|
||||
- 功能分支开发
|
||||
- 发布分支管理
|
||||
|
||||
## 🚀 部署说明
|
||||
|
||||
详细部署指南请参考 [DEPLOYMENT.md](docs/DEPLOYMENT.md),包含:
|
||||
|
||||
- 开发环境部署
|
||||
- 测试环境部署
|
||||
- 生产环境部署
|
||||
- 容器化部署 (Docker)
|
||||
- 安全配置指南
|
||||
|
||||
## 📞 支持与维护
|
||||
|
||||
### 开发团队
|
||||
- 后端开发: backend@jiebanke.com
|
||||
- 前端开发: frontend@jiebanke.com
|
||||
- 小程序开发: miniprogram@jiebanke.com
|
||||
|
||||
### 运维支持
|
||||
- 运维团队: ops@jiebanke.com
|
||||
- 紧急联系: +86-138-0013-8000
|
||||
|
||||
## 📊 版本信息
|
||||
|
||||
- **当前版本**: v1.0.0
|
||||
- **Node.js**: 16.20.2
|
||||
- **Vue**: 3.3.4
|
||||
- **MySQL**: 8.0.33
|
||||
|
||||
---
|
||||
*最后更新: 2024年* 📅
|
||||
@@ -1,61 +0,0 @@
|
||||
const bcrypt = require('bcryptjs');
|
||||
const { query } = require('./backend/src/config/database');
|
||||
|
||||
// 数据库配置
|
||||
const dbConfig = {
|
||||
host: '129.211.213.226',
|
||||
port: 9527,
|
||||
user: 'root',
|
||||
password: 'aiotAiot123!',
|
||||
database: 'jiebandata'
|
||||
};
|
||||
|
||||
async function addTestAdmin() {
|
||||
try {
|
||||
// 加密密码
|
||||
const saltRounds = 10;
|
||||
const plainPassword = 'admin123';
|
||||
const hashedPassword = await bcrypt.hash(plainPassword, saltRounds);
|
||||
|
||||
console.log('加密后的密码:', hashedPassword);
|
||||
|
||||
// 插入测试管理员账户
|
||||
const insertSQL = `
|
||||
INSERT INTO admins (username, password, email, nickname, role)
|
||||
VALUES (?, ?, ?, ?, ?)
|
||||
ON DUPLICATE KEY UPDATE
|
||||
password = VALUES(password),
|
||||
email = VALUES(email),
|
||||
nickname = VALUES(nickname),
|
||||
role = VALUES(role)
|
||||
`;
|
||||
|
||||
const params = [
|
||||
'testadmin',
|
||||
hashedPassword,
|
||||
'testadmin@example.com',
|
||||
'测试管理员',
|
||||
'admin'
|
||||
];
|
||||
|
||||
// 注意:这里我们需要直接使用mysql2连接数据库,因为backend/src/config/database可能依赖环境变量
|
||||
const mysql = require('mysql2/promise');
|
||||
const connection = await mysql.createConnection(dbConfig);
|
||||
|
||||
const [result] = await connection.execute(insertSQL, params);
|
||||
console.log('✅ 测试管理员账户创建/更新成功');
|
||||
console.log('受影响的行数:', result.affectedRows);
|
||||
|
||||
// 验证插入的数据
|
||||
const [rows] = await connection.execute('SELECT * FROM admins WHERE username = ?', ['testadmin']);
|
||||
console.log('\n插入的管理员信息:');
|
||||
console.log(rows[0]);
|
||||
|
||||
await connection.end();
|
||||
} catch (error) {
|
||||
console.error('❌ 创建测试管理员账户失败:', error.message);
|
||||
console.error(error.stack);
|
||||
}
|
||||
}
|
||||
|
||||
addTestAdmin();
|
||||
264
architecture.md
264
architecture.md
@@ -1,264 +0,0 @@
|
||||
# 🏗️ 系统架构文档
|
||||
|
||||
## 📋 项目概述
|
||||
杰邦科项目是一个综合性的管理系统,包含后台管理、微信小程序和官网三个主要模块。
|
||||
|
||||
## 🎯 技术栈
|
||||
|
||||
### 后端技术栈
|
||||
- **运行时**: Node.js + Express.js
|
||||
- **数据库**: MySQL 8.0
|
||||
- **ORM**: Sequelize
|
||||
- **认证**: JWT + bcrypt
|
||||
- **缓存**: Redis (可选)
|
||||
- **消息队列**: RabbitMQ (可选)
|
||||
|
||||
### 前端技术栈
|
||||
- **后台管理系统**: Vue 3 + Element Plus
|
||||
- **微信小程序**: 原生小程序 + Vant Weapp
|
||||
- **官方网站**: Vue 3 + Vue Router
|
||||
|
||||
### 开发工具
|
||||
- **包管理**: npm
|
||||
- **容器化**: Docker + Docker Compose
|
||||
- **代码质量**: ESLint + Prettier
|
||||
- **测试**: Jest + Supertest
|
||||
|
||||
## 🏢 系统架构
|
||||
|
||||
```mermaid
|
||||
graph TB
|
||||
subgraph "前端应用"
|
||||
A[后台管理系统]
|
||||
B[微信小程序]
|
||||
C[官方网站]
|
||||
end
|
||||
|
||||
subgraph "后端服务"
|
||||
D[API Gateway]
|
||||
E[用户服务]
|
||||
F[业务服务]
|
||||
G[文件服务]
|
||||
end
|
||||
|
||||
subgraph "数据层"
|
||||
H[MySQL]
|
||||
I[Redis]
|
||||
J[MinIO]
|
||||
end
|
||||
|
||||
A --> D
|
||||
B --> D
|
||||
C --> D
|
||||
D --> E
|
||||
D --> F
|
||||
D --> G
|
||||
E --> H
|
||||
F --> H
|
||||
G --> J
|
||||
E --> I
|
||||
```
|
||||
|
||||
## 🗄️ 数据库设计
|
||||
|
||||
### 核心表结构
|
||||
|
||||
```mermaid
|
||||
erDiagram
|
||||
users ||--o{ orders : places
|
||||
users ||--o{ addresses : has
|
||||
users {
|
||||
bigint id PK
|
||||
varchar username
|
||||
varchar password_hash
|
||||
varchar email
|
||||
varchar phone
|
||||
datetime created_at
|
||||
datetime updated_at
|
||||
}
|
||||
|
||||
orders ||--o{ order_items : contains
|
||||
orders {
|
||||
bigint id PK
|
||||
bigint user_id FK
|
||||
decimal total_amount
|
||||
varchar status
|
||||
datetime created_at
|
||||
}
|
||||
|
||||
products ||--o{ order_items : included_in
|
||||
products {
|
||||
bigint id PK
|
||||
varchar name
|
||||
decimal price
|
||||
text description
|
||||
}
|
||||
```
|
||||
|
||||
## 🌐 环境配置
|
||||
|
||||
### 开发环境 (Development)
|
||||
```env
|
||||
DB_HOST=localhost
|
||||
DB_PORT=3306
|
||||
DB_USER=root
|
||||
DB_PASSWORD=rootpassword
|
||||
DB_DATABASE=jiebanke_dev
|
||||
NODE_ENV=development
|
||||
```
|
||||
|
||||
### 测试环境 (Test)
|
||||
```env
|
||||
DB_HOST=192.168.0.240
|
||||
DB_PORT=3306
|
||||
DB_USER=root
|
||||
DB_PASSWORD=aiotAiot123!
|
||||
DB_DATABASE=jiebandata_test
|
||||
NODE_ENV=test
|
||||
```
|
||||
|
||||
### 生产环境 (Production)
|
||||
```env
|
||||
DB_HOST=129.211.213.226
|
||||
DB_PORT=9527
|
||||
DB_USER=root
|
||||
DB_PASSWORD=Aiot123
|
||||
DB_DATABASE=jiebandata
|
||||
NODE_ENV=production
|
||||
```
|
||||
|
||||
## 🔌 API 设计
|
||||
|
||||
### 用户模块 API
|
||||
|
||||
| 方法 | 路径 | 描述 | 认证 |
|
||||
|------|------|------|------|
|
||||
| POST | `/api/v1/users/register` | 用户注册 | 否 |
|
||||
| POST | `/api/v1/users/login` | 用户登录 | 否 |
|
||||
| GET | `/api/v1/users/profile` | 获取用户信息 | JWT |
|
||||
| PUT | `/api/v1/users/profile` | 更新用户信息 | JWT |
|
||||
|
||||
### 示例请求
|
||||
```javascript
|
||||
// 用户登录
|
||||
POST /api/v1/users/login
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"username": "testuser",
|
||||
"password": "password123"
|
||||
}
|
||||
```
|
||||
|
||||
## 🚀 部署架构
|
||||
|
||||
### 开发部署
|
||||
```mermaid
|
||||
graph LR
|
||||
A[本地开发机] --> B[Docker Compose]
|
||||
B --> C[MySQL容器]
|
||||
B --> D[Node.js应用]
|
||||
B --> E[Redis容器]
|
||||
```
|
||||
|
||||
### 生产部署
|
||||
```mermaid
|
||||
graph TB
|
||||
subgraph "云服务器"
|
||||
A[Nginx]
|
||||
B[Node.js集群]
|
||||
C[MySQL主从]
|
||||
D[Redis哨兵]
|
||||
end
|
||||
|
||||
A --> B
|
||||
B --> C
|
||||
B --> D
|
||||
```
|
||||
|
||||
## 📊 监控与日志
|
||||
|
||||
- **应用监控**: PM2 + Keymetrics
|
||||
- **日志管理**: Winston + ELK Stack
|
||||
- **性能监控**: New Relic / Datadog
|
||||
- **错误追踪**: Sentry
|
||||
|
||||
## 🔒 安全架构
|
||||
|
||||
### 认证授权
|
||||
- JWT Token 认证
|
||||
- RBAC (基于角色的访问控制)
|
||||
- API 速率限制
|
||||
|
||||
### 数据安全
|
||||
- HTTPS 加密传输
|
||||
- 密码加盐哈希存储
|
||||
- SQL 注入防护
|
||||
- XSS 攻击防护
|
||||
|
||||
### 网络安全
|
||||
- 防火墙规则
|
||||
- IP 白名单
|
||||
- DDoS 防护
|
||||
|
||||
## 📈 性能优化
|
||||
|
||||
### 数据库优化
|
||||
- 索引优化
|
||||
- 查询缓存
|
||||
- 读写分离
|
||||
|
||||
### 应用优化
|
||||
- 响应压缩
|
||||
- 静态资源CDN
|
||||
- 内存缓存
|
||||
|
||||
### 前端优化
|
||||
- 代码分割
|
||||
- 懒加载
|
||||
- 图片优化
|
||||
|
||||
## 🛠️ 开发规范
|
||||
|
||||
### 代码规范
|
||||
- ESLint + Prettier 统一代码风格
|
||||
- Git Commit 消息规范
|
||||
- 代码审查流程
|
||||
|
||||
### 分支策略
|
||||
- Git Flow 工作流
|
||||
- 功能分支开发
|
||||
- 发布分支管理
|
||||
|
||||
### 测试策略
|
||||
- 单元测试覆盖核心逻辑
|
||||
- 集成测试API接口
|
||||
- E2E测试用户流程
|
||||
|
||||
## 📝 文档体系
|
||||
|
||||
1. **ARCHITECTURE.md** - 系统架构文档 (当前文件)
|
||||
2. **README.md** - 项目说明文档
|
||||
3. **API_DOCS.md** - API接口文档
|
||||
4. **DEPLOYMENT.md** - 部署指南
|
||||
5. **DEVELOPMENT.md** - 开发指南
|
||||
|
||||
## 🎯 后续规划
|
||||
|
||||
### 短期目标
|
||||
- [ ] 完善用户管理系统
|
||||
- [ ] 实现订单业务流程
|
||||
- [ ] 部署测试环境
|
||||
|
||||
### 中期目标
|
||||
- [ ] 微服务架构改造
|
||||
- [ ] 容器化部署
|
||||
- [ ] 自动化测试覆盖
|
||||
|
||||
### 长期目标
|
||||
- [ ] 大数据分析平台
|
||||
- [ ] AI智能推荐
|
||||
- [ ] 多语言国际化
|
||||
|
||||
---
|
||||
*最后更新: 2024年* 📅
|
||||
@@ -1,60 +0,0 @@
|
||||
const mysql = require('mysql2');
|
||||
|
||||
// 数据库连接配置
|
||||
const dbConfig = {
|
||||
host: '129.211.213.226',
|
||||
port: 9527,
|
||||
user: 'root',
|
||||
password: 'aiotAiot123!',
|
||||
database: 'jiebandata'
|
||||
};
|
||||
|
||||
// 创建连接
|
||||
const connection = mysql.createConnection(dbConfig);
|
||||
|
||||
// 连接数据库
|
||||
connection.connect((err) => {
|
||||
if (err) {
|
||||
console.error('数据库连接失败: ' + err.stack);
|
||||
return;
|
||||
}
|
||||
console.log('数据库连接成功,连接ID: ' + connection.threadId);
|
||||
|
||||
// 检查animals表结构
|
||||
connection.query('DESCRIBE animals', (error, results) => {
|
||||
if (error) {
|
||||
console.error('查询animals表结构失败: ' + error.stack);
|
||||
connection.end();
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('\n=== animals表结构 ===');
|
||||
console.table(results);
|
||||
|
||||
// 检查merchants表结构
|
||||
connection.query('DESCRIBE merchants', (error, results) => {
|
||||
if (error) {
|
||||
console.error('查询merchants表结构失败: ' + error.stack);
|
||||
connection.end();
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('\n=== merchants表结构 ===');
|
||||
console.table(results);
|
||||
|
||||
// 检查users表结构
|
||||
connection.query('DESCRIBE users', (error, results) => {
|
||||
if (error) {
|
||||
console.error('查询users表结构失败: ' + error.stack);
|
||||
connection.end();
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('\n=== users表结构 ===');
|
||||
console.table(results);
|
||||
|
||||
connection.end();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,103 +0,0 @@
|
||||
const mysql = require('mysql2');
|
||||
|
||||
// 数据库配置
|
||||
const configs = [
|
||||
{
|
||||
name: '测试环境',
|
||||
host: '192.168.0.240',
|
||||
port: 3306,
|
||||
user: 'root',
|
||||
password: 'aiot$Aiot123'
|
||||
},
|
||||
{
|
||||
name: '生产环境',
|
||||
host: '129.211.213.226',
|
||||
port: 9527,
|
||||
user: 'root',
|
||||
password: 'aiotAiot123!'
|
||||
}
|
||||
];
|
||||
|
||||
// 简单的SQL语句(避免编码问题)
|
||||
const sqlStatements = [
|
||||
"CREATE DATABASE IF NOT EXISTS jiebandata CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci",
|
||||
"USE jiebandata",
|
||||
`CREATE TABLE IF NOT EXISTS users (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
openid VARCHAR(64) UNIQUE NOT NULL,
|
||||
nickname VARCHAR(50) NOT NULL,
|
||||
avatar VARCHAR(255),
|
||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
|
||||
) ENGINE=InnoDB`
|
||||
];
|
||||
|
||||
function executeSQL(connection, sql, description) {
|
||||
return new Promise((resolve, reject) => {
|
||||
console.log(description);
|
||||
connection.query(sql, (err, results) => {
|
||||
if (err) {
|
||||
console.error('失败:', err.message);
|
||||
reject(err);
|
||||
} else {
|
||||
console.log('成功');
|
||||
resolve(results);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
async function setupDatabase(config) {
|
||||
console.log(`\n开始设置 ${config.name} 数据库...`);
|
||||
|
||||
const connection = mysql.createConnection({
|
||||
host: config.host,
|
||||
port: config.port,
|
||||
user: config.user,
|
||||
password: config.password
|
||||
});
|
||||
|
||||
try {
|
||||
await new Promise((resolve, reject) => {
|
||||
connection.connect((err) => {
|
||||
if (err) reject(err);
|
||||
else resolve();
|
||||
});
|
||||
});
|
||||
|
||||
for (let i = 0; i < sqlStatements.length; i++) {
|
||||
await executeSQL(connection, sqlStatements[i], `执行SQL ${i + 1}/${sqlStatements.length}`);
|
||||
}
|
||||
|
||||
console.log('✅ 数据库设置完成');
|
||||
return true;
|
||||
|
||||
} catch (error) {
|
||||
console.error('❌ 数据库设置失败:', error.message);
|
||||
return false;
|
||||
} finally {
|
||||
connection.end();
|
||||
}
|
||||
}
|
||||
|
||||
async function main() {
|
||||
console.log('🎯 结伴客数据库初始化');
|
||||
console.log('='.repeat(50));
|
||||
|
||||
let successCount = 0;
|
||||
|
||||
for (const config of configs) {
|
||||
const success = await setupDatabase(config);
|
||||
if (success) successCount++;
|
||||
console.log('\n' + '='.repeat(50));
|
||||
}
|
||||
|
||||
console.log(`📊 完成: ${successCount}/${configs.length} 个环境成功`);
|
||||
|
||||
if (successCount > 0) {
|
||||
console.log('\n🎉 数据库初始化完成!');
|
||||
console.log('现在可以运行测试脚本来验证数据库结构。');
|
||||
}
|
||||
}
|
||||
|
||||
main().catch(console.error);
|
||||
137
db_test.js
137
db_test.js
@@ -1,137 +0,0 @@
|
||||
const mysql = require('mysql2');
|
||||
|
||||
// 数据库配置
|
||||
const dbConfig = {
|
||||
host: '129.211.213.226',
|
||||
port: 9527,
|
||||
user: 'root',
|
||||
password: 'aiotAiot123!',
|
||||
database: 'jiebandata'
|
||||
};
|
||||
|
||||
// 创建连接
|
||||
const connection = mysql.createConnection(dbConfig);
|
||||
|
||||
// 连接数据库
|
||||
connection.connect((err) => {
|
||||
if (err) {
|
||||
console.error('数据库连接失败: ' + err.stack);
|
||||
return;
|
||||
}
|
||||
console.log('数据库连接成功,连接ID: ' + connection.threadId);
|
||||
|
||||
// 查询所有表
|
||||
connection.query('SHOW TABLES', (error, results) => {
|
||||
if (error) {
|
||||
console.error('查询表失败: ' + error.stack);
|
||||
connection.end();
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('数据库中的所有表:');
|
||||
const tables = results.map(row => {
|
||||
const tableName = Object.values(row)[0];
|
||||
console.log('- ' + tableName);
|
||||
return tableName;
|
||||
});
|
||||
|
||||
// 检查是否存在管理员表
|
||||
const adminTableExists = tables.some(table =>
|
||||
table.includes('admin') || table.includes('Admin') || table.includes('ADMIN')
|
||||
);
|
||||
|
||||
if (adminTableExists) {
|
||||
console.log('\n✅ 找到可能的管理员相关表');
|
||||
|
||||
// 显示管理员相关表结构
|
||||
const adminTables = tables.filter(table =>
|
||||
table.includes('admin') || table.includes('Admin') || table.includes('ADMIN')
|
||||
);
|
||||
|
||||
showTableStructure(adminTables, 0);
|
||||
} else {
|
||||
console.log('\n❌ 未找到管理员相关表');
|
||||
|
||||
// 显示所有表的简要信息
|
||||
showAllTablesInfo(tables, 0);
|
||||
}
|
||||
});
|
||||
|
||||
// 显示表结构的递归函数
|
||||
function showTableStructure(tables, index) {
|
||||
if (index >= tables.length) {
|
||||
connection.end();
|
||||
return;
|
||||
}
|
||||
|
||||
const tableName = tables[index];
|
||||
console.log(`\n${tableName} 表结构:`);
|
||||
|
||||
connection.query(`DESCRIBE ${tableName}`, (error, results) => {
|
||||
if (error) {
|
||||
console.error(`查询 ${tableName} 表结构失败: ` + error.stack);
|
||||
} else {
|
||||
console.table(results.map(row => ({
|
||||
字段: row.Field,
|
||||
类型: row.Type,
|
||||
空: row.Null,
|
||||
键: row.Key,
|
||||
默认值: row.Default,
|
||||
额外: row.Extra
|
||||
})));
|
||||
}
|
||||
|
||||
showTableStructure(tables, index + 1);
|
||||
});
|
||||
}
|
||||
|
||||
// 显示所有表信息的递归函数
|
||||
function showAllTablesInfo(tables, index) {
|
||||
if (index >= tables.length) {
|
||||
// 创建管理员表的SQL
|
||||
console.log('\n=== 建议创建的管理员表结构 ===');
|
||||
const createAdminTableSQL = `
|
||||
CREATE TABLE admins (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
username VARCHAR(50) NOT NULL UNIQUE,
|
||||
password VARCHAR(255) NOT NULL,
|
||||
email VARCHAR(100) UNIQUE,
|
||||
nickname VARCHAR(100),
|
||||
avatar VARCHAR(255),
|
||||
role ENUM('super_admin', 'admin', 'operator') DEFAULT 'admin',
|
||||
status TINYINT DEFAULT 1,
|
||||
last_login TIMESTAMP NULL,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
|
||||
);`;
|
||||
|
||||
console.log(createAdminTableSQL);
|
||||
|
||||
// 插入测试数据的SQL
|
||||
console.log('\n=== 插入测试数据 ===');
|
||||
const insertTestDataSQL = `
|
||||
INSERT INTO admins (username, password, email, nickname, role) VALUES
|
||||
('admin', '$2b$10$rVuz/q97ocR1Zb07DzW5F.9Qx6B6HnV7JFzQb5nR1W3v7Z2mH4n6O', 'admin@example.com', '超级管理员', 'super_admin'),
|
||||
('operator', '$2b$10$rVuz/q97ocR1Zb07DzW5F.9Qx6B6HnV7JFzQb5nR1W3v7Z2mH4n6O', 'operator@example.com', '操作员', 'operator');
|
||||
`;
|
||||
|
||||
console.log(insertTestDataSQL);
|
||||
|
||||
connection.end();
|
||||
return;
|
||||
}
|
||||
|
||||
const tableName = tables[index];
|
||||
console.log(`\n${tableName} 表信息:`);
|
||||
|
||||
connection.query(`SELECT COUNT(*) as count FROM ${tableName}`, (error, results) => {
|
||||
if (error) {
|
||||
console.error(`查询 ${tableName} 表数据量失败: ` + error.stack);
|
||||
} else {
|
||||
console.log(`数据量: ${results[0].count} 条`);
|
||||
}
|
||||
|
||||
showAllTablesInfo(tables, index + 1);
|
||||
});
|
||||
}
|
||||
});
|
||||
85
db_update.js
85
db_update.js
@@ -1,85 +0,0 @@
|
||||
const mysql = require('mysql2');
|
||||
|
||||
// 数据库配置
|
||||
const dbConfig = {
|
||||
host: '129.211.213.226',
|
||||
port: 9527,
|
||||
user: 'root',
|
||||
password: 'aiotAiot123!',
|
||||
database: 'jiebandata'
|
||||
};
|
||||
|
||||
// 创建连接
|
||||
const connection = mysql.createConnection(dbConfig);
|
||||
|
||||
// 连接数据库
|
||||
connection.connect((err) => {
|
||||
if (err) {
|
||||
console.error('数据库连接失败: ' + err.stack);
|
||||
return;
|
||||
}
|
||||
console.log('数据库连接成功,连接ID: ' + connection.threadId);
|
||||
|
||||
// 创建管理员表
|
||||
const createAdminTableSQL = `
|
||||
CREATE TABLE IF NOT EXISTS admins (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
username VARCHAR(50) NOT NULL UNIQUE,
|
||||
password VARCHAR(255) NOT NULL,
|
||||
email VARCHAR(100) UNIQUE,
|
||||
nickname VARCHAR(100),
|
||||
avatar VARCHAR(255),
|
||||
role ENUM('super_admin', 'admin', 'operator') DEFAULT 'admin',
|
||||
status TINYINT DEFAULT 1,
|
||||
last_login TIMESTAMP NULL,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
INDEX idx_username (username),
|
||||
INDEX idx_email (email),
|
||||
INDEX idx_role (role)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
`;
|
||||
|
||||
connection.query(createAdminTableSQL, (error, results) => {
|
||||
if (error) {
|
||||
console.error('创建管理员表失败: ' + error.stack);
|
||||
connection.end();
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('✅ 管理员表创建成功');
|
||||
|
||||
// 检查是否已存在测试数据
|
||||
connection.query('SELECT COUNT(*) as count FROM admins', (error, results) => {
|
||||
if (error) {
|
||||
console.error('查询管理员表数据量失败: ' + error.stack);
|
||||
connection.end();
|
||||
return;
|
||||
}
|
||||
|
||||
if (results[0].count > 0) {
|
||||
console.log('✅ 管理员表中已有数据,跳过插入测试数据');
|
||||
connection.end();
|
||||
return;
|
||||
}
|
||||
|
||||
// 插入测试数据
|
||||
const insertTestDataSQL = `
|
||||
INSERT INTO admins (username, password, email, nickname, role) VALUES
|
||||
('admin', '$2b$10$rVuz/q97ocR1Zb07DzW5F.9Qx6B6HnV7JFzQb5nR1W3v7Z2mH4n6O', 'admin@example.com', '超级管理员', 'super_admin'),
|
||||
('operator', '$2b$10$rVuz/q97ocR1Zb07DzW5F.9Qx6B6HnV7JFzQb5nR1W3v7Z2mH4n6O', 'operator@example.com', '操作员', 'operator');
|
||||
`;
|
||||
|
||||
connection.query(insertTestDataSQL, (error, results) => {
|
||||
if (error) {
|
||||
console.error('插入测试数据失败: ' + error.stack);
|
||||
connection.end();
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('✅ 测试数据插入成功,插入 ' + results.affectedRows + ' 条记录');
|
||||
connection.end();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
65
db_verify.js
65
db_verify.js
@@ -1,65 +0,0 @@
|
||||
const mysql = require('mysql2');
|
||||
|
||||
// 数据库配置
|
||||
const dbConfig = {
|
||||
host: '129.211.213.226',
|
||||
port: 9527,
|
||||
user: 'root',
|
||||
password: 'aiotAiot123!',
|
||||
database: 'jiebandata'
|
||||
};
|
||||
|
||||
// 创建连接
|
||||
const connection = mysql.createConnection(dbConfig);
|
||||
|
||||
// 连接数据库
|
||||
connection.connect((err) => {
|
||||
if (err) {
|
||||
console.error('数据库连接失败: ' + err.stack);
|
||||
return;
|
||||
}
|
||||
console.log('数据库连接成功,连接ID: ' + connection.threadId);
|
||||
|
||||
// 查询管理员表结构
|
||||
connection.query('DESCRIBE admins', (error, results) => {
|
||||
if (error) {
|
||||
console.error('查询管理员表结构失败: ' + error.stack);
|
||||
connection.end();
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('\n=== 管理员表结构 ===');
|
||||
console.table(results.map(row => ({
|
||||
字段: row.Field,
|
||||
类型: row.Type,
|
||||
空: row.Null,
|
||||
键: row.Key,
|
||||
默认值: row.Default,
|
||||
额外: row.Extra
|
||||
})));
|
||||
|
||||
// 查询管理员数据
|
||||
connection.query('SELECT * FROM admins', (error, results) => {
|
||||
if (error) {
|
||||
console.error('查询管理员数据失败: ' + error.stack);
|
||||
connection.end();
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('\n=== 管理员数据 ===');
|
||||
console.table(results.map(row => ({
|
||||
ID: row.id,
|
||||
用户名: row.username,
|
||||
邮箱: row.email,
|
||||
昵称: row.nickname,
|
||||
角色: row.role,
|
||||
状态: row.status,
|
||||
创建时间: row.created_at,
|
||||
最后登录: row.last_login
|
||||
})));
|
||||
|
||||
console.log('\n✅ 数据库验证完成');
|
||||
connection.end();
|
||||
});
|
||||
});
|
||||
});
|
||||
531
docs/API_DOCS.md
Normal file
531
docs/API_DOCS.md
Normal file
@@ -0,0 +1,531 @@
|
||||
# 📚 结伴客API接口文档
|
||||
|
||||
## 📋 文档说明
|
||||
本文档详细描述了结伴客项目的所有API接口,包括请求参数、响应格式和错误代码。结伴客是一个专注于结伴旅行和动物认领的社交平台。
|
||||
|
||||
## 🔐 认证方式
|
||||
|
||||
### JWT Token 认证
|
||||
所有需要认证的API必须在请求头中携带Token:
|
||||
```
|
||||
Authorization: Bearer <your_jwt_token>
|
||||
```
|
||||
|
||||
### Token 获取
|
||||
通过微信登录接口获取Token,Token有效期为7天。
|
||||
|
||||
## 👥 用户模块
|
||||
|
||||
### 微信用户登录
|
||||
|
||||
**Endpoint:** `POST /api/v1/auth/wechat-login`
|
||||
|
||||
**请求参数:**
|
||||
```json
|
||||
{
|
||||
"code": "string, required, 微信登录code",
|
||||
"userInfo": {
|
||||
"nickName": "string, required, 用户昵称",
|
||||
"avatarUrl": "string, required, 用户头像",
|
||||
"gender": "number, optional, 性别(0:未知,1:男,2:女)",
|
||||
"province": "string, optional, 省份",
|
||||
"city": "string, optional, 城市"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**响应示例:**
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"message": "登录成功",
|
||||
"data": {
|
||||
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
|
||||
"user": {
|
||||
"id": 1,
|
||||
"openid": "wx1234567890",
|
||||
"nickname": "旅行达人",
|
||||
"avatar": "https://avatar.url",
|
||||
"gender": "male",
|
||||
"phone": "13800138000"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**错误代码:**
|
||||
- `400`: 参数验证失败
|
||||
- `401`: 登录失败
|
||||
- `500`: 服务器内部错误
|
||||
|
||||
### 获取用户信息
|
||||
|
||||
**Endpoint:** `GET /api/v1/users/profile`
|
||||
|
||||
**请求头:**
|
||||
```
|
||||
Authorization: Bearer <token>
|
||||
```
|
||||
|
||||
**响应示例:**
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"message": "获取成功",
|
||||
"data": {
|
||||
"id": 1,
|
||||
"openid": "wx1234567890",
|
||||
"nickname": "旅行达人",
|
||||
"avatar": "https://avatar.url",
|
||||
"gender": "male",
|
||||
"birthday": "1990-01-01",
|
||||
"phone": "13800138000",
|
||||
"email": "test@example.com",
|
||||
"travelCount": 5,
|
||||
"animalClaimCount": 2,
|
||||
"createdAt": "2024-01-01T00:00:00.000Z",
|
||||
"updatedAt": "2024-01-01T00:00:00.000Z"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**错误代码:**
|
||||
- `401`: 未授权访问
|
||||
- `404`: 用户不存在
|
||||
- `500`: 服务器内部错误
|
||||
|
||||
## 🧳 旅行结伴模块
|
||||
|
||||
### 发布旅行计划
|
||||
|
||||
**Endpoint:** `POST /api/v1/travel/plans`
|
||||
|
||||
**请求头:**
|
||||
```
|
||||
Authorization: Bearer <token>
|
||||
```
|
||||
|
||||
**请求参数:**
|
||||
```json
|
||||
{
|
||||
"destination": "string, required, 目的地",
|
||||
"startDate": "string, required, 开始日期(YYYY-MM-DD)",
|
||||
"endDate": "string, required, 结束日期(YYYY-MM-DD)",
|
||||
"budget": "number, optional, 预算",
|
||||
"interests": "string, optional, 兴趣偏好",
|
||||
"description": "string, optional, 行程描述",
|
||||
"visibility": "string, optional, 可见性(public/friends/private)"
|
||||
}
|
||||
```
|
||||
|
||||
**响应示例:**
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"message": "旅行计划发布成功",
|
||||
"data": {
|
||||
"id": 1001,
|
||||
"userId": 1,
|
||||
"destination": "云南大理",
|
||||
"startDate": "2024-06-01",
|
||||
"endDate": "2024-06-07",
|
||||
"budget": 2000,
|
||||
"interests": "美食,摄影,文化",
|
||||
"status": "active",
|
||||
"createdAt": "2024-01-01T00:00:00.000Z"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 获取旅行计划列表
|
||||
|
||||
**Endpoint:** `GET /api/v1/travel/plans`
|
||||
|
||||
**请求头:**
|
||||
```
|
||||
Authorization: Bearer <token>
|
||||
```
|
||||
|
||||
**查询参数:**
|
||||
```
|
||||
?page=1&limit=10&destination=大理&startDate=2024-06-01&endDate=2024-06-30
|
||||
```
|
||||
|
||||
| 参数 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| page | number | 页码,默认1 |
|
||||
| limit | number | 每页数量,默认10 |
|
||||
| destination | string | 目的地过滤 |
|
||||
| startDate | string | 开始日期过滤 |
|
||||
| endDate | string | 结束日期过滤 |
|
||||
| budgetMin | number | 最低预算 |
|
||||
| budgetMax | number | 最高预算 |
|
||||
|
||||
**响应示例:**
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"message": "获取成功",
|
||||
"data": {
|
||||
"items": [
|
||||
{
|
||||
"id": 1001,
|
||||
"userId": 1,
|
||||
"userInfo": {
|
||||
"nickname": "旅行达人",
|
||||
"avatar": "https://avatar.url"
|
||||
},
|
||||
"destination": "云南大理",
|
||||
"startDate": "2024-06-01",
|
||||
"endDate": "2024-06-07",
|
||||
"budget": 2000,
|
||||
"interests": "美食,摄影,文化",
|
||||
"matchScore": 85,
|
||||
"createdAt": "2024-01-01T00:00:00.000Z"
|
||||
}
|
||||
],
|
||||
"pagination": {
|
||||
"page": 1,
|
||||
"limit": 10,
|
||||
"total": 100,
|
||||
"pages": 10
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 发起结伴邀请
|
||||
|
||||
**Endpoint:** `POST /api/v1/travel/invitations`
|
||||
|
||||
**请求头:**
|
||||
```
|
||||
Authorization: Bearer <token>
|
||||
```
|
||||
|
||||
**请求参数:**
|
||||
```json
|
||||
{
|
||||
"travelPlanId": "number, required, 旅行计划ID",
|
||||
"inviteeId": "number, required, 被邀请用户ID",
|
||||
"message": "string, optional, 邀请消息"
|
||||
}
|
||||
```
|
||||
|
||||
**响应示例:**
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"message": "邀请发送成功",
|
||||
"data": {
|
||||
"id": 5001,
|
||||
"travelPlanId": 1001,
|
||||
"inviterId": 1,
|
||||
"inviteeId": 2,
|
||||
"status": "pending",
|
||||
"message": "一起结伴去大理吧!",
|
||||
"createdAt": "2024-01-01T00:00:00.000Z"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 🐄 动物认领模块
|
||||
|
||||
### 获取可认领动物列表
|
||||
|
||||
**Endpoint:** `GET /api/v1/animals/available`
|
||||
|
||||
**查询参数:**
|
||||
```
|
||||
?page=1&limit=10&species=牛&farmLocation=云南
|
||||
```
|
||||
|
||||
| 参数 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| page | number | 页码,默认1 |
|
||||
| limit | number | 每页数量,默认10 |
|
||||
| species | string | 动物种类过滤 |
|
||||
| breed | string | 品种过滤 |
|
||||
| farmLocation | string | 农场位置过滤 |
|
||||
| priceMin | number | 最低价格 |
|
||||
| priceMax | number | 最高价格 |
|
||||
|
||||
**响应示例:**
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"message": "获取成功",
|
||||
"data": {
|
||||
"items": [
|
||||
{
|
||||
"id": 2001,
|
||||
"name": "小白",
|
||||
"species": "牛",
|
||||
"breed": "荷斯坦",
|
||||
"birthDate": "2023-01-15",
|
||||
"personality": "温顺亲人",
|
||||
"farmLocation": "云南大理幸福农场",
|
||||
"price": 2999,
|
||||
"images": ["https://animal.image1.jpg", "https://animal.image2.jpg"],
|
||||
"merchantInfo": {
|
||||
"businessName": "幸福农场",
|
||||
"contactPerson": "张老板"
|
||||
},
|
||||
"claimCount": 3,
|
||||
"createdAt": "2024-01-01T00:00:00.000Z"
|
||||
}
|
||||
],
|
||||
"pagination": {
|
||||
"page": 1,
|
||||
"limit": 10,
|
||||
"total": 50,
|
||||
"pages": 5
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 认领动物
|
||||
|
||||
**Endpoint:** `POST /api/v1/animals/claim`
|
||||
|
||||
**请求头:**
|
||||
```
|
||||
Authorization: Bearer <token>
|
||||
```
|
||||
|
||||
**请求参数:**
|
||||
```json
|
||||
{
|
||||
"animalId": "number, required, 动物ID",
|
||||
"duration": "number, required, 认领时长(月)",
|
||||
"agreementAccepted": "boolean, required, 是否接受协议"
|
||||
}
|
||||
```
|
||||
|
||||
**响应示例:**
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"message": "认领成功",
|
||||
"data": {
|
||||
"id": 3001,
|
||||
"userId": 1,
|
||||
"animalId": 2001,
|
||||
"animalName": "小白",
|
||||
"duration": 12,
|
||||
"totalAmount": 35988,
|
||||
"status": "paid",
|
||||
"startDate": "2024-01-01",
|
||||
"endDate": "2025-01-01",
|
||||
"createdAt": "2024-01-01T00:00:00.000Z"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 💐 送花服务模块
|
||||
|
||||
### 获取鲜花商品列表
|
||||
|
||||
**Endpoint:** `GET /api/v1/flower/products`
|
||||
|
||||
**查询参数:**
|
||||
```
|
||||
?page=1&limit=10&category=情人节&merchantId=1
|
||||
```
|
||||
|
||||
| 参数 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| page | number | 页码,默认1 |
|
||||
| limit | number | 每页数量,默认10 |
|
||||
| category | string | 商品分类过滤 |
|
||||
| merchantId | number | 商家ID过滤 |
|
||||
| priceMin | number | 最低价格 |
|
||||
| priceMax | number | 最高价格 |
|
||||
|
||||
**响应示例:**
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"message": "获取成功",
|
||||
"data": {
|
||||
"items": [
|
||||
{
|
||||
"id": 4001,
|
||||
"name": "红玫瑰礼盒",
|
||||
"description": "11朵红玫瑰精美礼盒",
|
||||
"price": 199,
|
||||
"originalPrice": 259,
|
||||
"images": ["https://flower.image1.jpg"],
|
||||
"category": "情人节",
|
||||
"merchantInfo": {
|
||||
"businessName": "爱之花店",
|
||||
"contactPhone": "13800138000"
|
||||
},
|
||||
"salesCount": 150,
|
||||
"rating": 4.8,
|
||||
"status": "active",
|
||||
"createdAt": "2024-01-01T00:00:00.000Z"
|
||||
}
|
||||
],
|
||||
"pagination": {
|
||||
"page": 1,
|
||||
"limit": 10,
|
||||
"total": 100,
|
||||
"pages": 10
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 下单送花
|
||||
|
||||
**Endpoint:** `POST /api/v1/flower/orders`
|
||||
|
||||
**请求头:**
|
||||
```
|
||||
Authorization: Bearer <token>
|
||||
```
|
||||
|
||||
**请求参数:**
|
||||
```json
|
||||
{
|
||||
"productId": "number, required, 商品ID",
|
||||
"quantity": "number, required, 数量",
|
||||
"recipientInfo": {
|
||||
"name": "string, required, 收花人姓名",
|
||||
"phone": "string, required, 收花人电话",
|
||||
"address": "string, required, 配送地址"
|
||||
},
|
||||
"deliveryDate": "string, required, 配送日期(YYYY-MM-DD)",
|
||||
"message": "string, optional, 祝福语"
|
||||
}
|
||||
```
|
||||
|
||||
**响应示例:**
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"message": "下单成功",
|
||||
"data": {
|
||||
"id": 5001,
|
||||
"orderNo": "FLOWER202401010001",
|
||||
"productId": 4001,
|
||||
"productName": "红玫瑰礼盒",
|
||||
"quantity": 1,
|
||||
"totalAmount": 199,
|
||||
"recipientName": "李小姐",
|
||||
"recipientPhone": "13800138001",
|
||||
"deliveryAddress": "北京市朝阳区xxx路xxx号",
|
||||
"deliveryDate": "2024-02-14",
|
||||
"status": "pending",
|
||||
"createdAt": "2024-01-01T00:00:00.000Z"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 📊 数据字典
|
||||
|
||||
### 旅行计划状态
|
||||
| 状态值 | 描述 |
|
||||
|--------|------|
|
||||
| active | 活跃中 |
|
||||
| completed | 已完成 |
|
||||
| cancelled | 已取消 |
|
||||
|
||||
### 结伴邀请状态
|
||||
| 状态值 | 描述 |
|
||||
|--------|------|
|
||||
| pending | 待接受 |
|
||||
| accepted | 已接受 |
|
||||
| rejected | 已拒绝 |
|
||||
| cancelled | 已取消 |
|
||||
|
||||
### 动物认领状态
|
||||
| 状态值 | 描述 |
|
||||
|--------|------|
|
||||
| pending | 待支付 |
|
||||
| paid | 已支付 |
|
||||
| active | 认领中 |
|
||||
| completed | 已完成 |
|
||||
| cancelled | 已取消 |
|
||||
|
||||
### 送花订单状态
|
||||
| 状态值 | 描述 |
|
||||
|--------|------|
|
||||
| pending | 待支付 |
|
||||
| paid | 已支付 |
|
||||
| confirmed | 商家已确认 |
|
||||
| delivering | 配送中 |
|
||||
| completed | 已完成 |
|
||||
| cancelled | 已取消 |
|
||||
|
||||
### 错误代码
|
||||
| 代码 | 描述 |
|
||||
|------|------|
|
||||
| 200 | 成功 |
|
||||
| 400 | 请求参数错误 |
|
||||
| 401 | 未授权访问 |
|
||||
| 403 | 禁止访问 |
|
||||
| 404 | 资源不存在 |
|
||||
| 409 | 资源冲突 |
|
||||
| 429 | 请求过于频繁 |
|
||||
| 500 | 服务器内部错误 |
|
||||
| 503 | 服务不可用 |
|
||||
|
||||
## 🔗 API 版本控制
|
||||
|
||||
当前API版本为v1,所有接口前缀为`/api/v1/`。
|
||||
|
||||
版本更新策略:
|
||||
- 向后兼容的修改直接更新
|
||||
- 不兼容的修改创建新版本v2
|
||||
- 旧版本API保持维护至少6个月
|
||||
|
||||
## 📡 接口限流
|
||||
|
||||
### 限流策略
|
||||
- 匿名用户: 60请求/分钟
|
||||
- 认证用户: 120请求/分钟
|
||||
- VIP用户: 300请求/分钟
|
||||
|
||||
### 限流响应
|
||||
当超过限流阈值时返回:
|
||||
```json
|
||||
{
|
||||
"code": 429,
|
||||
"message": "请求过于频繁,请稍后再试",
|
||||
"retryAfter": 60
|
||||
}
|
||||
```
|
||||
|
||||
## 🧪 接口测试
|
||||
|
||||
### 使用curl测试
|
||||
```bash
|
||||
# 微信用户登录
|
||||
curl -X POST http://localhost:3000/api/v1/auth/wechat-login \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"code":"wxlogincode123","userInfo":{"nickName":"测试用户","avatarUrl":"https://avatar.url","gender":1}}'
|
||||
|
||||
# 获取旅行计划列表
|
||||
curl -X GET http://localhost:3000/api/v1/travel/plans \
|
||||
-H "Authorization: Bearer <token>"
|
||||
```
|
||||
|
||||
### 使用Postman测试
|
||||
1. 导入Postman集合文件
|
||||
2. 设置环境变量(base_url, token等)
|
||||
3. 运行测试用例
|
||||
|
||||
## 📝 更新日志
|
||||
|
||||
### v1.0.0 (2024-01-01)
|
||||
- 微信用户登录接口
|
||||
- 旅行结伴管理接口
|
||||
- 动物认领管理接口
|
||||
- 送花服务接口
|
||||
- 基础认证系统
|
||||
|
||||
---
|
||||
*最后更新: 2024年* 📅
|
||||
@@ -1,41 +1,50 @@
|
||||
# 结伴客系统架构文档
|
||||
# 🏗️ 系统架构文档
|
||||
|
||||
## 1. 系统架构概览
|
||||
## 📋 项目概述
|
||||
杰邦科项目是一个综合性的管理系统,包含后台管理、微信小程序和官网三个主要模块。
|
||||
|
||||
### 1.1 架构图
|
||||
## 🎯 技术栈
|
||||
|
||||
### 后端技术栈
|
||||
- **运行时**: Node.js + Express.js
|
||||
- **数据库**: MySQL 8.0
|
||||
- **ORM**: Sequelize
|
||||
- **认证**: JWT + bcrypt
|
||||
- **缓存**: Redis (可选)
|
||||
- **消息队列**: RabbitMQ (可选)
|
||||
|
||||
### 前端技术栈
|
||||
- **后台管理系统**: Vue 3 + Element Plus
|
||||
- **微信小程序**: 原生小程序 + Vant Weapp
|
||||
- **官方网站**: Vue 3 + Vue Router
|
||||
|
||||
### 开发工具
|
||||
- **包管理**: npm
|
||||
- **容器化**: Docker + Docker Compose
|
||||
- **代码质量**: ESLint + Prettier
|
||||
- **测试**: Jest + Supertest
|
||||
|
||||
## 🏢 系统架构
|
||||
|
||||
```mermaid
|
||||
graph TB
|
||||
subgraph "客户端层"
|
||||
A[微信小程序 uni-app]
|
||||
B[后台管理系统 Vue 3 + Ant Design]
|
||||
C[官网系统 HTML5 + Bootstrap]
|
||||
subgraph "前端应用"
|
||||
A[后台管理系统]
|
||||
B[微信小程序]
|
||||
C[官方网站]
|
||||
end
|
||||
|
||||
subgraph "接入层"
|
||||
D[Express API Gateway]
|
||||
subgraph "后端服务"
|
||||
D[API Gateway]
|
||||
E[用户服务]
|
||||
F[业务服务]
|
||||
G[文件服务]
|
||||
end
|
||||
|
||||
subgraph "应用服务层"
|
||||
E[认证服务]
|
||||
F[用户服务]
|
||||
G[旅行服务]
|
||||
H[动物服务]
|
||||
I[订单服务]
|
||||
J[管理员服务]
|
||||
end
|
||||
|
||||
subgraph "基础设施层"
|
||||
K[MySQL 数据库]
|
||||
L[Redis 缓存]
|
||||
M[RabbitMQ 消息队列]
|
||||
N[文件存储]
|
||||
end
|
||||
|
||||
subgraph "监控运维层"
|
||||
O[Swagger API 文档]
|
||||
P[Winston 日志系统]
|
||||
Q[健康检查监控]
|
||||
subgraph "数据层"
|
||||
H[MySQL]
|
||||
I[Redis]
|
||||
J[MinIO]
|
||||
end
|
||||
|
||||
A --> D
|
||||
@@ -44,527 +53,351 @@ graph TB
|
||||
D --> E
|
||||
D --> F
|
||||
D --> G
|
||||
D --> H
|
||||
D --> I
|
||||
D --> J
|
||||
|
||||
E --> K
|
||||
F --> K
|
||||
G --> K
|
||||
H --> K
|
||||
I --> K
|
||||
J --> K
|
||||
|
||||
E --> L
|
||||
F --> L
|
||||
G --> L
|
||||
|
||||
I --> M
|
||||
|
||||
E --> N
|
||||
F --> N
|
||||
H --> N
|
||||
|
||||
D --> O
|
||||
D --> P
|
||||
D --> Q
|
||||
E --> H
|
||||
F --> H
|
||||
G --> J
|
||||
E --> I
|
||||
```
|
||||
|
||||
**系统架构层次说明:**
|
||||
## 🗄️ 数据库设计
|
||||
|
||||
**1. 客户端层**
|
||||
- **微信小程序**: 基于uni-app开发,提供用户端功能
|
||||
- **后台管理系统**: 基于Vue.js 3 + TypeScript + Ant Design Vue + Pinia开发,提供管理功能
|
||||
- **官网系统**: 基于HTML5 + Bootstrap开发,提供企业宣传功能
|
||||
### 核心表结构设计
|
||||
|
||||
**2. 接入层**
|
||||
- **API网关**: 基于Express.js框架,提供统一的API接入、路由分发、安全防护和请求处理,所有API路径前缀为`/api/v1`
|
||||
|
||||
**3. 应用服务层**
|
||||
- **认证服务**: 用户身份认证、JWT令牌管理和权限控制
|
||||
- **用户服务**: 用户信息管理、个人中心功能和用户统计
|
||||
- **旅行服务**: 旅行计划创建、查询、匹配和管理功能
|
||||
- **动物服务**: 动物信息管理、认领流程和动物统计
|
||||
- **订单服务**: 订单创建、支付处理和交易管理
|
||||
- **管理员服务**: 管理员权限管理和系统配置
|
||||
|
||||
**4. 基础设施层**
|
||||
- **MySQL数据库**: 单实例架构,存储核心业务数据,使用连接池优化性能(测试环境: 192.168.0.240:3306,生产环境: 129.211.213.226:9527)
|
||||
- **Redis缓存**: 单实例模式,提供会话管理和数据缓存服务
|
||||
- **RabbitMQ消息队列**: 异步消息处理和解耦(待实现)
|
||||
- **文件存储**: 本地文件系统,存储用户上传的图片和文件资源
|
||||
|
||||
**5. 监控运维层**
|
||||
- **Swagger API文档**: 自动生成的API接口文档
|
||||
- **Winston日志系统**: 结构化日志记录和分析
|
||||
- **健康检查监控**: 系统状态监控和性能统计
|
||||
|
||||
**架构连接关系:**
|
||||
- 所有客户端通过API网关访问后端服务
|
||||
- 应用服务层各服务独立部署,通过API网关统一暴露接口
|
||||
- 认证服务、用户服务、旅行服务、动物服务、商家服务连接MySQL数据库和Redis缓存
|
||||
- 支付服务和推广服务连接MySQL数据库和RabbitMQ消息队列
|
||||
- 认证服务、用户服务、动物服务、商家服务连接对象存储
|
||||
- 监控系统、日志系统、CI/CD系统监控所有应用服务
|
||||
|
||||
## 2. 项目结构
|
||||
|
||||
```
|
||||
结伴客项目 (根目录)
|
||||
├── mini-program // 微信小程序 (uni-app)
|
||||
│ ├── pages
|
||||
│ │ ├── user // 用户相关页面
|
||||
│ │ │ ├── login // 登录页面
|
||||
│ │ │ ├── register // 注册页面
|
||||
│ │ │ ├── profile // 个人主页
|
||||
│ │ │ └── settings // 设置页面
|
||||
│ │ ├── merchant // 商家相关页面
|
||||
│ │ │ ├── register // 商家注册
|
||||
│ │ │ ├── profile // 商家主页
|
||||
│ │ │ └── dashboard // 商家控制台
|
||||
│ │ ├── travel // 旅行结伴页面
|
||||
│ │ │ ├── plan // 旅行计划
|
||||
│ │ │ ├── search // 搜索结伴
|
||||
│ │ │ └── activities // 其他活动
|
||||
│ │ ├── animal // 动物认领页面
|
||||
│ │ │ ├── list // 动物列表
|
||||
│ │ │ ├── detail // 动物详情
|
||||
│ │ │ └── claim // 认领流程
|
||||
│ │ ├── social // 社交互动页面
|
||||
│ │ │ ├── messages // 消息聊天
|
||||
│ │ │ └── feed // 动态分享
|
||||
│ │ ├── flower // 送花服务页面
|
||||
│ │ │ ├── products // 鲜花产品
|
||||
│ │ │ └── orders // 订单管理
|
||||
│ │ └── promotion // 推广奖励页面
|
||||
│ │ ├── invite // 邀请推广
|
||||
│ │ └── rewards // 奖励中心
|
||||
│ ├── components // 可复用组件
|
||||
│ │ ├── common // 通用组件
|
||||
│ │ ├── user // 用户相关组件
|
||||
│ │ ├── travel // 旅行相关组件
|
||||
│ │ ├── animal // 动物相关组件
|
||||
│ │ ├── social // 社交相关组件
|
||||
│ │ ├── merchant // 商家相关组件
|
||||
│ │ └── flower // 鲜花相关组件
|
||||
│ ├── utils // 工具函数
|
||||
│ │ ├── request // 网络请求封装
|
||||
│ │ ├── auth // 认证相关工具
|
||||
│ │ ├── storage // 存储相关工具
|
||||
│ │ └── helpers // 辅助函数
|
||||
│ ├── static // 静态资源
|
||||
│ │ ├── images // 图片资源
|
||||
│ │ └── styles // 样式文件
|
||||
│ └── store // 状态管理
|
||||
│ ├── modules // 模块化状态
|
||||
│ │ ├── user // 用户状态
|
||||
│ │ ├── travel // 旅行状态
|
||||
│ │ ├── animal // 动物状态
|
||||
│ │ ├── social // 社交状态
|
||||
│ │ ├── merchant // 商家状态
|
||||
│ │ ├── flower // 鲜花状态
|
||||
│ │ └── promotion // 推广状态
|
||||
│ └── index.js // 状态管理入口
|
||||
├── admin-system // 后台管理系统 (Vue.js 3 + TypeScript + Ant Design Vue + Pinia)
|
||||
│ ├── public // 静态资源
|
||||
│ ├── src
|
||||
│ │ ├── api // API接口 (TypeScript类型定义)
|
||||
│ │ │ ├── user // 用户相关接口
|
||||
│ │ │ ├── merchant // 商家相关接口
|
||||
│ │ │ ├── travel // 旅行相关接口
|
||||
│ │ │ ├── animal // 动物相关接口
|
||||
│ │ │ ├── order // 订单相关接口
|
||||
│ │ │ ├── promotion // 推广相关接口
|
||||
│ │ │ └── system // 系统管理接口
|
||||
│ │ ├── assets // 静态资源
|
||||
│ │ ├── components // 公共组件 (Vue 3 Composition API)
|
||||
│ │ │ ├── layout // 布局组件
|
||||
│ │ │ ├── common // 通用组件
|
||||
│ │ │ ├── user // 用户相关组件
|
||||
│ │ │ ├── merchant // 商家相关组件
|
||||
│ │ │ ├── travel // 旅行相关组件
|
||||
│ │ │ ├── animal // 动物相关组件
|
||||
│ │ │ ├── order // 订单相关组件
|
||||
│ │ │ ├── promotion // 推广相关组件
|
||||
│ │ │ └── dashboard // 仪表板组件
|
||||
│ │ ├── composables // 组合式函数 (Vue 3 Composition API)
|
||||
│ │ ├── directives // 自定义指令
|
||||
│ │ ├── layouts // 页面布局
|
||||
│ │ │ ├── default.vue // 默认布局
|
||||
│ │ │ ├── auth.vue // 认证布局
|
||||
│ │ │ └── empty.vue // 空白布局
|
||||
│ │ ├── locales // 国际化资源
|
||||
│ │ │ ├── zh-CN.json // 中文语言包
|
||||
│ │ │ └── en-US.json // 英文语言包
|
||||
│ │ ├── pages // 页面视图 (Vue 3 + TypeScript)
|
||||
│ │ │ ├── dashboard // 仪表板页面
|
||||
│ │ │ ├── user // 用户管理页面
|
||||
│ │ │ ├── merchant // 商家管理页面
|
||||
│ │ │ ├── travel // 旅行管理页面
|
||||
│ │ │ ├── animal // 动物管理页面
|
||||
│ │ │ ├── order // 订单管理页面
|
||||
│ │ │ ├── promotion // 推广管理页面
|
||||
│ │ │ ├── system // 系统管理页面
|
||||
│ │ │ ├── login.vue // 登录页面
|
||||
│ │ │ └── register.vue // 注册页面
|
||||
│ │ ├── plugins // 插件
|
||||
│ │ ├── router // 路由配置 (Vue Router 4 + TypeScript)
|
||||
│ │ │ ├── modules // 模块路由
|
||||
│ │ │ │ ├── user.ts // 用户路由
|
||||
│ │ │ │ ├── merchant.ts // 商家路由
|
||||
│ │ │ │ ├── travel.ts // 旅行路由
|
||||
│ │ │ │ ├── animal.ts // 动物路由
|
||||
│ │ │ │ ├── order.ts // 订单路由
|
||||
│ │ │ │ ├── promotion.ts // 推广路由
|
||||
│ │ │ │ └── system.ts // 系统路由
|
||||
│ │ │ └── index.ts // 路由入口
|
||||
│ │ ├── stores // 状态管理 (Pinia 2 + TypeScript)
|
||||
│ │ │ ├── modules // 模块状态
|
||||
│ │ │ │ ├── user.ts // 用户状态
|
||||
│ │ │ │ ├── merchant.ts // 商家状态
|
||||
│ │ │ │ ├── travel.ts // 旅行状态
|
||||
│ │ │ │ ├── animal.ts // 动物状态
|
||||
│ │ │ │ ├── order.ts // 订单状态
|
||||
│ │ │ │ ├── promotion.ts // 推广状态
|
||||
│ │ │ │ └── system.ts // 系统状态
|
||||
│ │ │ └── index.ts // 状态管理入口
|
||||
│ │ ├── styles // 样式文件
|
||||
│ │ ├── types // TypeScript类型定义
|
||||
│ │ ├── utils // 工具函数 (TypeScript)
|
||||
│ │ │ ├── request.ts // 请求封装 (Axios + TypeScript)
|
||||
│ │ │ ├── auth.ts // 认证工具
|
||||
│ │ │ ├── storage.ts // 存储工具
|
||||
│ │ │ ├── format.ts // 格式化工具
|
||||
│ │ │ └── validate.ts // 验证工具
|
||||
│ │ └── App.vue // 根组件 (Vue 3 + TypeScript)
|
||||
│ │ └── main.ts // 入口文件 (Vue 3 + TypeScript + Pinia + Ant Design Vue)
|
||||
│ ├── tests // 测试目录 (Vitest + Vue Test Utils)
|
||||
│ ├── .env // 环境配置
|
||||
│ ├── .env.development // 开发环境配置
|
||||
│ ├── .env.production // 生产环境配置
|
||||
│ ├── index.html // HTML模板
|
||||
│ ├── tsconfig.json // TypeScript配置 (严格模式)
|
||||
│ ├── vite.config.ts // 构建配置 (Vite 4 + TypeScript)
|
||||
│ └── package.json // 依赖配置 (Vue 3 + TypeScript + Ant Design Vue + Pinia)
|
||||
├── website // 官网系统 (HTML5 + Bootstrap)
|
||||
│ ├── index.html // 首页
|
||||
│ ├── about.html // 关于我们
|
||||
│ ├── contact.html // 联系我们
|
||||
│ ├── merchant // 商家合作页面
|
||||
│ │ ├── index.html // 商家合作首页
|
||||
│ │ ├── policy.html // 合作政策
|
||||
│ │ └── apply.html // 入驻申请
|
||||
│ ├── case.html // 案例展示
|
||||
│ ├── css // 样式文件
|
||||
│ │ ├── bootstrap.min.css // Bootstrap样式
|
||||
│ │ └── custom.css // 自定义样式
|
||||
│ ├── js // JavaScript文件
|
||||
│ │ ├── bootstrap.min.js // Bootstrap脚本
|
||||
│ │ └── custom.js // 自定义脚本
|
||||
│ ├── images // 图片资源
|
||||
│ └── vendor // 第三方库
|
||||
├── backend // 后端接口服务 (Node.js + Express)
|
||||
│ ├── src
|
||||
│ │ ├── controllers // 控制器层
|
||||
│ │ │ ├── user // 用户控制器
|
||||
│ │ │ ├── merchant // 商家控制器
|
||||
│ │ │ ├── travel // 旅行控制器
|
||||
│ │ │ ├── animal // 动物控制器
|
||||
│ │ │ ├── social // 社交控制器
|
||||
│ │ │ ├── flower // 鲜花控制器
|
||||
│ │ │ ├── promotion // 推广控制器
|
||||
│ │ │ └── auth // 认证控制器
|
||||
│ │ ├── services // 业务逻辑层
|
||||
│ │ │ ├── user // 用户服务
|
||||
│ │ │ ├── merchant // 商家服务
|
||||
│ │ │ ├── travel // 旅行服务
|
||||
│ │ │ ├── animal // 动物服务
|
||||
│ │ │ ├── social // 社交服务
|
||||
│ │ │ ├── flower // 鲜花服务
|
||||
│ │ │ ├── promotion // 推广服务
|
||||
│ │ │ └── auth // 认证服务
|
||||
│ │ ├── models // 数据模型层
|
||||
│ │ │ ├── user.js // 用户模型
|
||||
│ │ │ ├── merchant.js // 商家模型
|
||||
│ │ │ ├── travelPlan.js // 旅行计划模型
|
||||
│ │ │ ├── animal.js // 动物模型
|
||||
│ │ │ ├── claim.js // 认领模型
|
||||
│ │ │ ├── message.js // 消息模型
|
||||
│ │ │ ├── activity.js // 活动模型
|
||||
│ │ │ ├── product.js // 商品模型
|
||||
│ │ │ ├── order.js // 订单模型
|
||||
│ │ │ ├── review.js // 评价模型
|
||||
│ │ │ └── reward.js // 奖励模型
|
||||
│ │ ├── routes // 路由定义
|
||||
│ │ │ ├── api // API路由
|
||||
│ │ │ │ ├── v1 // v1版本API
|
||||
│ │ │ │ │ ├── user.js // 用户相关API
|
||||
│ │ │ │ │ ├── merchant.js // 商家相关API
|
||||
│ │ │ │ │ ├── travel.js // 旅行相关API
|
||||
│ │ │ │ │ ├── animal.js // 动物相关API
|
||||
│ │ │ │ │ ├── social.js // 社交相关API
|
||||
│ │ │ │ │ ├── flower.js // 鲜花相关API
|
||||
│ │ │ │ │ └── promotion.js // 推广相关API
|
||||
│ │ │ │ └── index.js // API路由入口
|
||||
│ │ │ └── web // Web路由(管理后台)
|
||||
│ │ ├── middleware // 中间件
|
||||
│ │ │ ├── auth // 认证中间件
|
||||
│ │ │ ├── validation // 验证中间件
|
||||
│ │ │ ├── rateLimit // 限流中间件
|
||||
│ │ │ └── error // 错误处理中间件
|
||||
│ │ ├── utils // 工具函数
|
||||
│ │ │ ├── database // 数据库工具
|
||||
│ │ │ ├── logger // 日志工具
|
||||
│ │ │ ├── helpers // 辅助函数
|
||||
│ │ │ └── constants // 常量定义
|
||||
│ │ ├── config // 配置文件
|
||||
│ │ │ ├── database.js // 数据库配置
|
||||
│ │ │ ├── redis.js // Redis配置
|
||||
│ │ │ ├── rabbitmq.js // RabbitMQ配置
|
||||
│ │ │ └── app.js // 应用配置
|
||||
│ │ └── app.js // 应用入口
|
||||
│ ├── tests // 测试目录
|
||||
│ │ ├── unit // 单元测试
|
||||
│ │ └── integration // 集成测试
|
||||
│ ├── docs // 文档目录
|
||||
│ └── package.json // 依赖配置
|
||||
└── docs // 项目文档
|
||||
├── requirements.md // 需求文档
|
||||
├── architecture.md // 架构文档
|
||||
├── detailed_design.md // 详细设计文档
|
||||
└── development_plan.md // 开发计划文档
|
||||
```mermaid
|
||||
erDiagram
|
||||
USERS ||--o{ TRAVEL_PLANS : creates
|
||||
USERS ||--o{ TRAVEL_INVITATIONS : sends
|
||||
USERS ||--o{ TRAVEL_INVITATIONS : receives
|
||||
USERS ||--o{ ANIMAL_CLAIMS : claims
|
||||
USERS ||--o{ FLOWER_ORDERS : places
|
||||
MERCHANTS ||--o{ ANIMALS : owns
|
||||
MERCHANTS ||--o{ FLOWER_PRODUCTS : sells
|
||||
ANIMALS ||--o{ ANIMAL_CLAIMS : claimed_by
|
||||
FLOWER_PRODUCTS ||--o{ FLOWER_ORDERS : ordered
|
||||
TRAVEL_PLANS ||--o{ TRAVEL_INVITATIONS : has
|
||||
|
||||
USERS {
|
||||
int id PK
|
||||
string openid
|
||||
string nickname
|
||||
string avatar
|
||||
string gender
|
||||
date birthday
|
||||
string phone
|
||||
string email
|
||||
int travel_count
|
||||
int animal_claim_count
|
||||
datetime created_at
|
||||
datetime updated_at
|
||||
}
|
||||
|
||||
TRAVEL_PLANS {
|
||||
int id PK
|
||||
int user_id FK
|
||||
string destination
|
||||
date start_date
|
||||
date end_date
|
||||
decimal budget
|
||||
string interests
|
||||
string description
|
||||
string visibility
|
||||
string status
|
||||
datetime created_at
|
||||
datetime updated_at
|
||||
}
|
||||
|
||||
TRAVEL_INVITATIONS {
|
||||
int id PK
|
||||
int travel_plan_id FK
|
||||
int inviter_id FK
|
||||
int invitee_id FK
|
||||
string message
|
||||
string status
|
||||
datetime created_at
|
||||
datetime updated_at
|
||||
}
|
||||
|
||||
ANIMALS {
|
||||
int id PK
|
||||
int merchant_id FK
|
||||
string name
|
||||
string species
|
||||
string breed
|
||||
date birth_date
|
||||
string personality
|
||||
string farm_location
|
||||
decimal price
|
||||
json images
|
||||
int claim_count
|
||||
datetime created_at
|
||||
datetime updated_at
|
||||
}
|
||||
|
||||
ANIMAL_CLAIMS {
|
||||
int id PK
|
||||
int user_id FK
|
||||
int animal_id FK
|
||||
int duration
|
||||
decimal total_amount
|
||||
string status
|
||||
date start_date
|
||||
date end_date
|
||||
datetime created_at
|
||||
datetime updated_at
|
||||
}
|
||||
|
||||
MERCHANTS {
|
||||
int id PK
|
||||
string business_name
|
||||
string contact_person
|
||||
string contact_phone
|
||||
string business_license
|
||||
string address
|
||||
string status
|
||||
datetime created_at
|
||||
datetime updated_at
|
||||
}
|
||||
|
||||
FLOWER_PRODUCTS {
|
||||
int id PK
|
||||
int merchant_id FK
|
||||
string name
|
||||
string description
|
||||
decimal price
|
||||
decimal original_price
|
||||
json images
|
||||
string category
|
||||
int sales_count
|
||||
decimal rating
|
||||
string status
|
||||
datetime created_at
|
||||
datetime updated_at
|
||||
}
|
||||
|
||||
FLOWER_ORDERS {
|
||||
int id PK
|
||||
int user_id FK
|
||||
int product_id FK
|
||||
string order_number
|
||||
int quantity
|
||||
decimal total_amount
|
||||
json recipient_info
|
||||
date delivery_date
|
||||
string message
|
||||
string status
|
||||
datetime created_at
|
||||
datetime updated_at
|
||||
}
|
||||
```
|
||||
|
||||
## 🌐 环境配置
|
||||
|
||||
## 2. 技术栈选型
|
||||
|
||||
### 2.1 后端技术栈
|
||||
|
||||
| 技术组件 | 版本 | 用途 | 选型理由 |
|
||||
|---------|------|------|----------|
|
||||
| Node.js | >=16.0.0 | 运行时环境 | 高性能、异步I/O、丰富的生态系统 |
|
||||
| Express.js | ^4.18.2 | Web框架 | 轻量级、灵活、中间件生态丰富 |
|
||||
| MySQL2 | ^3.14.3 | 数据库驱动 | 支持Promise、连接池、性能优化 |
|
||||
| JWT | ^9.0.2 | 身份认证 | 无状态、安全、易于分布式部署 |
|
||||
| bcryptjs | ^2.4.3 | 密码加密 | 安全性高、性能适中 |
|
||||
| Redis | ^5.8.2 | 缓存/会话 | 内存存储、高性能、支持数据结构 |
|
||||
| RabbitMQ | ^0.10.9 | 消息队列 | 异步处理、系统解耦(待实现) |
|
||||
| Swagger | ^6.2.8 | API文档 | 自动化文档、接口测试 |
|
||||
| Winston | ^3.11.0 | 日志系统 | 结构化日志、多传输方式 |
|
||||
|
||||
### 2.2 安全防护
|
||||
|
||||
| 安全组件 | 版本 | 防护类型 |
|
||||
|----------|------|----------|
|
||||
| Helmet | ^7.1.0 | 安全头部 |
|
||||
| express-rate-limit | ^7.1.5 | 请求限流 |
|
||||
| xss-clean | ^0.1.4 | XSS防护 |
|
||||
| hpp | ^0.2.3 | 参数污染防护 |
|
||||
| express-mongo-sanitize | ^2.2.0 | NoSQL注入防护 |
|
||||
|
||||
### 2.3 前端技术栈
|
||||
|
||||
| 项目 | 技术栈 | 状态 |
|
||||
|------|--------|------|
|
||||
| 微信小程序 | uni-app + Vue 2 | 开发中 |
|
||||
| 后台管理系统 | Vue 3 + TypeScript + Ant Design Vue + Pinia | 开发中 |
|
||||
| 官网系统 | HTML5 + Bootstrap + JavaScript | 待开发 |
|
||||
|
||||
### 2.6 选型理由与对比分析
|
||||
|
||||
#### 后端技术栈选型理由
|
||||
|
||||
**Node.js (TypeScript) + Express.js**
|
||||
- **优势**:
|
||||
- 高性能:Node.js基于事件驱动和非阻塞I/O模型,适合高并发场景
|
||||
- 生态丰富:npm生态系统庞大,可快速集成各种第三方库
|
||||
- 全栈统一:前后端均可使用JavaScript/TypeScript,降低开发成本
|
||||
- 轻量级:Express.js是一个轻量级的Web框架,灵活性高
|
||||
- RBAC支持:完善的权限管理中间件生态,支持JWT和RBAC权限控制
|
||||
- **劣势**:
|
||||
- CPU密集型任务处理能力较弱
|
||||
- 回调地狱问题(TypeScript可有效缓解)
|
||||
|
||||
#### 前端技术栈选型理由
|
||||
|
||||
**uni-app**
|
||||
- **优势**:
|
||||
- 一套代码多端运行:可同时发布到iOS、Android、H5、以及各种小程序平台
|
||||
- 开发生态:基于Vue.js,学习成本低,社区活跃
|
||||
- 性能优化:接近原生应用的性能体验
|
||||
- **劣势**:
|
||||
- 平台限制:某些平台特定功能需要特殊处理
|
||||
- 复杂度:多端兼容可能带来额外的复杂性
|
||||
|
||||
**后台管理系统 (Vue.js 3 + TypeScript + Ant Design Vue + Pinia)**
|
||||
- **优势**:
|
||||
- **类型安全**: TypeScript提供编译时类型检查,减少运行时错误
|
||||
- **开发体验**: Vue 3 Composition API + `<script setup>`语法提供更好的代码组织和复用
|
||||
- **企业级UI**: Ant Design Vue提供专业的企业级UI组件和设计规范
|
||||
- **状态管理**: Pinia提供轻量级、类型安全的状态管理方案,替代Vuex
|
||||
- **构建性能**: Vite构建工具提供极快的开发服务器启动和热重载
|
||||
- **代码质量**: ESLint + Prettier确保代码风格统一和质量
|
||||
- **测试覆盖**: Vitest + Vue Test Utils支持完整的单元测试和组件测试
|
||||
- **劣势**:
|
||||
- 学习曲线: TypeScript和新的Composition API需要一定的学习成本
|
||||
- 包体积: 类型系统和完整工具链会增加最终的包体积
|
||||
|
||||
#### 官网技术栈选型理由
|
||||
|
||||
**HTML5 + Bootstrap**
|
||||
- **优势**:
|
||||
- 简单易用:技术门槛低,开发效率高
|
||||
- 兼容性好:Bootstrap提供了良好的浏览器兼容性
|
||||
- 响应式设计:Bootstrap内置响应式布局,适配各种设备
|
||||
- 社区活跃:Bootstrap拥有庞大的社区和丰富的组件
|
||||
- **劣势**:
|
||||
- 定制性相对较弱:需要额外工作来实现独特的设计效果
|
||||
- 文件体积:Bootstrap框架本身会增加页面加载体积
|
||||
|
||||
#### 数据库选型理由
|
||||
|
||||
**MySQL 5.7**
|
||||
- **优势**:
|
||||
- 成熟稳定:关系型数据库,事务支持完善
|
||||
- 生态丰富:社区活跃,文档齐全
|
||||
- 广泛兼容:MySQL 5.7在生产环境中广泛使用,兼容性好
|
||||
- **劣势**:
|
||||
- 水平扩展性相对较弱
|
||||
- 复杂查询性能可能不如专门的分析型数据库
|
||||
- 缺少MySQL 8.0的一些新特性
|
||||
|
||||
#### 缓存选型理由
|
||||
|
||||
**Redis Cluster**
|
||||
- **优势**:
|
||||
- 高性能:内存数据库,读写速度极快
|
||||
- 分布式支持:Redis Cluster提供高可用和水平扩展能力
|
||||
- 丰富数据结构:支持字符串、哈希、列表、集合等多种数据结构
|
||||
- **劣势**:
|
||||
- 内存成本:数据存储在内存中,成本较高
|
||||
- 持久化性能:持久化操作可能影响性能
|
||||
|
||||
#### 消息队列选型理由
|
||||
|
||||
**RabbitMQ**
|
||||
- **优势**:
|
||||
- 成熟稳定:经过多年发展,稳定性好
|
||||
- 协议支持:支持多种消息协议
|
||||
- 灵活路由:支持多种消息路由模式
|
||||
- **劣势**:
|
||||
- 吞吐量:相比Kafka等大数据消息队列,吞吐量较低
|
||||
- Erlang语言:维护和调优需要掌握Erlang语言
|
||||
|
||||
**WebSocket**
|
||||
- **优势**:
|
||||
- 实时性:全双工通信,实时性好
|
||||
- 节省资源:相比轮询,节省网络资源
|
||||
- **劣势**:
|
||||
- 连接管理:需要处理连接断开重连等问题
|
||||
- 浏览器兼容性:老旧浏览器支持不好
|
||||
|
||||
## 3. 部署视图
|
||||
|
||||
```
|
||||
外网:
|
||||
├── uni-app前端用户 --- HTTPS --> API网关
|
||||
├── 官网用户 --- HTTPS --> Nginx反向代理 --> 官网系统
|
||||
├── 后台管理系统用户 --- HTTPS --> API网关 (Vue 3 + TypeScript + Ant Design Vue + Pinia)
|
||||
└── 第三方支付平台 <-- 支付回调 --- 后端服务
|
||||
|
||||
腾讯云服务器:
|
||||
├── Nginx反向代理 --> 官网系统
|
||||
│ ├── 静态资源服务
|
||||
│ └── SSR渲染服务 (Nuxt.js)
|
||||
├── API网关 --> 后端服务
|
||||
│ ├── 用户端API服务 (小程序接口)
|
||||
│ ├── 管理端API服务 (后台管理接口 - Vue 3 + TypeScript + Ant Design Vue + Pinia)
|
||||
│ └── 公共服务 (认证、权限等)
|
||||
├── 后端服务 --> MySQL数据库 (包含RBAC权限表)
|
||||
├── 后端服务 --> Redis缓存 (会话和权限缓存)
|
||||
├── 后端服务 --> RabbitMQ消息队列
|
||||
└── 后端服务 --监控--> Prometheus监控 --> Grafana
|
||||
|--> ELK Stack
|
||||
### 开发环境 (Development)
|
||||
```env
|
||||
DB_HOST=localhost
|
||||
DB_PORT=3306
|
||||
DB_USER=root
|
||||
DB_PASSWORD=rootpassword
|
||||
DB_DATABASE=jiebanke_dev
|
||||
NODE_ENV=development
|
||||
```
|
||||
|
||||
### 3.1 部署环境
|
||||
- 云服务提供商:腾讯云
|
||||
- 服务器配置:4台4核8GB服务器组成Kubernetes集群
|
||||
- 负载均衡:腾讯云负载均衡CLB
|
||||
- SSL证书:腾讯云SSL证书服务
|
||||
- 域名解析:腾讯云DNS解析
|
||||
- 对象存储:腾讯云COS(用于存储图片、视频等静态资源)
|
||||
- CDN加速:腾讯云CDN(用于加速静态资源访问)
|
||||
- 反向代理:Nginx
|
||||
- 静态资源服务器:Nginx
|
||||
### 测试环境 (Test)
|
||||
```env
|
||||
DB_HOST=192.168.0.240
|
||||
DB_PORT=3306
|
||||
DB_USER=root
|
||||
DB_PASSWORD=aiotAiot123!
|
||||
DB_DATABASE=jiebandata_test
|
||||
NODE_ENV=test
|
||||
```
|
||||
|
||||
### 3.2 部署流程
|
||||
1. 代码提交到Git仓库触发CI/CD流水线
|
||||
2. 通过Docker构建服务镜像并推送到镜像仓库
|
||||
3. Kubernetes从镜像仓库拉取镜像并部署服务
|
||||
4. 配置健康检查和自动扩缩容策略
|
||||
5. 配置监控和日志收集系统
|
||||
6. 配置域名解析和SSL证书
|
||||
7. 配置Nginx反向代理和静态资源服务器
|
||||
### 生产环境 (Production)
|
||||
```env
|
||||
DB_HOST=129.211.213.226
|
||||
DB_PORT=9527
|
||||
DB_USER=root
|
||||
DB_PASSWORD=Aiot123
|
||||
DB_DATABASE=jiebandata
|
||||
NODE_ENV=production
|
||||
```
|
||||
|
||||
### 3.3 备份与灾备
|
||||
- 数据库每日自动备份到COS
|
||||
- 关键服务配置文件版本化管理
|
||||
- 多可用区部署实现高可用
|
||||
## 🔌 API 设计
|
||||
|
||||
## 4. 风险分析与应对策略
|
||||
### 用户模块接口
|
||||
|
||||
### 4.1 技术风险
|
||||
#### 微信用户登录
|
||||
- **Endpoint:** `POST /api/v1/auth/wechat-login`
|
||||
- **Method:** POST
|
||||
- **Description:** 微信用户登录获取Token
|
||||
- **Request Body:**
|
||||
```json
|
||||
{
|
||||
"code": "string, required",
|
||||
"userInfo": {
|
||||
"nickName": "string, required",
|
||||
"avatarUrl": "string, required",
|
||||
"gender": "number, optional",
|
||||
"province": "string, optional",
|
||||
"city": "string, optional"
|
||||
}
|
||||
}
|
||||
```
|
||||
- **Response:**
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"message": "登录成功",
|
||||
"data": {
|
||||
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
|
||||
"user": {
|
||||
"id": 1,
|
||||
"openid": "wx1234567890",
|
||||
"nickname": "旅行达人",
|
||||
"avatar": "https://avatar.url",
|
||||
"gender": "male",
|
||||
"phone": "13800138000"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### 系统性能瓶颈
|
||||
- **风险描述**:随着用户量增长,系统可能面临性能瓶颈,特别是在高并发场景下。
|
||||
- **应对策略**:
|
||||
- 使用Redis缓存热点数据,减少数据库访问压力
|
||||
- 对数据库进行读写分离和分库分表
|
||||
- 使用CDN加速静态资源访问
|
||||
- 实施自动扩缩容策略,根据负载动态调整服务实例数量
|
||||
#### 获取用户信息
|
||||
- **Endpoint:** `GET /api/v1/users/profile`
|
||||
- **Method:** GET
|
||||
- **Description:** 获取当前登录用户详细信息
|
||||
- **Headers:** `Authorization: Bearer <token>`
|
||||
- **Response:**
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"message": "获取成功",
|
||||
"data": {
|
||||
"id": 1,
|
||||
"openid": "wx1234567890",
|
||||
"nickname": "旅行达人",
|
||||
"avatar": "https://avatar.url",
|
||||
"gender": "male",
|
||||
"birthday": "1990-01-01",
|
||||
"phone": "13800138000",
|
||||
"email": "test@example.com",
|
||||
"travelCount": 5,
|
||||
"animalClaimCount": 2,
|
||||
"createdAt": "2024-01-01T00:00:00.000Z",
|
||||
"updatedAt": "2024-01-01T00:00:00.000Z"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### 数据安全风险
|
||||
- **风险描述**: 系统涉及用户个人信息、支付信息等敏感数据,存在数据泄露风险。管理员后台权限控制不当可能导致数据泄露。
|
||||
- **应对策略**:
|
||||
- 对敏感数据进行加密存储(AES/RSA算法)
|
||||
- 实施严格的访问控制和身份认证机制
|
||||
- 采用RBAC权限模型,严格控制管理员操作权限
|
||||
- 定期进行安全审计和渗透测试
|
||||
- 遵循GDPR等数据保护法规要求
|
||||
- 管理员操作日志记录和审计
|
||||
## 🚀 部署架构
|
||||
|
||||
### 4.2 业务风险
|
||||
### 开发部署
|
||||
```mermaid
|
||||
graph LR
|
||||
A[本地开发机] --> B[Docker Compose]
|
||||
B --> C[MySQL容器]
|
||||
B --> D[Node.js应用]
|
||||
B --> E[Redis容器]
|
||||
```
|
||||
|
||||
#### 用户增长压力
|
||||
- **风险描述**:产品上线后可能面临用户快速增长的压力,对系统稳定性提出挑战。
|
||||
- **应对策略**:
|
||||
- 提前进行压力测试,评估系统承载能力
|
||||
- 设计可水平扩展的架构,支持快速扩容
|
||||
- 制定限流和降级策略,保证核心功能稳定运行
|
||||
### 生产部署
|
||||
```mermaid
|
||||
graph TB
|
||||
subgraph "云服务器"
|
||||
A[Nginx]
|
||||
B[Node.js集群]
|
||||
C[MySQL主从]
|
||||
D[Redis哨兵]
|
||||
end
|
||||
|
||||
A --> B
|
||||
B --> C
|
||||
B --> D
|
||||
```
|
||||
|
||||
#### 商家服务质量风险
|
||||
- **风险描述**: 商家用户提供的服务质量和用户体验直接影响平台声誉。管理员审核不严可能导致低质量商家入驻。
|
||||
- **应对策略**:
|
||||
- 建立商家资质审核机制
|
||||
- 实施用户评价体系,公开服务评价
|
||||
- 建立投诉处理机制,及时处理用户反馈
|
||||
- 对低质量商家实施警告、限流或清退措施
|
||||
- 管理员审核流程标准化和权限分级
|
||||
## 📊 监控与日志
|
||||
|
||||
### 4.3 运维风险
|
||||
- **应用监控**: PM2 + Keymetrics
|
||||
- **日志管理**: Winston + ELK Stack
|
||||
- **性能监控**: New Relic / Datadog
|
||||
- **错误追踪**: Sentry
|
||||
|
||||
#### 系统监控不足
|
||||
- **风险描述**:缺乏有效的监控可能导致问题发现不及时,影响用户体验。
|
||||
- **应对策略**:
|
||||
- 建立全方位监控体系,包括基础设施、应用性能、业务指标等
|
||||
- 设置合理的告警阈值和通知机制
|
||||
- 定期审查和优化监控策略
|
||||
## 🔒 安全架构
|
||||
|
||||
#### 故障恢复能力
|
||||
- **风险描述**:系统故障可能导致服务中断,影响业务连续性。
|
||||
- **应对策略**:
|
||||
- 制定详细的应急预案和故障恢复流程
|
||||
- 定期进行故障演练,验证恢复能力
|
||||
- 实施多可用区部署,提高容灾能力
|
||||
- 建立数据库备份和恢复机制
|
||||
### 认证授权
|
||||
- JWT Token 认证
|
||||
- RBAC (基于角色的访问控制)
|
||||
- API 速率限制
|
||||
|
||||
### 数据安全
|
||||
- HTTPS 加密传输
|
||||
- 密码加盐哈希存储
|
||||
- SQL 注入防护
|
||||
- XSS 攻击防护
|
||||
|
||||
### 网络安全
|
||||
- 防火墙规则
|
||||
- IP 白名单
|
||||
- DDoS 防护
|
||||
|
||||
## 📈 性能优化
|
||||
|
||||
### 数据库优化
|
||||
- 索引优化
|
||||
- 查询缓存
|
||||
- 读写分离
|
||||
|
||||
### 应用优化
|
||||
- 响应压缩
|
||||
- 静态资源CDN
|
||||
- 内存缓存
|
||||
|
||||
### 前端优化
|
||||
- 代码分割
|
||||
- 懒加载
|
||||
- 图片优化
|
||||
|
||||
## 🛠️ 开发规范
|
||||
|
||||
### 代码规范
|
||||
- ESLint + Prettier 统一代码风格
|
||||
- Git Commit 消息规范
|
||||
- 代码审查流程
|
||||
|
||||
### 分支策略
|
||||
- Git Flow 工作流
|
||||
- 功能分支开发
|
||||
- 发布分支管理
|
||||
|
||||
### 测试策略
|
||||
- 单元测试覆盖核心逻辑
|
||||
- 集成测试API接口
|
||||
- E2E测试用户流程
|
||||
|
||||
## 📝 文档体系
|
||||
|
||||
1. **ARCHITECTURE.md** - 系统架构文档 (当前文件)
|
||||
2. **README.md** - 项目说明文档
|
||||
3. **API_DOCS.md** - API接口文档
|
||||
4. **DEPLOYMENT.md** - 部署指南
|
||||
5. **DEVELOPMENT.md** - 开发指南
|
||||
|
||||
## 🎯 后续规划
|
||||
|
||||
### 短期目标
|
||||
- [ ] 完善用户管理系统
|
||||
- [ ] 实现订单业务流程
|
||||
- [ ] 部署测试环境
|
||||
|
||||
### 中期目标
|
||||
- [ ] 微服务架构改造
|
||||
- [ ] 容器化部署
|
||||
- [ ] 自动化测试覆盖
|
||||
|
||||
### 长期目标
|
||||
- [ ] 大数据分析平台
|
||||
- [ ] AI智能推荐
|
||||
- [ ] 多语言国际化
|
||||
|
||||
---
|
||||
*最后更新: 2024年* 📅
|
||||
@@ -1,183 +0,0 @@
|
||||
const mysql = require('mysql2');
|
||||
|
||||
// 数据库配置
|
||||
const configs = [
|
||||
{
|
||||
name: '测试环境',
|
||||
host: '192.168.0.240',
|
||||
port: 3306,
|
||||
user: 'root',
|
||||
password: 'aiot$Aiot123'
|
||||
},
|
||||
{
|
||||
name: '生产环境',
|
||||
host: '129.211.213.226',
|
||||
port: 9527,
|
||||
user: 'root',
|
||||
password: 'aiotAiot123!'
|
||||
}
|
||||
];
|
||||
|
||||
// 创建数据库的SQL语句
|
||||
const createDatabaseSQL = `
|
||||
CREATE DATABASE IF NOT EXISTS jiebandata
|
||||
CHARACTER SET utf8mb4
|
||||
COLLATE utf极4_unicode_ci;
|
||||
`;
|
||||
|
||||
// 创建用户表的SQL语句
|
||||
const createUsersTableSQL = `
|
||||
CREATE TABLE IF NOT EXISTS jiebandata.users (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
openid VARCHAR(64) UNIQUE NOT NULL,
|
||||
nickname VARCHAR(50) NOT NULL,
|
||||
avatar VARCHAR(255),
|
||||
gender ENUM('male', 'female', 'other'),
|
||||
birthday DATE,
|
||||
phone VARCHAR(20) UNIQUE,
|
||||
email VARCHAR(100) UNIQUE,
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
INDEX idx_openid (openid),
|
||||
INDEX idx_phone (phone),
|
||||
INDEX idx_email (email)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
`;
|
||||
|
||||
// 创建商家表的SQL语句
|
||||
const createMerchantsTableSQL = `
|
||||
CREATE TABLE IF NOT EXISTS jiebandata.merchants (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
user_id INT NOT NULL,
|
||||
merchant_type ENUM('flower_shop', 'activity_organizer', 'farm_owner') NOT NULL,
|
||||
business_name VARCHAR(100) NOT NULL,
|
||||
business_license VARCHAR(255),
|
||||
contact_person VARCHAR(50) NOT NULL,
|
||||
contact_phone VARCHAR(20) NOT NULL,
|
||||
address VARCHAR(255),
|
||||
description TEXT,
|
||||
status ENUM('pending', 'approved', 'rejected', 'suspended') NOT NULL DEFAULT 'pending',
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (user_id) REFERENCES users(id),
|
||||
INDEX idx_user_id (user_id),
|
||||
INDEX idx_status (status)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
`;
|
||||
|
||||
// 创建旅行计划表的SQL语句
|
||||
const createTravelPlansTableSQL = `
|
||||
CREATE TABLE IF NOT EXISTS jiebandata.travel_plans (
|
||||
id极INT AUTO_INCREMENT PRIMARY KEY,
|
||||
user_id INT NOT NULL,
|
||||
destination VARCHAR(100) NOT NULL,
|
||||
start_date DATE NOT NULL,
|
||||
end_date DATE NOT NULL,
|
||||
budget DECIMAL(10,2) NOT NULL,
|
||||
interests TEXT,
|
||||
visibility ENUM('public', 'friends', 'private') NOT NULL DEFAULT 'public',
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (user_id) REFERENCES users(id),
|
||||
INDEX idx_user_id (user_id),
|
||||
INDEX idx_destination (destination),
|
||||
INDEX idx_dates (start_date, end_date)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
`;
|
||||
|
||||
function executeSQL(connection, sql, description) {
|
||||
return new Promise((resolve, reject) => {
|
||||
console.log(`🛠️ ${description}...`);
|
||||
connection.query(sql, (err, results) => {
|
||||
if (err) {
|
||||
console.error(`❌ ${description}失败:`, err.message);
|
||||
reject(err);
|
||||
} else {
|
||||
console.log(`✅ ${description}成功`);
|
||||
resolve(results);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
async function initializeDatabase(config) {
|
||||
console.log(`\n🚀 开始初始化 ${config.name} 数据库...`);
|
||||
console.log('='.repeat(60));
|
||||
|
||||
const connection = mysql.createConnection({
|
||||
host: config.host,
|
||||
port: config.port,
|
||||
user: config.user,
|
||||
password: config.password,
|
||||
multipleStatements: true
|
||||
});
|
||||
|
||||
try {
|
||||
// 连接数据库
|
||||
await new Promise((resolve, reject) => {
|
||||
connection.connect((err) => {
|
||||
if (err) reject(err);
|
||||
else resolve();
|
||||
});
|
||||
});
|
||||
|
||||
// 创建数据库
|
||||
await executeSQL(connection, createDatabaseSQL, '创建数据库 jiebandata');
|
||||
|
||||
// 使用新创建的数据库
|
||||
await executeSQL(connection, 'USE jiebandata', '切换到 jiebandata 数据库');
|
||||
|
||||
// 创建用户表
|
||||
await executeSQL(connection, createUsersTableSQL, '创建用户表');
|
||||
|
||||
// 创建商家表
|
||||
await executeSQL(connection, createMerchantsTableSQL, '创建商家表');
|
||||
|
||||
// 创建旅行计划表
|
||||
await executeSQL(connection, createTravelPlansTableSQL, '创建旅行计划表');
|
||||
|
||||
console.log('✅ 数据库初始化完成!');
|
||||
|
||||
return { success: true, message: '数据库初始化成功' };
|
||||
|
||||
} catch (error) {
|
||||
console.error('❌ 数据库初始化失败:', error.message);
|
||||
return { success: false, error: error.message };
|
||||
} finally {
|
||||
// 关闭极接
|
||||
connection.end();
|
||||
console.log('✅ 数据库连接已关闭');
|
||||
}
|
||||
}
|
||||
|
||||
async function main() {
|
||||
console.log('🎯 结伴客系统数据库初始化工具');
|
||||
console.log('='.repeat(60));
|
||||
|
||||
const results = [];
|
||||
|
||||
for (const config of configs) {
|
||||
const result = await initializeDatabase(config);
|
||||
results.push({
|
||||
environment: config.name,
|
||||
success: result.success,
|
||||
message: result.message || result.error
|
||||
});
|
||||
console.log('\n' + '='.repeat(60));
|
||||
}
|
||||
|
||||
// 输出汇总结果
|
||||
console.log('📋 初始化结果汇总:');
|
||||
results.forEach(result => {
|
||||
console.log(`${result.environment}: ${result.success ? '✅ 成功' : '❌ 失败'} - ${result.message}`);
|
||||
});
|
||||
|
||||
if (results.some(r => r.success)) {
|
||||
console.log('\n🎉 数据库初始化完成!现在可以运行测试验证数据库结构。');
|
||||
} else {
|
||||
console.log('\n⚠️ 所有环境初始化失败,请检查网络连接和数据库权限');
|
||||
}
|
||||
}
|
||||
|
||||
// 运行初始化
|
||||
main().catch(console.error);
|
||||
@@ -1,188 +0,0 @@
|
||||
const mysql = require('mysql2');
|
||||
|
||||
// 数据库配置
|
||||
const configs = [
|
||||
{
|
||||
name: '测试环境',
|
||||
host: '192.168.0.240',
|
||||
port: 3306,
|
||||
user: '极',
|
||||
password: 'aiot$Aiot123'
|
||||
},
|
||||
{
|
||||
name: '生产环境',
|
||||
host: '129.211.213.226',
|
||||
port: 9527,
|
||||
user: 'root',
|
||||
password: 'aiotAiot123!'
|
||||
}
|
||||
];
|
||||
|
||||
// 创建数据库的SQL语句
|
||||
const createDatabaseSQL = `
|
||||
CREATE DATABASE IF NOT EXISTS jiebandata
|
||||
CHARACTER SET utf8mb4
|
||||
COLLATE utf8mb4_unicode_ci;
|
||||
`;
|
||||
|
||||
// 创建用户表的SQL语句
|
||||
const createUsersTableSQL = `
|
||||
CREATE TABLE IF NOT EXISTS jiebandata.users (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
openid VARCHAR(64) UNIQUE NOT NULL,
|
||||
nickname VARCHAR(50) NOT NULL,
|
||||
avatar VARCHAR(255),
|
||||
gender ENUM('male', 'female', 'other'),
|
||||
birthday DATE,
|
||||
phone VARCHAR(20) UNIQUE,
|
||||
email VARCHAR(100) UNIQUE,
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
INDEX idx_openid (openid),
|
||||
INDEX idx_phone (phone),
|
||||
INDEX idx_email (email)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf极4 COLLATE=utf8mb4_unicode_ci;
|
||||
`;
|
||||
|
||||
// 创建商家表的SQL语句
|
||||
const createMerchantsTableSQL = `
|
||||
CREATE TABLE IF NOT EXISTS jiebandata.merchants (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
user_id INT NOT NULL,
|
||||
merchant_type ENUM('flower_shop', 'activity_organizer', 'farm_owner') NOT NULL,
|
||||
business_name VARCHAR(100) NOT NULL,
|
||||
business_license VARCHAR(255),
|
||||
contact_person VARCHAR极50) NOT NULL,
|
||||
contact_phone VARCHAR(20) NOT NULL,
|
||||
address VARCHAR(255),
|
||||
description TEXT,
|
||||
status ENUM('pending', 'approved', 'rejected', 'suspended') NOT NULL DEFAULT 'pending',
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (user_id) REFERENCES users(id),
|
||||
INDEX idx_user_id (user_id),
|
||||
INDEX idx_status (status)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
`;
|
||||
|
||||
// 创建旅行计划表的SQL语句
|
||||
const createTravelPlansTableSQL = `
|
||||
CREATE TABLE IF NOT EXISTS jiebandata.travel_plans (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
user_id INT NOT NULL,
|
||||
destination VARCHAR(100) NOT NULL,
|
||||
start_date DATE NOT NULL,
|
||||
end_date DATE NOT NULL,
|
||||
budget DECIMAL(10,2) NOT NULL,
|
||||
interests TEXT,
|
||||
visibility ENUM('public', 'friends', 'private') NOT NULL DEFAULT 'public',
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (user_id) REFERENCES users(id),
|
||||
INDEX idx_user_id (user_id),
|
||||
INDEX idx_destination (destination),
|
||||
INDEX idx_dates (start_date, end_date)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
`;
|
||||
|
||||
// 所有表创建语句
|
||||
const tableCreationSQLs = [
|
||||
createUsersTableSQL,
|
||||
createMerchantsTableSQL,
|
||||
createTravelPlansTableSQL
|
||||
];
|
||||
|
||||
function executeSQL(connection, sql, description) {
|
||||
return new Promise((resolve, reject) => {
|
||||
console.log(`🛠️ ${description}...`);
|
||||
connection.query(sql, (err, results) => {
|
||||
if (err) {
|
||||
console.error(`❌ ${description}失败:`, err.message);
|
||||
reject(err);
|
||||
} else {
|
||||
console.log(`✅ ${description}成功`);
|
||||
resolve(results);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
async function initializeDatabase(config) {
|
||||
console.log(`\n🚀 开始初始化 ${config.name} 数据库...`);
|
||||
console.log('='.repeat(60));
|
||||
|
||||
const connection = mysql.createConnection({
|
||||
host: config.host,
|
||||
port: config.port,
|
||||
user: config.user,
|
||||
password: config.password,
|
||||
multipleStatements: true
|
||||
});
|
||||
|
||||
try {
|
||||
// 连接数据库
|
||||
await new Promise((resolve, reject) => {
|
||||
connection.connect((err) => {
|
||||
if (err) reject(err);
|
||||
else resolve();
|
||||
});
|
||||
});
|
||||
|
||||
// 创建数据库
|
||||
await executeSQL(connection, createDatabaseSQL, '创建数据库 jiebandata');
|
||||
|
||||
// 使用新创建的数据库
|
||||
await executeSQL(connection, 'USE jiebandata', '切换到 jiebandata 数据库');
|
||||
|
||||
// 创建所有表
|
||||
for (let i = 0; i < tableCreationSQLs.length; i++) {
|
||||
await executeSQL(connection, tableCreationSQLs[i], `创建表 ${i + 1}/${tableCreationSQLs.length}`);
|
||||
}
|
||||
|
||||
console.log('✅ 数据库初始化完成!');
|
||||
|
||||
return { success: true, message: '数据库初始化成功' };
|
||||
|
||||
} catch (error) {
|
||||
console.error('❌ 数据库初始化失败:', error.message);
|
||||
return { success: false, error: error.message };
|
||||
} finally {
|
||||
// 关闭连接
|
||||
connection.end();
|
||||
console.log('✅ 数据库连接已关闭');
|
||||
}
|
||||
}
|
||||
|
||||
async function main() {
|
||||
console.log('🎯 结伴客系统数据库初始化工具');
|
||||
console.log('='.repeat(60));
|
||||
|
||||
const results = [];
|
||||
|
||||
for (const config of configs) {
|
||||
const result = await initializeDatabase(config);
|
||||
results.push({
|
||||
environment: config.name,
|
||||
success: result.success,
|
||||
message: result.message || result.error
|
||||
});
|
||||
console.log('\n' + '='.repeat(60));
|
||||
}
|
||||
|
||||
// 输出汇总结果
|
||||
console.log('📋 初始化结果汇总:');
|
||||
results.forEach(result => {
|
||||
console.log(`${result.environment}: ${result.success ? '✅ 成功' : '❌ 失败'} - ${result.message}`);
|
||||
});
|
||||
|
||||
// 检查是否所有环境都成功
|
||||
const allSuccess = results.every(result => result.success);
|
||||
if (allSuccess) {
|
||||
console.log('\n🎉 所有环境数据库初始化成功!');
|
||||
} else {
|
||||
console.log('\n⚠️ 部分环境初始化失败,请检查网络连接和数据库权限');
|
||||
}
|
||||
}
|
||||
|
||||
// 运行初始化
|
||||
main().catch(console.error);
|
||||
221
init-database.js
221
init-database.js
@@ -1,221 +0,0 @@
|
||||
const mysql = require('mysql2');
|
||||
|
||||
// 数据库配置
|
||||
const configs = [
|
||||
{
|
||||
name: '测试环境',
|
||||
host: '192.168.0.240',
|
||||
port: 3306,
|
||||
user: 'root',
|
||||
password: 'aiot$Aiot123'
|
||||
},
|
||||
{
|
||||
name: '生产环境',
|
||||
host: '129.211.213.226',
|
||||
port: 9527,
|
||||
user: 'root',
|
||||
password: 'aiotAiot123!'
|
||||
}
|
||||
];
|
||||
|
||||
// 创建数据库的SQL语句
|
||||
const createDatabaseSQL = `
|
||||
CREATE DATABASE IF NOT EXISTS jiebandata
|
||||
CHARACTER SET utf8mb4
|
||||
COLLATE utf8mb4_unicode_ci;
|
||||
`;
|
||||
|
||||
// 创建用户表的SQL语句
|
||||
const createUsersTableSQL = `
|
||||
CREATE TABLE IF NOT EXISTS jiebandata.users (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
openid VARCHAR(64) UNIQUE NOT NULL,
|
||||
nickname VARCHAR(50) NOT NULL,
|
||||
avatar VARCHAR(255),
|
||||
gender ENUM('male', 'female', 'other'),
|
||||
birthday DATE,
|
||||
phone VARCHAR(20) UNIQUE,
|
||||
email VARCHAR(100) UNIQUE,
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
INDEX idx_openid (openid),
|
||||
INDEX idx_phone (phone),
|
||||
INDEX idx_email (email)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
`;
|
||||
|
||||
// 创建商家表的SQL语句
|
||||
const createMerchantsTableSQL = `
|
||||
CREATE TABLE IF NOT EXISTS jiebandata.merchants (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
user_id INT NOT NULL,
|
||||
merchant_type ENUM('flower_shop', 'activity_organizer', 'farm_owner') NOT NULL,
|
||||
business_name VARCHAR(100) NOT NULL,
|
||||
business_license VARCHAR(255),
|
||||
contact_person VARCHAR(50) NOT NULL,
|
||||
contact_phone VARCHAR(20) NOT NULL,
|
||||
address VARCHAR(255),
|
||||
description TEXT,
|
||||
status ENUM('pending', 'approved', 'rejected', 'suspended') NOT NULL DEFAULT 'pending',
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (user_id) REFERENCES users(id),
|
||||
INDEX idx_user_id (user_id),
|
||||
INDEX idx_status (status)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
`;
|
||||
|
||||
// 创建旅行计划表的SQL语句
|
||||
const createTravelPlansTableSQL = `
|
||||
CREATE TABLE IF NOT EXISTS jiebandata.travel_plans (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
user_id INT NOT NULL,
|
||||
destination VARCHAR(100) NOT NULL,
|
||||
start_date DATE NOT NULL,
|
||||
end_date DATE NOT NULL,
|
||||
budget DECIMAL(10,2) NOT NULL,
|
||||
interests TEXT,
|
||||
visibility ENUM('public', 'friends', 'private') NOT NULL DEFAULT 'public',
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (user_id) REFERENCES users(id),
|
||||
INDEX idx_user_id (user_id),
|
||||
INDEX idx_destination (destination),
|
||||
INDEX idx_dates (start_date, end_date)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
`;
|
||||
|
||||
// 创建管理员表的SQL语句
|
||||
const createAdminsTableSQL = `
|
||||
CREATE TABLE IF NOT EXISTS jiebandata.admins (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
username VARCHAR(50) NOT NULL UNIQUE,
|
||||
password VARCHAR(255) NOT NULL,
|
||||
email VARCHAR(100),
|
||||
nickname VARCHAR(50),
|
||||
avatar VARCHAR(255),
|
||||
role VARCHAR(20) NOT NULL DEFAULT 'admin',
|
||||
status TINYINT(1) NOT NULL DEFAULT 1,
|
||||
last_login DATETIME,
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
INDEX idx_username (username),
|
||||
INDEX idx_role (role),
|
||||
INDEX idx_status (status)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
`;
|
||||
|
||||
// 所有表创建语句
|
||||
const tableCreationSQLs = [
|
||||
createUsersTableSQL,
|
||||
createMerchantsTableSQL,
|
||||
createTravelPlansTableSQL,
|
||||
createAdminsTableSQL
|
||||
];
|
||||
|
||||
function executeSQL(connection, sql, description) {
|
||||
return new Promise((resolve, reject) => {
|
||||
console.log(`🛠️ ${description}...`);
|
||||
connection.query(sql, (err, results) => {
|
||||
if (err) {
|
||||
console.error(`❌ ${description}失败:`, err.message);
|
||||
reject(err);
|
||||
} else {
|
||||
console.log(`✅ ${description}成功`);
|
||||
resolve(results);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
async function initializeDatabase(config) {
|
||||
console.log(`\n🚀 开始初始化 ${config.name} 数据库...`);
|
||||
console.log('='.repeat(60));
|
||||
|
||||
const connection = mysql.createConnection({
|
||||
host: config.host,
|
||||
port: config.port,
|
||||
user: config.user,
|
||||
password: config.password,
|
||||
multipleStatements: true // 允许执行多条SQL语句
|
||||
});
|
||||
|
||||
try {
|
||||
// 连接数据库
|
||||
await new Promise((resolve, reject) => {
|
||||
connection.connect((err) => {
|
||||
if (err) reject(err);
|
||||
else resolve();
|
||||
});
|
||||
});
|
||||
|
||||
// 创建数据库
|
||||
await executeSQL(connection, createDatabaseSQL, '创建数据库 jiebandata');
|
||||
|
||||
// 使用新创建的数据库
|
||||
await executeSQL(connection, 'USE jiebandata', '切换到 jiebandata 数据库');
|
||||
|
||||
// 创建所有表
|
||||
for (let i = 0; i < tableCreationSQLs.length; i++) {
|
||||
await executeSQL(connection, tableCreationSQLs[i], `创建表 ${i + 1}/${tableCreationSQLs.length}`);
|
||||
}
|
||||
|
||||
// 插入示例数据
|
||||
console.log('📝 插入示例数据...');
|
||||
|
||||
// 插入示例用户
|
||||
await executeSQL(connection, `
|
||||
INSERT IGNORE INTO users (openid, nickname, avatar, gender, phone, email) VALUES
|
||||
('test_openid_1', '测试用户1', 'https://example.com/avatar1.jpg', 'male', '13800138001', 'user1@example.com'),
|
||||
('test_openid_2', '测试用户2', 'https://example.com/avatar2.jpg', 'female', '13800138002', 'user2@example.com')
|
||||
`, '插入示例用户数据');
|
||||
|
||||
// 插入示例管理员
|
||||
await executeSQL(connection, `
|
||||
INSERT IGNORE INTO admins (username, password, email, nickname, role) VALUES
|
||||
('admin', '$2a$10$rZ.r/.H0he7d.9T3.1E3qOeP.UZvF0.U6BQ35ENcQbLQzvEuh3dOq', 'admin@example.com', '超级管理员', 'admin')
|
||||
`, '插入示例管理员数据');
|
||||
|
||||
// 验证数据插入
|
||||
const usersResult = await new Promise((resolve, reject) => {
|
||||
connection.query('SELECT COUNT(*) as count FROM users', (err, results) => {
|
||||
if (err) reject(err);
|
||||
else resolve(results);
|
||||
});
|
||||
});
|
||||
|
||||
console.log(`✅ 数据库初始化完成!用户表中有 ${usersResult[0].count} 条记录`);
|
||||
|
||||
return { success: true, message: '数据库初始化成功' };
|
||||
|
||||
} catch (error) {
|
||||
console.error('❌ 数据库初始化失败:', error.message);
|
||||
return { success: false, error: error.message };
|
||||
} finally {
|
||||
// 关闭连接
|
||||
connection.end();
|
||||
console.log('✅ 数据库连接已关闭');
|
||||
}
|
||||
}
|
||||
|
||||
async function main() {
|
||||
console.log('🎯 结伴客系统数据库初始化工具');
|
||||
console.log('='.repeat(60));
|
||||
|
||||
// 直接使用生产环境配置
|
||||
const config = configs[1]; // 生产环境配置
|
||||
const result = await initializeDatabase(config);
|
||||
if (result.success) {
|
||||
console.log('\n🎉 数据库初始化成功!');
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
console.log('\n' + '='.repeat(60));
|
||||
console.log('❌ 数据库初始化失败,请检查网络连接和数据库配置');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
// 运行初始化
|
||||
main().catch(console.error);
|
||||
|
||||
module.exports = { initializeDatabase };
|
||||
19712
package-lock.json
generated
19712
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
37
package.json
37
package.json
@@ -1,10 +1,43 @@
|
||||
{
|
||||
"name": "jiebanke",
|
||||
"version": "1.0.0",
|
||||
"description": "杰邦科项目 - 综合性管理系统",
|
||||
"private": true,
|
||||
"workspaces": [
|
||||
"backend",
|
||||
"admin-system",
|
||||
"website",
|
||||
"mini-program",
|
||||
"scripts"
|
||||
],
|
||||
"scripts": {
|
||||
"dev": "concurrently \"npm run dev:backend\" \"npm run dev:admin\" \"npm run dev:website\"",
|
||||
"dev:backend": "cd backend && npm run dev",
|
||||
"dev:admin": "cd admin-system && npm run dev",
|
||||
"dev:website": "cd website && npm run dev",
|
||||
"build": "concurrently \"npm run build:backend\" \"npm run build:admin\" \"npm run build:website\"",
|
||||
"build:backend": "cd backend && npm run build",
|
||||
"build:admin": "cd admin-system && npm run build",
|
||||
"build:website": "cd website && npm run build",
|
||||
"test": "concurrently \"npm run test:backend\" \"npm run test:admin\" \"npm run test:website\"",
|
||||
"test:backend": "cd backend && npm run test",
|
||||
"test:admin": "cd admin-system && npm run test",
|
||||
"test:website": "cd website && npm run test",
|
||||
"install:all": "npm install && cd backend && npm install && cd ../admin-system && npm install && cd ../website && npm install && cd ../mini-program && npm install",
|
||||
"clean": "rimraf backend/node_modules admin-system/node_modules website/node_modules mini-program/node_modules"
|
||||
},
|
||||
"devDependencies": {
|
||||
"concurrently": "^8.2.2",
|
||||
"rimraf": "^5.0.5",
|
||||
"less": "^4.4.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"axios": "^1.11.0",
|
||||
"bcryptjs": "^3.0.2",
|
||||
"mysql2": "^3.14.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"less": "^4.4.1"
|
||||
"engines": {
|
||||
"node": ">=16.0.0",
|
||||
"npm": ">=8.0.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
const bcrypt = require('bcryptjs');
|
||||
|
||||
// 重置管理员密码为 'admin123'
|
||||
async function resetAdminPassword() {
|
||||
try {
|
||||
const plainPassword = 'admin123';
|
||||
const hashedPassword = await bcrypt.hash(plainPassword, 10);
|
||||
|
||||
console.log('🔐 重置管理员密码');
|
||||
console.log('='.repeat(50));
|
||||
console.log('原密码:', plainPassword);
|
||||
console.log('加密后:', hashedPassword);
|
||||
console.log('');
|
||||
|
||||
// 生成SQL更新语句
|
||||
const updateSQL = `UPDATE jiebandata.admins SET password = '${hashedPassword}' WHERE username = 'admin';`;
|
||||
|
||||
console.log('📋 SQL更新语句:');
|
||||
console.log(updateSQL);
|
||||
console.log('');
|
||||
|
||||
console.log('💡 使用方法:');
|
||||
console.log('1. 使用MySQL客户端执行以上SQL语句');
|
||||
console.log('2. 或者使用MCP工具执行SQL更新');
|
||||
console.log('3. 然后使用用户名: admin, 密码: admin123 登录');
|
||||
|
||||
} catch (error) {
|
||||
console.error('❌ 生成密码失败:', error.message);
|
||||
}
|
||||
}
|
||||
|
||||
// 运行重置
|
||||
resetAdminPassword();
|
||||
@@ -1,72 +0,0 @@
|
||||
const mysql = require('mysql2');
|
||||
|
||||
// 测试环境配置
|
||||
const testConfig = {
|
||||
host: '192.168.0.240',
|
||||
port: 3306,
|
||||
user: 'root',
|
||||
password: 'aiot$Aiot123'
|
||||
};
|
||||
|
||||
// 生产环境配置
|
||||
const prodConfig = {
|
||||
host: '129.211.213.226',
|
||||
port: 9527,
|
||||
user: 'root',
|
||||
password: 'aiotAiot123!'
|
||||
};
|
||||
|
||||
function testConnection(config, environment) {
|
||||
return new Promise((resolve) => {
|
||||
console.log(`\n🔗 测试 ${environment} 连接...`);
|
||||
|
||||
const connection = mysql.createConnection(config);
|
||||
|
||||
connection.connect((err) => {
|
||||
if (err) {
|
||||
console.error('❌ 连接失败:', err.message);
|
||||
connection.end();
|
||||
resolve({ success: false, error: err.message });
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('✅ 连接成功');
|
||||
|
||||
// 测试简单查询
|
||||
connection.query('SELECT VERSION() as version', (err, results) => {
|
||||
if (err) {
|
||||
console.error('❌ 查询失败:', err.message);
|
||||
} else {
|
||||
console.log('📋 MySQL版本:', results[0].version);
|
||||
}
|
||||
|
||||
connection.end();
|
||||
resolve({ success: true });
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
async function main() {
|
||||
console.log('🚀 MySQL连接测试');
|
||||
console.log('='.repeat(40));
|
||||
|
||||
// 测试测试环境
|
||||
const testResult = await testConnection(testConfig, '测试环境');
|
||||
|
||||
console.log('\n' + '='.repeat(40));
|
||||
|
||||
// 测试生产环境
|
||||
const prodResult = await testConnection(prodConfig, '生产环境');
|
||||
|
||||
console.log('\n' + '='.repeat(40));
|
||||
console.log('📋 测试结果:');
|
||||
console.log('测试环境:', testResult.success ? '✅ 成功' : '❌ 失败');
|
||||
console.log('生产环境:', prodResult.success ? '✅ 成功' : '❌ 失败');
|
||||
|
||||
if (testResult.success && prodResult.success) {
|
||||
console.log('\n🎉 两个环境连接都成功!');
|
||||
}
|
||||
}
|
||||
|
||||
main().catch(console.error);
|
||||
@@ -1,105 +0,0 @@
|
||||
const axios = require('axios');
|
||||
|
||||
// API基础配置
|
||||
const BASE_URL = 'http://localhost:3100';
|
||||
|
||||
// 测试管理员登录
|
||||
async function testAdminLogin() {
|
||||
try {
|
||||
console.log('🔐 测试管理员登录接口...');
|
||||
|
||||
const response = await axios.post(`${BASE_URL}/api/v1/admin/login`, {
|
||||
username: 'admin',
|
||||
password: 'admin123' // 默认密码
|
||||
});
|
||||
|
||||
console.log('✅ 登录成功:', response.data);
|
||||
return response.data.data.token;
|
||||
} catch (error) {
|
||||
console.error('❌ 登录失败:', error.response?.data || error.message);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// 测试获取管理员信息
|
||||
async function testGetAdminProfile(token) {
|
||||
if (!token) return;
|
||||
|
||||
try {
|
||||
console.log('\n👤 测试获取管理员信息接口...');
|
||||
|
||||
const response = await axios.get(`${BASE_URL}/api/v1/admin/profile`, {
|
||||
headers: { Authorization: `Bearer ${token}` }
|
||||
});
|
||||
|
||||
console.log('✅ 获取管理员信息成功:', response.data);
|
||||
} catch (error) {
|
||||
console.error('❌ 获取管理员信息失败:', error.response?.data || error.message);
|
||||
}
|
||||
}
|
||||
|
||||
// 测试获取用户列表
|
||||
async function testGetUsers(token) {
|
||||
if (!token) return;
|
||||
|
||||
try {
|
||||
console.log('\n👥 测试获取用户列表接口...');
|
||||
|
||||
const response = await axios.get(`${BASE_URL}/api/v1/users`, {
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
params: { page: 1, limit: 10 }
|
||||
});
|
||||
|
||||
console.log('✅ 获取用户列表成功:');
|
||||
console.log(' 总用户数:', response.data.data.total);
|
||||
console.log(' 当前页用户数:', response.data.data.items.length);
|
||||
} catch (error) {
|
||||
console.error('❌ 获取用户列表失败:', error.response?.data || error.message);
|
||||
}
|
||||
}
|
||||
|
||||
// 测试获取系统信息
|
||||
async function testGetSystemInfo(token) {
|
||||
if (!token) return;
|
||||
|
||||
try {
|
||||
console.log('\n💻 测试获取系统信息接口...');
|
||||
|
||||
const response = await axios.get(`${BASE_URL}/api/v1/admin/system/info`, {
|
||||
headers: { Authorization: `Bearer ${token}` }
|
||||
});
|
||||
|
||||
console.log('✅ 获取系统信息成功:');
|
||||
console.log(' 系统版本:', response.data.data.version);
|
||||
console.log(' 运行环境:', response.data.data.environment);
|
||||
} catch (error) {
|
||||
console.error('❌ 获取系统信息失败:', error.response?.data || error.message);
|
||||
}
|
||||
}
|
||||
|
||||
// 主测试函数
|
||||
async function main() {
|
||||
console.log('🎯 结伴客系统管理员API测试工具');
|
||||
console.log('='.repeat(60));
|
||||
|
||||
// 检查后端服务是否运行
|
||||
try {
|
||||
await axios.get(`${BASE_URL}/health`);
|
||||
console.log('✅ 后端服务正常运行');
|
||||
} catch (error) {
|
||||
console.log('⚠️ 后端服务未启动,请先启动后端服务');
|
||||
console.log(' 运行命令: cd backend && npm start');
|
||||
return;
|
||||
}
|
||||
|
||||
const token = await testAdminLogin();
|
||||
await testGetAdminProfile(token);
|
||||
await testGetUsers(token);
|
||||
await testGetSystemInfo(token);
|
||||
|
||||
console.log('\n' + '='.repeat(60));
|
||||
console.log('🎉 API测试完成!');
|
||||
}
|
||||
|
||||
// 运行测试
|
||||
main().catch(console.error);
|
||||
@@ -1,86 +0,0 @@
|
||||
const mysql = require('mysql2');
|
||||
|
||||
// 生产环境数据库配置(先不指定数据库)
|
||||
const prodConfig = {
|
||||
host: '129.211.213.226',
|
||||
port: 9527,
|
||||
user: 'root',
|
||||
password: 'aiotAiot123!'
|
||||
};
|
||||
|
||||
function testConnection(config, environment) {
|
||||
return new Promise((resolve) => {
|
||||
console.log(`\n🔗 正在测试 ${environment} 数据库连接...`);
|
||||
console.log(`主机: ${config.host}`);
|
||||
console.log(`端口: ${config.port}`);
|
||||
|
||||
// 创建连接
|
||||
const connection = mysql.createConnection(config);
|
||||
|
||||
connection.connect((err) => {
|
||||
if (err) {
|
||||
console.error('❌ 数据库连接失败:', err.message);
|
||||
connection.end();
|
||||
return resolve({ success: false, error: err.message });
|
||||
}
|
||||
|
||||
console.log('✅ 数据库连接成功!');
|
||||
|
||||
// 测试查询
|
||||
console.log('📊 执行测试查询...');
|
||||
connection.query('SELECT 1 as test_result', (err, rows) => {
|
||||
if (err) {
|
||||
console.error('❌ 测试查询失败:', err.message);
|
||||
connection.end();
|
||||
return resolve({ success: false, error: err.message });
|
||||
}
|
||||
|
||||
console.log('✅ 测试查询成功:', rows[0]);
|
||||
|
||||
// 获取数据库版本
|
||||
connection.query('SELECT VERSION() as version', (err, versionRows) => {
|
||||
if (err) {
|
||||
console.error('❌ 获取版本失败:', err.message);
|
||||
} else {
|
||||
console.log('📋 数据库版本:', versionRows[0].version);
|
||||
}
|
||||
|
||||
// 列出所有数据库
|
||||
connection.query('SHOW DATABASES', (err, dbRows) => {
|
||||
if (err) {
|
||||
console.error('❌ 获取数据库列表失败:', err.message);
|
||||
} else {
|
||||
console.log('📚 可用数据库:');
|
||||
dbRows.forEach(row => {
|
||||
console.log(` • ${row.Database}`);
|
||||
});
|
||||
}
|
||||
|
||||
connection.end();
|
||||
resolve({ success: true });
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
async function main() {
|
||||
console.log('🚀 开始测试结伴客系统数据库连接');
|
||||
console.log('============================================================');
|
||||
|
||||
// 测试生产环境数据库
|
||||
const prodResult = await testConnection(prodConfig, '生产环境');
|
||||
|
||||
console.log('\n============================================================');
|
||||
console.log('🏁 数据库连接测试完成');
|
||||
|
||||
if (prodResult.success) {
|
||||
console.log('🎉 所有测试通过!');
|
||||
} else {
|
||||
console.log('💥 部分测试失败');
|
||||
}
|
||||
}
|
||||
|
||||
// 执行测试
|
||||
main().catch(console.error);
|
||||
@@ -1,77 +0,0 @@
|
||||
const axios = require('axios');
|
||||
|
||||
// 创建axios实例
|
||||
const api = axios.create({
|
||||
baseURL: 'http://localhost:3100/api/v1',
|
||||
timeout: 10000
|
||||
});
|
||||
|
||||
async function testAdminAPI() {
|
||||
console.log('🚀 开始测试管理员API接口...\n');
|
||||
|
||||
let token = null;
|
||||
|
||||
try {
|
||||
// 1. 测试管理员登录(使用新创建的测试账户)
|
||||
console.log('1. 测试管理员登录...');
|
||||
const loginResponse = await api.post('/admin/login', {
|
||||
username: 'testadmin',
|
||||
password: 'admin123'
|
||||
});
|
||||
|
||||
console.log('✅ 登录成功');
|
||||
console.log('登录响应:', loginResponse.data);
|
||||
|
||||
// 保存token用于后续测试
|
||||
token = loginResponse.data.data.token;
|
||||
api.defaults.headers.common['Authorization'] = `Bearer ${token}`;
|
||||
|
||||
} catch (error) {
|
||||
if (error.response) {
|
||||
console.log('❌ 登录失败:', error.response.data);
|
||||
} else {
|
||||
console.error('❌ 请求失败:', error.message);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
// 2. 测试获取当前管理员信息
|
||||
console.log('\n2. 测试获取当前管理员信息...');
|
||||
const profileResponse = await api.get('/admin/profile');
|
||||
|
||||
console.log('✅ 获取管理员信息成功');
|
||||
console.log('管理员信息:', profileResponse.data);
|
||||
|
||||
} catch (error) {
|
||||
if (error.response) {
|
||||
console.log('❌ 获取管理员信息失败:', error.response.data);
|
||||
} else {
|
||||
console.error('❌ 请求失败:', error.message);
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
// 3. 测试获取管理员列表
|
||||
console.log('\n3. 测试获取管理员列表...');
|
||||
const listResponse = await api.get('/admin');
|
||||
|
||||
console.log('✅ 获取管理员列表成功');
|
||||
console.log('管理员列表:');
|
||||
listResponse.data.data.admins.forEach((admin, index) => {
|
||||
console.log(`${index + 1}. ID: ${admin.id}, 用户名: ${admin.username}, 角色: ${admin.role}, 状态: ${admin.status}`);
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
if (error.response) {
|
||||
console.log('❌ 获取管理员列表失败:', error.response.data);
|
||||
} else {
|
||||
console.error('❌ 请求失败:', error.message);
|
||||
}
|
||||
}
|
||||
|
||||
console.log('\n✅ 管理员API测试完成');
|
||||
}
|
||||
|
||||
// 运行测试
|
||||
testAdminAPI().catch(console.error);
|
||||
@@ -1,60 +0,0 @@
|
||||
const mysql = require('mysql2/promise');
|
||||
|
||||
// 数据库配置
|
||||
const dbConfig = {
|
||||
host: '129.211.213.226',
|
||||
port: 9527,
|
||||
user: 'root',
|
||||
password: 'aiotAiot123!',
|
||||
database: 'jiebandata',
|
||||
connectionLimit: 10,
|
||||
charset: 'utf8mb4',
|
||||
timezone: '+08:00',
|
||||
waitForConnections: true,
|
||||
queueLimit: 0,
|
||||
// 添加连接超时配置
|
||||
connectTimeout: 10000, // 10秒连接超时
|
||||
acquireTimeout: 10000, // 10秒获取连接超时
|
||||
timeout: 10000 // 10秒查询超时
|
||||
};
|
||||
|
||||
async function testConnection() {
|
||||
let connection;
|
||||
try {
|
||||
console.log('尝试连接数据库...');
|
||||
connection = await mysql.createConnection(dbConfig);
|
||||
console.log('✅ 数据库连接成功');
|
||||
|
||||
// 测试查询
|
||||
const [rows] = await connection.execute('SELECT 1 as test');
|
||||
console.log('✅ 数据库查询测试成功:', rows);
|
||||
|
||||
// 查询管理员表
|
||||
const [admins] = await connection.execute('SELECT id, username, role FROM admins LIMIT 3');
|
||||
console.log('✅ 管理员表查询成功:');
|
||||
console.table(admins);
|
||||
|
||||
await connection.end();
|
||||
console.log('✅ 数据库连接已关闭');
|
||||
} catch (error) {
|
||||
console.error('❌ 数据库连接失败:', error.message);
|
||||
if (error.code) {
|
||||
console.error('错误代码:', error.code);
|
||||
}
|
||||
if (error.errno) {
|
||||
console.error('错误编号:', error.errno);
|
||||
}
|
||||
if (error.syscall) {
|
||||
console.error('系统调用:', error.syscall);
|
||||
}
|
||||
if (connection) {
|
||||
try {
|
||||
await connection.end();
|
||||
} catch (closeError) {
|
||||
console.error('关闭连接时出错:', closeError.message);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
testConnection();
|
||||
Reference in New Issue
Block a user