# 后端管理开发文档

## 1. 项目概述

### 1.1 项目简介
解班客后端管理系统是一个基于Node.js的企业级后端服务，为管理后台、小程序和官网提供统一的API服务和数据管理功能。

### 1.2 技术栈
- **运行环境**：Node.js 18.x
- **开发框架**：Express.js 4.x
- **开发语言**：TypeScript 5.x
- **数据库**：MySQL 8.0 + Redis 7.x
- **ORM框架**：TypeORM 0.3.x
- **认证授权**：JWT + RBAC
- **文件存储**：阿里云OSS
- **消息队列**：Redis + Bull
- **日志系统**：Winston
- **API文档**：Swagger/OpenAPI
- **测试框架**：Jest + Supertest
- **代码规范**：ESLint + Prettier

### 1.3 项目结构
```
backend/
├── src/
│   ├── controllers/     # 控制器
│   │   ├── admin/       # 管理后台控制器
│   │   ├── app/         # 小程序控制器
│   │   └── common/      # 通用控制器
│   ├── services/        # 业务服务层
│   │   ├── user/        # 用户服务
│   │   ├── travel/      # 旅行服务
│   │   ├── animal/      # 动物服务
│   │   ├── order/       # 订单服务
│   │   └── common/      # 通用服务
│   ├── models/          # 数据模型
│   │   ├── entities/    # 实体定义
│   │   ├── dto/         # 数据传输对象
│   │   └── vo/          # 视图对象
│   ├── middleware/      # 中间件
│   │   ├── auth/        # 认证中间件
│   │   ├── validation/  # 验证中间件
│   │   └── common/      # 通用中间件
│   ├── utils/           # 工具函数
│   │   ├── database/    # 数据库工具
│   │   ├── cache/       # 缓存工具
│   │   ├── file/        # 文件处理
│   │   └── common/      # 通用工具
│   ├── config/          # 配置文件
│   │   ├── database.ts  # 数据库配置
│   │   ├── redis.ts     # Redis配置
│   │   └── app.ts       # 应用配置
│   ├── routes/          # 路由定义
│   │   ├── admin/       # 管理后台路由
│   │   ├── app/         # 小程序路由
│   │   └── common/      # 通用路由
│   ├── jobs/            # 定时任务
│   ├── migrations/      # 数据库迁移
│   ├── seeds/           # 数据种子
│   ├── app.ts           # 应用入口
│   └── server.ts        # 服务器启动
├── tests/               # 测试文件
│   ├── unit/            # 单元测试
│   ├── integration/     # 集成测试
│   └── e2e/             # 端到端测试
├── docs/                # 文档
├── scripts/             # 脚本文件
├── .env.example         # 环境变量示例
├── package.json
├── tsconfig.json
├── jest.config.js
└── README.md
```

## 2. 开发环境搭建

### 2.1 环境要求
- Node.js >= 18.0.0
- npm >= 9.0.0 或 yarn >= 1.22.0
- MySQL >= 8.0.0
- Redis >= 7.0.0
- Git >= 2.0.0

### 2.2 环境搭建步骤

#### 2.2.1 克隆项目
```bash
git clone https://github.com/jiebanke/backend.git
cd backend
```

#### 2.2.2 安装依赖
```bash
npm install
# 或
yarn install
```

#### 2.2.3 配置环境变量
```bash
# 复制环境配置文件
cp .env.example .env.development
cp .env.example .env.production

# 编辑配置文件
vim .env.development
```

#### 2.2.4 数据库初始化
```bash
# 创建数据库
npm run db:create

# 运行迁移
npm run migration:run

# 运行种子数据
npm run seed:run
```

#### 2.2.5 启动开发服务器
```bash
npm run dev
# 或
yarn dev
```

### 2.3 开发工具配置

#### 2.3.1 VSCode配置
推荐安装以下插件：
- TypeScript Importer
- ESLint
- Prettier
- REST Client
- MySQL
- Redis

#### 2.3.2 数据库工具
- MySQL Workbench
- Navicat
- DBeaver
- Redis Desktop Manager

## 3. 开发计划与任务分解

### 3.1 开发阶段划分

#### 阶段一：基础框架搭建（预计8个工作日）
- 项目初始化和环境配置
- 数据库设计和迁移
- 基础中间件开发
- 认证授权系统

#### 阶段二：核心业务开发（预计25个工作日）
- 用户管理系统
- 旅行结伴功能
- 动物认领功能
- 订单支付系统

#### 阶段三：管理功能开发（预计15个工作日）
- 管理后台API
- 数据统计分析
- 系统配置管理
- 日志审计功能

#### 阶段四：优化和部署（预计10个工作日）
- 性能优化
- 安全加固
- 测试和修复
- 部署和监控

### 3.2 详细任务分解

#### 3.2.1 阶段一：基础框架搭建

##### 任务1.1：项目初始化（2个工作日）
**负责人**：后端架构师 + 后端开发工程师  
**工时估算**：16人时  
**任务描述**：
- 创建Express.js项目结构
- 配置TypeScript和构建工具
- 设置代码规范和Git hooks
- 配置开发环境

**具体子任务**：
1. 创建Express + TypeScript项目（4人时）
2. 配置ESLint、Prettier和Git hooks（4人时）
3. 设置环境变量和配置管理（4人时）
4. 配置开发和构建脚本（4人时）

**验收标准**：
- 项目可以正常启动和热重载
- 代码规范检查通过
- TypeScript编译无错误

##### 任务1.2：数据库设计和迁移（3个工作日）
**负责人**：后端开发工程师 + 数据库工程师  
**工时估算**：24人时  
**任务描述**：
- 设计数据库表结构
- 创建TypeORM实体
- 编写数据库迁移
- 创建种子数据

**具体子任务**：
1. 设计核心业务表结构（8人时）
2. 创建TypeORM实体和关系（8人时）
3. 编写数据库迁移脚本（4人时）
4. 创建测试和演示数据（4人时）

**验收标准**：
- 数据库表结构完整
- 实体关系正确
- 迁移脚本可正常执行

##### 任务1.3：基础中间件开发（2个工作日）
**负责人**：后端开发工程师  
**工时估算**：16人时  
**任务描述**：
- 请求日志中间件
- 错误处理中间件
- 参数验证中间件
- 跨域处理中间件

**具体子任务**：
1. 请求日志和响应时间中间件（4人时）
2. 全局错误处理中间件（4人时）
3. 请求参数验证中间件（4人时）
4. CORS和安全头中间件（4人时）

**验收标准**：
- 中间件功能完整
- 错误处理规范
- 日志记录准确

##### 任务1.4：认证授权系统（1个工作日）
**负责人**：后端开发工程师  
**工时估算**：8人时  
**任务描述**：
- JWT认证实现
- RBAC权限控制
- 用户会话管理
- 权限验证中间件

**具体子任务**：
1. JWT生成和验证（3人时）
2. RBAC权限模型实现（3人时）
3. 权限验证中间件（2人时）

**验收标准**：
- JWT认证正常
- 权限控制精确
- 会话管理安全

#### 3.2.2 阶段二：核心业务开发

##### 任务2.1：用户管理系统（6个工作日）
**负责人**：后端开发工程师  
**工时估算**：48人时  
**任务描述**：
- 用户注册登录
- 用户信息管理
- 实名认证功能
- 用户行为记录

**具体子任务**：
1. 微信登录和手机号登录（12人时）
2. 用户信息CRUD操作（10人时）
3. 实名认证流程和验证（12人时）
4. 用户行为日志记录（8人时）
5. 用户状态管理（6人时）

**验收标准**：
- 登录流程完整
- 用户信息管理功能齐全
- 实名认证流程正确

##### 任务2.2：旅行结伴功能（7个工作日）
**负责人**：后端开发工程师  
**工时估算**：56人时  
**任务描述**：
- 旅行活动管理
- 参与申请处理
- 活动状态管理
- 地理位置服务

**具体子任务**：
1. 旅行活动CRUD操作（14人时）
2. 参与申请和审核流程（12人时）
3. 活动状态和生命周期管理（10人时）
4. 地理位置搜索和推荐（10人时）
5. 活动评价和反馈（10人时）

**验收标准**：
- 活动管理功能完整
- 申请流程顺畅
- 地理位置服务准确

##### 任务2.3：动物认领功能（6个工作日）
**负责人**：后端开发工程师  
**工时估算**：48人时  
**任务描述**：
- 动物信息管理
- 认领申请处理
- 认领记录跟踪
- 动物状态更新

**具体子任务**：
1. 动物信息CRUD操作（12人时）
2. 认领申请和审核流程（12人时）
3. 认领记录和历史跟踪（10人时）
4. 动物状态和健康记录（8人时）
5. 认领动态和通知（6人时）

**验收标准**：
- 动物信息管理完整
- 认领流程清晰
- 状态跟踪准确

##### 任务2.4：订单支付系统（6个工作日）
**负责人**：后端开发工程师  
**工时估算**：48人时  
**任务描述**：
- 订单创建和管理
- 支付接口集成
- 订单状态跟踪
- 退款处理功能

**具体子任务**：
1. 订单创建和状态管理（12人时）
2. 微信支付接口集成（15人时）
3. 支付回调和状态同步（10人时）
4. 退款申请和处理（8人时）
5. 订单查询和统计（3人时）

**验收标准**：
- 订单管理功能完整
- 支付流程稳定
- 退款处理正确

#### 3.2.3 阶段三：管理功能开发

##### 任务3.1：管理后台API（5个工作日）
**负责人**：后端开发工程师  
**工时估算**：40人时  
**任务描述**：
- 管理员认证授权
- 用户管理接口
- 内容管理接口
- 系统配置接口

**具体子任务**：
1. 管理员登录和权限管理（10人时）
2. 用户管理相关接口（10人时）
3. 内容审核和管理接口（10人时）
4. 系统配置和参数管理（10人时）

**验收标准**：
- 管理接口功能完整
- 权限控制严格
- 数据操作安全

##### 任务3.2：数据统计分析（4个工作日）
**负责人**：后端开发工程师  
**工时估算**：32人时  
**任务描述**：
- 用户数据统计
- 业务数据分析
- 财务数据报表
- 实时数据监控

**具体子任务**：
1. 用户增长和活跃度统计（10人时）
2. 业务数据分析和报表（10人时）
3. 财务收支统计（8人时）
4. 实时数据监控接口（4人时）

**验收标准**：
- 统计数据准确
- 报表生成正确
- 实时监控有效

##### 任务3.3：系统配置管理（3个工作日）
**负责人**：后端开发工程师  
**工时估算**：24人时  
**任务描述**：
- 系统参数配置
- 字典数据管理
- 配置缓存机制
- 配置变更通知

**具体子任务**：
1. 系统参数CRUD操作（8人时）
2. 字典数据管理接口（6人时）
3. 配置缓存和更新机制（6人时）
4. 配置变更通知和日志（4人时）

**验收标准**：
- 配置管理功能完整
- 缓存机制有效
- 变更通知及时

##### 任务3.4：日志审计功能（3个工作日）
**负责人**：后端开发工程师  
**工时估算**：24人时  
**任务描述**：
- 操作日志记录
- 审计日志查询
- 日志分析统计
- 日志归档清理

**具体子任务**：
1. 操作日志记录和存储（8人时）
2. 审计日志查询接口（8人时）
3. 日志分析和统计（4人时）
4. 日志归档和清理机制（4人时）

**验收标准**：
- 日志记录完整
- 查询功能强大
- 归档机制有效

#### 3.2.4 阶段四：优化和部署

##### 任务4.1：性能优化（3个工作日）
**负责人**：后端开发工程师  
**工时估算**：24人时  
**任务描述**：
- 数据库查询优化
- 缓存策略优化
- 接口性能优化
- 并发处理优化

**具体子任务**：
1. SQL查询优化和索引调整（8人时）
2. Redis缓存策略优化（6人时）
3. 接口响应时间优化（6人时）
4. 并发处理和连接池优化（4人时）

**验收标准**：
- 查询性能提升50%
- 缓存命中率>80%
- 接口响应时间<500ms

##### 任务4.2：安全加固（2个工作日）
**负责人**：后端开发工程师  
**工时估算**：16人时  
**任务描述**：
- 输入验证加强
- SQL注入防护
- XSS攻击防护
- 接口限流保护

**具体子任务**：
1. 输入参数验证和过滤（6人时）
2. SQL注入和XSS防护（4人时）
3. 接口限流和防刷机制（4人时）
4. 敏感数据加密存储（2人时）

**验收标准**：
- 安全漏洞修复
- 防护机制有效
- 敏感数据安全

##### 任务4.3：测试和修复（3个工作日）
**负责人**：后端开发工程师 + 测试工程师  
**工时估算**：24人时  
**任务描述**：
- 单元测试编写
- 集成测试执行
- 性能测试验证
- Bug修复和优化

**具体子任务**：
1. 单元测试编写和执行（10人时）
2. 集成测试和API测试（8人时）
3. 性能测试和压力测试（4人时）
4. Bug修复和代码优化（2人时）

**验收标准**：
- 测试覆盖率>80%
- 集成测试通过
- 性能指标达标

##### 任务4.4：部署和监控（2个工作日）
**负责人**：后端开发工程师 + 运维工程师  
**工时估算**：16人时  
**任务描述**：
- 生产环境部署
- 监控系统配置
- 日志收集配置
- 备份恢复机制

**具体子任务**：
1. Docker容器化和部署（6人时）
2. 监控和告警配置（4人时）
3. 日志收集和分析配置（4人时）
4. 数据备份和恢复测试（2人时）

**验收标准**：
- 部署流程自动化
- 监控系统正常
- 备份机制有效

## 4. 开发规范

### 4.1 代码规范

#### 4.1.1 项目结构规范
```typescript
// src/controllers/admin/user.controller.ts
import { Request, Response } from 'express'
import { UserService } from '@/services/user/user.service'
import { CreateUserDto, UpdateUserDto, UserQueryDto } from '@/models/dto/user.dto'
import { ApiResponse } from '@/utils/response'
import { validateDto } from '@/middleware/validation'

export class AdminUserController {
  private userService: UserService

  constructor() {
    this.userService = new UserService()
  }

  /**
   * 获取用户列表
   */
  async getUsers(req: Request, res: Response) {
    try {
      const query = req.query as UserQueryDto
      const result = await this.userService.getUsers(query)
      
      return ApiResponse.success(res, result, '获取用户列表成功')
    } catch (error) {
      return ApiResponse.error(res, error.message)
    }
  }

  /**
   * 创建用户
   */
  async createUser(req: Request, res: Response) {
    try {
      const createUserDto = await validateDto(CreateUserDto, req.body)
      const user = await this.userService.createUser(createUserDto)
      
      return ApiResponse.success(res, user, '创建用户成功')
    } catch (error) {
      return ApiResponse.error(res, error.message)
    }
  }

  /**
   * 更新用户
   */
  async updateUser(req: Request, res: Response) {
    try {
      const { id } = req.params
      const updateUserDto = await validateDto(UpdateUserDto, req.body)
      const user = await this.userService.updateUser(Number(id), updateUserDto)
      
      return ApiResponse.success(res, user, '更新用户成功')
    } catch (error) {
      return ApiResponse.error(res, error.message)
    }
  }

  /**
   * 删除用户
   */
  async deleteUser(req: Request, res: Response) {
    try {
      const { id } = req.params
      await this.userService.deleteUser(Number(id))
      
      return ApiResponse.success(res, null, '删除用户成功')
    } catch (error) {
      return ApiResponse.error(res, error.message)
    }
  }
}
```

#### 4.1.2 服务层规范
```typescript
// src/services/user/user.service.ts
import { Repository } from 'typeorm'
import { AppDataSource } from '@/config/database'
import { User } from '@/models/entities/user.entity'
import { CreateUserDto, UpdateUserDto, UserQueryDto } from '@/models/dto/user.dto'
import { UserVo } from '@/models/vo/user.vo'
import { PageResult } from '@/types/common'
import { CacheService } from '@/utils/cache'
import { LoggerService } from '@/utils/logger'

export class UserService {
  private userRepository: Repository<User>
  private cacheService: CacheService
  private logger: LoggerService

  constructor() {
    this.userRepository = AppDataSource.getRepository(User)
    this.cacheService = new CacheService()
    this.logger = new LoggerService('UserService')
  }

  /**
   * 获取用户列表
   */
  async getUsers(query: UserQueryDto): Promise<PageResult<UserVo>> {
    try {
      const { page = 1, limit = 10, keyword, status } = query
      const queryBuilder = this.userRepository.createQueryBuilder('user')

      // 关键词搜索
      if (keyword) {
        queryBuilder.andWhere(
          '(user.username LIKE :keyword OR user.email LIKE :keyword OR user.phone LIKE :keyword)',
          { keyword: `%${keyword}%` }
        )
      }

      // 状态筛选
      if (status !== undefined) {
        queryBuilder.andWhere('user.status = :status', { status })
      }

      // 分页
      queryBuilder
        .skip((page - 1) * limit)
        .take(limit)
        .orderBy('user.created_at', 'DESC')

      const [users, total] = await queryBuilder.getManyAndCount()

      // 转换为VO
      const userVos = users.map(user => new UserVo(user))

      return {
        data: userVos,
        total,
        page,
        limit,
        pages: Math.ceil(total / limit)
      }
    } catch (error) {
      this.logger.error('获取用户列表失败', error)
      throw error
    }
  }

  /**
   * 根据ID获取用户
   */
  async getUserById(id: number): Promise<UserVo | null> {
    try {
      // 先从缓存获取
      const cacheKey = `user:${id}`
      let user = await this.cacheService.get<User>(cacheKey)

      if (!user) {
        // 缓存未命中，从数据库获取
        user = await this.userRepository.findOne({
          where: { id },
          relations: ['profile', 'roles']
        })

        if (user) {
          // 存入缓存，过期时间30分钟
          await this.cacheService.set(cacheKey, user, 1800)
        }
      }

      return user ? new UserVo(user) : null
    } catch (error) {
      this.logger.error('获取用户详情失败', error)
      throw error
    }
  }

  /**
   * 创建用户
   */
  async createUser(createUserDto: CreateUserDto): Promise<UserVo> {
    try {
      // 检查用户名是否已存在
      const existingUser = await this.userRepository.findOne({
        where: [
          { username: createUserDto.username },
          { email: createUserDto.email }
        ]
      })

      if (existingUser) {
        throw new Error('用户名或邮箱已存在')
      }

      // 创建用户
      const user = this.userRepository.create(createUserDto)
      const savedUser = await this.userRepository.save(user)

      this.logger.info('创建用户成功', { userId: savedUser.id })
      return new UserVo(savedUser)
    } catch (error) {
      this.logger.error('创建用户失败', error)
      throw error
    }
  }

  /**
   * 更新用户
   */
  async updateUser(id: number, updateUserDto: UpdateUserDto): Promise<UserVo> {
    try {
      const user = await this.userRepository.findOne({ where: { id } })
      if (!user) {
        throw new Error('用户不存在')
      }

      // 更新用户信息
      Object.assign(user, updateUserDto)
      const updatedUser = await this.userRepository.save(user)

      // 清除缓存
      await this.cacheService.del(`user:${id}`)

      this.logger.info('更新用户成功', { userId: id })
      return new UserVo(updatedUser)
    } catch (error) {
      this.logger.error('更新用户失败', error)
      throw error
    }
  }

  /**
   * 删除用户
   */
  async deleteUser(id: number): Promise<void> {
    try {
      const user = await this.userRepository.findOne({ where: { id } })
      if (!user) {
        throw new Error('用户不存在')
      }

      // 软删除
      await this.userRepository.softDelete(id)

      // 清除缓存
      await this.cacheService.del(`user:${id}`)

      this.logger.info('删除用户成功', { userId: id })
    } catch (error) {
      this.logger.error('删除用户失败', error)
      throw error
    }
  }
}
```

#### 4.1.3 数据模型规范
```typescript
// src/models/entities/user.entity.ts
import {
  Entity,
  PrimaryGeneratedColumn,
  Column,
  CreateDateColumn,
  UpdateDateColumn,
  DeleteDateColumn,
  OneToOne,
  ManyToMany,
  JoinTable
} from 'typeorm'
import { UserProfile } from './user-profile.entity'
import { Role } from './role.entity'

@Entity('users')
export class User {
  @PrimaryGeneratedColumn()
  id: number

  @Column({ unique: true, length: 50 })
  username: string

  @Column({ unique: true, length: 100 })
  email: string

  @Column({ length: 20, nullable: true })
  phone: string

  @Column({ length: 255 })
  password: string

  @Column({ type: 'tinyint', default: 1, comment: '状态：0-禁用，1-启用' })
  status: number

  @Column({ type: 'datetime', nullable: true, comment: '最后登录时间' })
  last_login_at: Date

  @CreateDateColumn()
  created_at: Date

  @UpdateDateColumn()
  updated_at: Date

  @DeleteDateColumn()
  deleted_at: Date

  // 关联关系
  @OneToOne(() => UserProfile, profile => profile.user)
  profile: UserProfile

  @ManyToMany(() => Role, role => role.users)
  @JoinTable({
    name: 'user_roles',
    joinColumn: { name: 'user_id', referencedColumnName: 'id' },
    inverseJoinColumn: { name: 'role_id', referencedColumnName: 'id' }
  })
  roles: Role[]
}
```

```typescript
// src/models/dto/user.dto.ts
import { IsString, IsEmail, IsOptional, IsNumber, MinLength, MaxLength } from 'class-validator'

export class CreateUserDto {
  @IsString()
  @MinLength(3)
  @MaxLength(50)
  username: string

  @IsEmail()
  email: string

  @IsOptional()
  @IsString()
  @MaxLength(20)
  phone?: string

  @IsString()
  @MinLength(6)
  password: string
}

export class UpdateUserDto {
  @IsOptional()
  @IsString()
  @MinLength(3)
  @MaxLength(50)
  username?: string

  @IsOptional()
  @IsEmail()
  email?: string

  @IsOptional()
  @IsString()
  @MaxLength(20)
  phone?: string

  @IsOptional()
  @IsNumber()
  status?: number
}

export class UserQueryDto {
  @IsOptional()
  @IsNumber()
  page?: number

  @IsOptional()
  @IsNumber()
  limit?: number

  @IsOptional()
  @IsString()
  keyword?: string

  @IsOptional()
  @IsNumber()
  status?: number
}
```

```typescript
// src/models/vo/user.vo.ts
import { User } from '@/models/entities/user.entity'

export class UserVo {
  id: number
  username: string
  email: string
  phone: string
  status: number
  last_login_at: Date
  created_at: Date
  updated_at: Date

  constructor(user: User) {
    this.id = user.id
    this.username = user.username
    this.email = user.email
    this.phone = user.phone
    this.status = user.status
    this.last_login_at = user.last_login_at
    this.created_at = user.created_at
    this.updated_at = user.updated_at
  }
}
```

### 4.2 API设计规范

#### 4.2.1 路由规范
```typescript
// src/routes/admin/user.routes.ts
import { Router } from 'express'
import { AdminUserController } from '@/controllers/admin/user.controller'
import { authMiddleware } from '@/middleware/auth'
import { permissionMiddleware } from '@/middleware/permission'

const router = Router()
const userController = new AdminUserController()

// 用户管理路由
router.get(
  '/users',
  authMiddleware,
  permissionMiddleware('user:view'),
  userController.getUsers.bind(userController)
)

router.get(
  '/users/:id',
  authMiddleware,
  permissionMiddleware('user:view'),
  userController.getUserById.bind(userController)
)

router.post(
  '/users',
  authMiddleware,
  permissionMiddleware('user:create'),
  userController.createUser.bind(userController)
)

router.put(
  '/users/:id',
  authMiddleware,
  permissionMiddleware('user:update'),
  userController.updateUser.bind(userController)
)

router.delete(
  '/users/:id',
  authMiddleware,
  permissionMiddleware('user:delete'),
  userController.deleteUser.bind(userController)
)

export default router
```

#### 4.2.2 响应格式规范
```typescript
// src/utils/response.ts
import { Response } from 'express'

export interface ApiResponseData<T = any> {
  code: number
  message: string
  data: T
  timestamp: number
}

export class ApiResponse {
  /**
   * 成功响应
   */
  static success<T>(res: Response, data: T, message = '操作成功'): Response {
    return res.json({
      code: 200,
      message,
      data,
      timestamp: Date.now()
    })
  }

  /**
   * 错误响应
   */
  static error(res: Response, message = '操作失败', code = 500): Response {
    return res.status(code).json({
      code,
      message,
      data: null,
      timestamp: Date.now()
    })
  }

  /**
   * 参数错误响应
   */
  static badRequest(res: Response, message = '参数错误'): Response {
    return this.error(res, message, 400)
  }

  /**
   * 未授权响应
   */
  static unauthorized(res: Response, message = '未授权访问'): Response {
    return this.error(res, message, 401)
  }

  /**
   * 禁止访问响应
   */
  static forbidden(res: Response, message = '禁止访问'): Response {
    return this.error(res, message, 403)
  }

  /**
   * 资源不存在响应
   */
  static notFound(res: Response, message = '资源不存在'): Response {
    return this.error(res, message, 404)
  }
}
```

### 4.3 数据库操作规范

#### 4.3.1 查询优化规范
```typescript
// src/services/travel/travel.service.ts
export class TravelService {
  /**
   * 获取旅行活动列表（优化版本）
   */
  async getTravelActivities(query: TravelQueryDto): Promise<PageResult<TravelVo>> {
    const { page = 1, limit = 10, city, start_date, end_date, status } = query
    
    // 使用QueryBuilder进行复杂查询
    const queryBuilder = this.travelRepository
      .createQueryBuilder('travel')
      .leftJoinAndSelect('travel.creator', 'creator')
      .leftJoinAndSelect('travel.participants', 'participants')
      .select([
        'travel.id',
        'travel.title',
        'travel.description',
        'travel.city',
        'travel.start_date',
        'travel.end_date',
        'travel.max_participants',
        'travel.status',
        'travel.created_at',
        'creator.id',
        'creator.username',
        'creator.avatar_url',
        'participants.id'
      ])

    // 城市筛选
    if (city) {
      queryBuilder.andWhere('travel.city = :city', { city })
    }

    // 日期范围筛选
    if (start_date) {
      queryBuilder.andWhere('travel.start_date >= :start_date', { start_date })
    }
    if (end_date) {
      queryBuilder.andWhere('travel.end_date <= :end_date', { end_date })
    }

    // 状态筛选
    if (status !== undefined) {
      queryBuilder.andWhere('travel.status = :status', { status })
    }

    // 分页和排序
    queryBuilder
      .skip((page - 1) * limit)
      .take(limit)
      .orderBy('travel.created_at', 'DESC')

    const [travels, total] = await queryBuilder.getManyAndCount()

    return {
      data: travels.map(travel => new TravelVo(travel)),
      total,
      page,
      limit,
      pages: Math.ceil(total / limit)
    }
  }

  /**
   * 批量更新操作
   */
  async batchUpdateTravelStatus(ids: number[], status: number): Promise<void> {
    await this.travelRepository
      .createQueryBuilder()
      .update(Travel)
      .set({ status, updated_at: new Date() })
      .where('id IN (:...ids)', { ids })
      .execute()
  }
}
```

#### 4.3.2 事务处理规范
```typescript
// src/services/order/order.service.ts
import { DataSource } from 'typeorm'

export class OrderService {
  constructor(private dataSource: DataSource) {}

  /**
   * 创建订单（事务处理）
   */
  async createOrder(createOrderDto: CreateOrderDto): Promise<OrderVo> {
    const queryRunner = this.dataSource.createQueryRunner()
    await queryRunner.connect()
    await queryRunner.startTransaction()

    try {
      // 1. 创建订单
      const order = queryRunner.manager.create(Order, {
        ...createOrderDto,
        order_no: this.generateOrderNo(),
        status: OrderStatus.PENDING
      })
      const savedOrder = await queryRunner.manager.save(order)

      // 2. 创建订单项
      const orderItems = createOrderDto.items.map(item => 
        queryRunner.manager.create(OrderItem, {
          ...item,
          order_id: savedOrder.id
        })
      )
      await queryRunner.manager.save(orderItems)

      // 3. 更新库存
      for (const item of createOrderDto.items) {
        await queryRunner.manager.decrement(
          Product,
          { id: item.product_id },
          'stock',
          item.quantity
        )
      }

      // 4. 记录操作日志
      const log = queryRunner.manager.create(OperationLog, {
        user_id: createOrderDto.user_id,
        action: 'CREATE_ORDER',
        target_type: 'ORDER',
        target_id: savedOrder.id,
        details: JSON.stringify(createOrderDto)
      })
      await queryRunner.manager.save(log)

      await queryRunner.commitTransaction()
      
      return new OrderVo(savedOrder)
    } catch (error) {
      await queryRunner.rollbackTransaction()
      throw error
    } finally {
      await queryRunner.release()
    }
  }
}
```

## 5. 质量保证

### 5.1 测试策略

#### 5.1.1 单元测试
```typescript
// tests/unit/services/user.service.spec.ts
import { UserService } from '@/services/user/user.service'
import { User } from '@/models/entities/user.entity'
import { CreateUserDto } from '@/models/dto/user.dto'

describe('UserService', () => {
  let userService: UserService
  let mockUserRepository: any

  beforeEach(() => {
    mockUserRepository = {
      findOne: jest.fn(),
      create: jest.fn(),
      save: jest.fn(),
      softDelete: jest.fn(),
      createQueryBuilder: jest.fn()
    }
    
    userService = new UserService()
    userService['userRepository'] = mockUserRepository
  })

  describe('createUser', () => {
    it('should create user successfully', async () => {
      const createUserDto: CreateUserDto = {
        username: 'testuser',
        email: 'test@example.com',
        password: 'password123'
      }

      const mockUser = { id: 1, ...createUserDto }
      
      mockUserRepository.findOne.mockResolvedValue(null)
      mockUserRepository.create.mockReturnValue(mockUser)
      mockUserRepository.save.mockResolvedValue(mockUser)

      const result = await userService.createUser(createUserDto)

      expect(result.username).toBe(createUserDto.username)
      expect(result.email).toBe(createUserDto.email)
      expect(mockUserRepository.save).toHaveBeenCalledWith(mockUser)
    })

    it('should throw error when user already exists', async () => {
      const createUserDto: CreateUserDto = {
        username: 'testuser',
        email: 'test@example.com',
        password: 'password123'
      }

      mockUserRepository.findOne.mockResolvedValue({ id: 1 })

      await expect(userService.createUser(createUserDto))
        .rejects.toThrow('用户名或邮箱已存在')
    })
  })
})
```

#### 5.1.2 集成测试
```typescript
// tests/integration/controllers/user.controller.spec.ts
import request from 'supertest'
import { app } from '@/app'
import { AppDataSource } from '@/config/database'

describe('User Controller Integration Tests', () => {
  let authToken: string

  beforeAll(async () => {
    await AppDataSource.initialize()
    
    // 获取认证token
    const loginResponse = await request(app)
      .post('/api/auth/login')
      .send({
        username: 'admin',
        password: 'admin123'
      })
    
    authToken = loginResponse.body.data.access_token
  })

  afterAll(async () => {
    await AppDataSource.destroy()
  })

  describe('GET /api/admin/users', () => {
    it('should return user list', async () => {
      const response = await request(app)
        .get('/api/admin/users')
        .set('Authorization', `Bearer ${authToken}`)
        .expect(200)

      expect(response.body.code).toBe(200)
      expect(response.body.data).toHaveProperty('data')
      expect(response.body.data).toHaveProperty('total')
      expect(Array.isArray(response.body.data.data)).toBe(true)
    })

    it('should return 401 without auth token', async () => {
      await request(app)
        .get('/api/admin/users')
        .expect(401)
    })
  })

  describe('POST /api/admin/users', () => {
    it('should create user successfully', async () => {
      const newUser = {
        username: 'newuser',
        email: 'newuser@example.com',
        password: 'password123'
      }

      const response = await request(app)
        .post('/api/admin/users')
        .set('Authorization', `Bearer ${authToken}`)
        .send(newUser)
        .expect(200)

      expect(response.body.code).toBe(200)
      expect(response.body.data.username).toBe(newUser.username)
      expect(response.body.data.email).toBe(newUser.email)
    })
  })
})
```

### 5.2 代码质量检查

#### 5.2.1 ESLint配置
```javascript
// .eslintrc.js
module.exports = {
  parser: '@typescript-eslint/parser',
  extends: [
    '@typescript-eslint/recommended',
    'prettier'
  ],
  plugins: ['@typescript-eslint'],
  rules: {
    '@typescript-eslint/no-unused-vars': 'error',
    '@typescript-eslint/explicit-function-return-type': 'warn',
    '@typescript-eslint/no-explicit-any': 'warn',
    'prefer-const': 'error',
    'no-var': 'error'
  }
}
```

#### 5.2.2 代码审查流程
1. 开发者提交Pull Request
2. 自动化检查（ESLint、TypeScript、测试）
3. 同行代码审查
4. 技术负责人审查
5. 合并到主分支

## 6. 部署和运维

### 6.1 Docker配置

#### 6.1.1 Dockerfile
```dockerfile
# Dockerfile
FROM node:18-alpine

WORKDIR /app

# 复制package文件
COPY package*.json ./

# 安装依赖
RUN npm ci --only=production

# 复制源代码
COPY . .

# 构建应用
RUN npm run build

# 暴露端口
EXPOSE 3000

# 启动应用
CMD ["npm", "start"]
```

#### 6.1.2 Docker Compose
```yaml
# docker-compose.yml
version: '3.8'

services:
  app:
    build: .
    ports:
      - "3000:3000"
    environment:
      - NODE_ENV=production
      - DB_HOST=mysql
      - REDIS_HOST=redis
    depends_on:
      - mysql
      - redis
    volumes:
      - ./logs:/app/logs

  mysql:
    image: mysql:8.0
    environment:
      MYSQL_ROOT_PASSWORD: rootpassword
      MYSQL_DATABASE: jiebanke
      MYSQL_USER: jiebanke
      MYSQL_PASSWORD: password
    ports:
      - "3306:3306"
    volumes:
      - mysql_data:/var/lib/mysql

  redis:
    image: redis:7-alpine
    ports:
      - "6379:6379"
    volumes:
      - redis_data:/data

volumes:
  mysql_data:
  redis_data:
```

### 6.2 CI/CD配置

#### 6.2.1 GitHub Actions
```yaml
# .github/workflows/deploy.yml
name: Deploy to Production

on:
  push:
    branches: [ main ]

jobs:
  test:
    runs-on: ubuntu-latest
    
    services:
      mysql:
        image: mysql:8.0
        env:
          MYSQL_ROOT_PASSWORD: root
          MYSQL_DATABASE: test
        options: >-
          --health-cmd="mysqladmin ping"
          --health-interval=10s
          --health-timeout=5s
          --health-retries=3
      
      redis:
        image: redis:7-alpine
        options: >-
          --health-cmd="redis-cli ping"
          --health-interval=10s
          --health-timeout=5s
          --health-retries=3

    steps:
    - uses: actions/checkout@v3
    
    - name: Setup Node.js
      uses: actions/setup-node@v3
      with:
        node-version: '18'
        cache: 'npm'
    
    - name: Install dependencies
      run: npm ci
    
    - name: Run linting
      run: npm run lint
    
    - name: Run tests
      run: npm run test
      env:
        DB_HOST: localhost
        DB_PORT: 3306
        DB_USERNAME: root
        DB_PASSWORD: root
        DB_DATABASE: test
        REDIS_HOST: localhost
        REDIS_PORT: 6379

  deploy:
    needs: test
    runs-on: ubuntu-latest
    
    steps:
    - uses: actions/checkout@v3
    
    - name: Build Docker image
      run: docker build -t jiebanke/backend:${{ github.sha }} .
    
    - name: Push to registry
      run: |
        echo ${{ secrets.DOCKER_PASSWORD }} | docker login -u ${{ secrets.DOCKER_USERNAME }} --password-stdin
        docker push jiebanke/backend:${{ github.sha }}
    
    - name: Deploy to server
      uses: appleboy/ssh-action@v0.1.5
      with:
        host: ${{ secrets.HOST }}
        username: ${{ secrets.USERNAME }}
        key: ${{ secrets.SSH_KEY }}
        script: |
          docker pull jiebanke/backend:${{ github.sha }}
          docker stop jiebanke-backend || true
          docker rm jiebanke-backend || true
          docker run -d --name jiebanke-backend \
            -p 3000:3000 \
            --env-file /opt/jiebanke/.env \
            jiebanke/backend:${{ github.sha }}
```

### 6.3 监控和日志

#### 6.3.1 日志配置
```typescript
// src/utils/logger.ts
import winston from 'winston'
import DailyRotateFile from 'winston-daily-rotate-file'

export class LoggerService {
  private logger: winston.Logger

  constructor(private context: string) {
    this.logger = winston.createLogger({
      level: process.env.LOG_LEVEL || 'info',
      format: winston.format.combine(
        winston.format.timestamp(),
        winston.format.errors({ stack: true }),
        winston.format.json()
      ),
      defaultMeta: { service: 'jiebanke-backend', context: this.context },
      transports: [
        // 控制台输出
        new winston.transports.Console({
          format: winston.format.combine(
            winston.format.colorize(),
            winston.format.simple()
          )
        }),
        
        // 错误日志文件
        new DailyRotateFile({
          filename: 'logs/error-%DATE%.log',
          datePattern: 'YYYY-MM-DD',
          level: 'error',
          maxSize: '20m',
          maxFiles: '14d'
        }),
        
        // 应用日志文件
        new DailyRotateFile({
          filename: 'logs/app-%DATE%.log',
          datePattern: 'YYYY-MM-DD',
          maxSize: '20m',
          maxFiles: '14d'
        })
      ]
    })
  }

  info(message: string, meta?: any) {
    this.logger.info(message, meta)
  }

  error(message: string, error?: any) {
    this.logger.error(message, { error: error?.stack || error })
  }

  warn(message: string, meta?: any) {
    this.logger.warn(message, meta)
  }

  debug(message: string, meta?: any) {
    this.logger.debug(message, meta)
  }
}
```

#### 6.3.2 性能监控
```typescript
// src/middleware/monitor.ts
import { Request, Response, NextFunction } from 'express'
import { LoggerService } from '@/utils/logger'

const logger = new LoggerService('Monitor')

export const performanceMonitor = (req: Request, res: Response, next: NextFunction) => {
  const startTime = Date.now()
  
  res.on('finish', () => {
    const duration = Date.now() - startTime
    const { method, originalUrl, ip } = req
    const { statusCode } = res
    
    // 记录请求日志
    logger.info('HTTP Request', {
      method,
      url: originalUrl,
      statusCode,
      duration,
      ip,
      userAgent: req.get('User-Agent')
    })
    
    // 慢查询告警
    if (duration > 2000) {
      logger.warn('Slow Request', {
        method,
        url: originalUrl,
        duration
      })
    }
    
    // 错误状态告警
    if (statusCode >= 500) {
      logger.error('Server Error', {
        method,
        url: originalUrl,
        statusCode
      })
    }
  })
  
  next()
}
```

## 7. 总结

本开发文档详细规划了解班客后端管理系统的开发计划，包括：

### 7.1 开发计划
- **总工期**：58个工作日
- **团队规模**：2-3名后端开发工程师
- **关键里程碑**：基础框架、核心业务、管理功能、优化部署

### 7.2 技术架构
- **后端框架**：Express.js + TypeScript
- **数据库**：MySQL + Redis
- **ORM框架**：TypeORM
- **认证授权**：JWT + RBAC

### 7.3 质量保证
- **代码规范**：ESLint + Prettier
- **测试策略**：单元测试 + 集成测试
- **性能优化**：查询优化、缓存策略
- **监控体系**：日志监控 + 性能监控

### 7.4 部署运维
- **容器化**：Docker + Docker Compose
- **CI/CD**：GitHub Actions自动化部署
- **监控日志**：Winston日志系统
- **性能监控**：请求监控和告警

通过严格按照本开发文档执行，可以确保后端管理系统的高质量交付和稳定运行。