646 lines
19 KiB
Markdown
646 lines
19 KiB
Markdown
# 后端模块重构实施指南
|
||
|
||
## 概述
|
||
|
||
本指南提供了完整的后端模块重构步骤和代码示例。重构涉及:
|
||
- 创建 50+ 个新文件
|
||
- 修改所有 Controller 的路由前缀
|
||
- 更新前端 API 调用路径
|
||
- 创建新的模块组织结构
|
||
|
||
## 一、快速开始
|
||
|
||
### 方案选择
|
||
|
||
**方案A:手动逐步执行**(推荐,风险低)
|
||
- 按照本文档逐个模块迁移
|
||
- 每完成一个端就测试验证
|
||
- 适合希望完全掌控过程的团队
|
||
|
||
**方案B:使用自动化脚本**(快速,需要验证)
|
||
- 使用提供的 Node.js 脚本批量迁移
|
||
- 完成后统一测试和修复
|
||
- 适合有经验的团队
|
||
|
||
**方案C:AI辅助完成**(平衡)
|
||
- AI 创建关键示例和模板
|
||
- 人工复制粘贴并调整其他模块
|
||
- 本文档提供所有必要的模板
|
||
|
||
## 二、目录结构
|
||
|
||
```
|
||
apps/server/src/modules/
|
||
├── user/ # 用户端(C端)
|
||
│ ├── auth/
|
||
│ │ ├── auth.controller.ts
|
||
│ │ ├── auth.service.ts
|
||
│ │ ├── auth.module.ts
|
||
│ │ └── dto/
|
||
│ ├── profile/
|
||
│ ├── guest/
|
||
│ ├── order/
|
||
│ ├── review/
|
||
│ ├── coupon/
|
||
│ ├── finance/
|
||
│ ├── activity/
|
||
│ └── user.module.ts # 用户端总模块
|
||
│
|
||
├── merchant/ # 商家端(B端)
|
||
│ ├── auth/
|
||
│ ├── profile/
|
||
│ ├── room/
|
||
│ ├── room-calendar/
|
||
│ ├── order/
|
||
│ ├── review/
|
||
│ ├── finance/
|
||
│ ├── statistics/
|
||
│ └── merchant.module.ts # 商家端总模块
|
||
│
|
||
├── admin/ # 平台管理端
|
||
│ ├── auth/
|
||
│ ├── user/
|
||
│ ├── merchant/
|
||
│ ├── room/
|
||
│ ├── order/
|
||
│ ├── review/
|
||
│ ├── coupon/
|
||
│ ├── activity/
|
||
│ ├── config/
|
||
│ ├── finance/
|
||
│ ├── website/
|
||
│ └── admin.module.ts # 管理端总模块
|
||
│
|
||
├── website/ # 官网
|
||
│ ├── info/
|
||
│ └── website.module.ts
|
||
│
|
||
└── shared/ # 公共模块
|
||
├── room/
|
||
├── merchant/
|
||
├── activity/
|
||
├── upload/
|
||
└── shared.module.ts
|
||
```
|
||
|
||
## 三、路由前缀映射表
|
||
|
||
### 用户端
|
||
| 旧路由 | 新路由 | 说明 |
|
||
|--------|--------|------|
|
||
| `/auth/*` | `/api/user/auth/*` | 用户认证 |
|
||
| `/user/*` | `/api/user/profile/*` | 个人信息 |
|
||
| `/user/guests` | `/api/user/guests` | 入住人管理 |
|
||
| `/orders` | `/api/user/orders` | 用户订单 |
|
||
| `/reviews` | `/api/user/reviews` | 用户评价 |
|
||
| `/user/coupons` | `/api/user/coupons` | 用户优惠券 |
|
||
| `/user/finance` | `/api/user/finance` | 用户财务 |
|
||
| `/user/activity/invite` | `/api/user/activity/invite` | 邀请活动 |
|
||
|
||
### 商家端
|
||
| 旧路由 | 新路由 | 说明 |
|
||
|--------|--------|------|
|
||
| `/seller/auth/*` | `/api/merchant/auth/*` | 商家认证 |
|
||
| `/seller/merchant` | `/api/merchant/profile` | 商家信息 |
|
||
| `/seller/statistics` | `/api/merchant/statistics` | 数据统计 |
|
||
| `/seller/rooms` | `/api/merchant/rooms` | 房源管理 |
|
||
| `/seller/room-calendar` | `/api/merchant/room-calendar` | 房量房价 |
|
||
| `/seller/orders` | `/api/merchant/orders` | 商家订单 |
|
||
| `/seller/reviews` | `/api/merchant/reviews` | 商家评价 |
|
||
| `/merchant/finance/*` | `/api/merchant/finance/*` | 商家财务 |
|
||
|
||
### 平台管理端
|
||
| 旧路由 | 新路由 | 说明 |
|
||
|--------|--------|------|
|
||
| `/admin/auth/*` | `/api/admin/auth/*` | 管理员认证 |
|
||
| `/admin/users` | `/api/admin/users` | 用户管理 |
|
||
| `/admin/merchants` | `/api/admin/merchants` | 商家管理 |
|
||
| `/admin/rooms` | `/api/admin/rooms` | 房源审核 |
|
||
| `/admin/orders` | `/api/admin/orders` | 订单管理 |
|
||
| `/admin/reviews` | `/api/admin/reviews` | 评价审核 |
|
||
| `/admin/coupons` | `/api/admin/coupons` | 优惠券管理 |
|
||
| `/admin/activity` | `/api/admin/activity` | 活动管理 |
|
||
| `/admin/config` | `/api/admin/config` | 系统配置 |
|
||
| `/admin/finance/*` | `/api/admin/finance/*` | 财务管理 |
|
||
|
||
### 公共接口
|
||
| 旧路由 | 新路由 | 说明 |
|
||
|--------|--------|------|
|
||
| `/rooms` | `/api/public/rooms` | 房源公开查询 |
|
||
| `/merchants` | `/api/public/merchants` | 商家公开信息 |
|
||
| `/activity` | `/api/public/activity` | 活动公开信息 |
|
||
| `/upload` | `/api/user/upload` | 用户上传 |
|
||
| `/seller/upload` | `/api/merchant/upload` | 商家上传 |
|
||
| `/admin/upload` | `/api/admin/upload` | 管理员上传 |
|
||
|
||
## 四、代码模板
|
||
|
||
### 1. Controller 模板(用户端认证示例)
|
||
|
||
**文件位置**: `apps/server/src/modules/user/auth/auth.controller.ts`
|
||
|
||
```typescript
|
||
import { Controller, Post, Body, UseGuards, Get, Req } from '@nestjs/common';
|
||
import { ApiTags, ApiOperation, ApiBearerAuth } from '@nestjs/swagger';
|
||
import { AuthService } from './auth.service';
|
||
import {
|
||
LoginByPhoneDto,
|
||
LoginByPasswordDto,
|
||
RegisterDto,
|
||
SendCodeDto,
|
||
WechatLoginDto,
|
||
} from './dto/auth.dto';
|
||
import { JwtAuthGuard } from '@/common/guards/jwt-auth.guard';
|
||
|
||
@ApiTags('用户认证')
|
||
@Controller('api/user/auth') // ⚠️ 关键:新的路由前缀
|
||
export class AuthController {
|
||
constructor(private readonly authService: AuthService) {}
|
||
|
||
@Post('send-code')
|
||
@ApiOperation({ summary: '发送验证码' })
|
||
async sendCode(@Body() dto: SendCodeDto) {
|
||
return this.authService.sendCode(dto.phone);
|
||
}
|
||
|
||
@Post('login/phone')
|
||
@ApiOperation({ summary: '手机号验证码登录' })
|
||
async loginByPhone(@Body() dto: LoginByPhoneDto) {
|
||
return this.authService.loginByPhone(dto);
|
||
}
|
||
|
||
@Post('login/password')
|
||
@ApiOperation({ summary: '账号密码登录' })
|
||
async loginByPassword(@Body() dto: LoginByPasswordDto) {
|
||
return this.authService.loginByPassword(dto);
|
||
}
|
||
|
||
@Post('login/wechat')
|
||
@ApiOperation({ summary: '微信授权登录' })
|
||
async loginByWechat(@Body() dto: WechatLoginDto) {
|
||
return this.authService.loginByWechat(dto);
|
||
}
|
||
|
||
@Post('register')
|
||
@ApiOperation({ summary: '用户注册' })
|
||
async register(@Body() dto: RegisterDto) {
|
||
return this.authService.register(dto);
|
||
}
|
||
|
||
@Post('refresh')
|
||
@ApiOperation({ summary: '刷新令牌' })
|
||
async refresh(@Body('refreshToken') refreshToken: string) {
|
||
return this.authService.refresh(refreshToken);
|
||
}
|
||
|
||
@Get('profile')
|
||
@UseGuards(JwtAuthGuard)
|
||
@ApiBearerAuth()
|
||
@ApiOperation({ summary: '获取当前用户信息' })
|
||
async getProfile(@Req() req) {
|
||
return req.user;
|
||
}
|
||
}
|
||
```
|
||
|
||
### 2. Module 模板(子模块)
|
||
|
||
**文件位置**: `apps/server/src/modules/user/auth/auth.module.ts`
|
||
|
||
```typescript
|
||
import { Module, Global } from '@nestjs/common';
|
||
import { JwtModule } from '@nestjs/jwt';
|
||
import { ConfigModule, ConfigService } from '@nestjs/config';
|
||
import { TypeOrmModule } from '@nestjs/typeorm';
|
||
import { AuthController } from './auth.controller';
|
||
import { AuthService } from './auth.service';
|
||
import { User } from '@/entities/user.entity';
|
||
import { UserAccount } from '@/entities/user-account.entity';
|
||
|
||
@Global()
|
||
@Module({
|
||
imports: [
|
||
TypeOrmModule.forFeature([User, UserAccount]),
|
||
JwtModule.registerAsync({
|
||
imports: [ConfigModule],
|
||
useFactory: (configService: ConfigService) => ({
|
||
secret: configService.get<string>('jwt.secret') || 'dev_secret_key',
|
||
signOptions: {
|
||
expiresIn: configService.get<string>('jwt.expiresIn') || '7d',
|
||
},
|
||
}),
|
||
inject: [ConfigService],
|
||
}),
|
||
],
|
||
controllers: [AuthController],
|
||
providers: [AuthService],
|
||
exports: [AuthService, JwtModule],
|
||
})
|
||
export class UserAuthModule {} // ⚠️ 重命名避免冲突
|
||
```
|
||
|
||
### 3. 端总模块模板
|
||
|
||
**文件位置**: `apps/server/src/modules/user/user.module.ts`
|
||
|
||
```typescript
|
||
import { Module } from '@nestjs/common';
|
||
import { UserAuthModule } from './auth/auth.module';
|
||
import { UserProfileModule } from './profile/profile.module';
|
||
import { UserGuestModule } from './guest/guest.module';
|
||
import { UserOrderModule } from './order/order.module';
|
||
import { UserReviewModule } from './review/review.module';
|
||
import { UserCouponModule } from './coupon/coupon.module';
|
||
import { UserFinanceModule } from './finance/finance.module';
|
||
import { UserActivityModule } from './activity/activity.module';
|
||
|
||
@Module({
|
||
imports: [
|
||
UserAuthModule,
|
||
UserProfileModule,
|
||
UserGuestModule,
|
||
UserOrderModule,
|
||
UserReviewModule,
|
||
UserCouponModule,
|
||
UserFinanceModule,
|
||
UserActivityModule,
|
||
],
|
||
})
|
||
export class UserModule {}
|
||
```
|
||
|
||
### 4. 根模块更新
|
||
|
||
**文件位置**: `apps/server/src/app.module.ts`
|
||
|
||
```typescript
|
||
import { Module } from '@nestjs/common';
|
||
import { ConfigModule } from '@nestjs/config';
|
||
import { TypeOrmModule } from '@nestjs/typeorm';
|
||
import { UserModule } from './modules/user/user.module';
|
||
import { MerchantModule } from './modules/merchant/merchant.module';
|
||
import { AdminModule } from './modules/admin/admin.module';
|
||
import { WebsiteModule } from './modules/website/website.module';
|
||
import { SharedModule } from './modules/shared/shared.module';
|
||
// ... 其他导入
|
||
|
||
@Module({
|
||
imports: [
|
||
ConfigModule.forRoot(/* ... */),
|
||
TypeOrmModule.forRoot(/* ... */),
|
||
UserModule, // 用户端
|
||
MerchantModule, // 商家端
|
||
AdminModule, // 管理端
|
||
WebsiteModule, // 官网
|
||
SharedModule, // 公共模块
|
||
// 删除旧的模块导入
|
||
],
|
||
})
|
||
export class AppModule {}
|
||
```
|
||
|
||
## 五、前端 API 路径更新
|
||
|
||
### 小程序 (miniapp)
|
||
|
||
**文件**: `apps/miniapp/src/api/auth.ts`
|
||
|
||
```typescript
|
||
// 旧代码
|
||
export function login(data: any) {
|
||
return request.post('/auth/login/phone', data);
|
||
}
|
||
|
||
// 新代码
|
||
export function login(data: any) {
|
||
return request.post('/api/user/auth/login/phone', data);
|
||
}
|
||
```
|
||
|
||
### 批量替换规则(使用 VS Code 全局搜索替换)
|
||
|
||
**用户端接口**:
|
||
- 搜索: `'/auth/`
|
||
- 替换: `'/api/user/auth/`
|
||
|
||
- 搜索: `'/user/`
|
||
- 替换: `'/api/user/profile/`
|
||
|
||
- 搜索: `'/orders`
|
||
- 替换: `'/api/user/orders`
|
||
|
||
**商家端接口**:
|
||
- 搜索: `'/seller/auth/`
|
||
- 替换: `'/api/merchant/auth/`
|
||
|
||
- 搜索: `'/seller/`
|
||
- 替换: `'/api/merchant/`
|
||
|
||
- 搜索: `'/merchant/finance/`
|
||
- 替换: `'/api/merchant/finance/`
|
||
|
||
**管理端接口**:
|
||
- 搜索: `'/admin/`
|
||
- 替换: `'/api/admin/`
|
||
|
||
**公共接口**:
|
||
- 搜索: `'/rooms`
|
||
- 替换: `'/api/public/rooms`
|
||
|
||
- 搜索: `'/merchants`
|
||
- 替换: `'/api/public/merchants`
|
||
|
||
## 六、官网模块实现
|
||
|
||
### 1. 创建 WebsiteInfo 实体
|
||
|
||
**文件**: `apps/server/src/entities/website-info.entity.ts`
|
||
|
||
```typescript
|
||
import {
|
||
Entity,
|
||
PrimaryGeneratedColumn,
|
||
Column,
|
||
CreateDateColumn,
|
||
UpdateDateColumn,
|
||
} from 'typeorm';
|
||
|
||
@Entity('website_info')
|
||
export class WebsiteInfo {
|
||
@PrimaryGeneratedColumn()
|
||
id: number;
|
||
|
||
@Column({ name: 'site_name', length: 100 })
|
||
siteName: string;
|
||
|
||
@Column({ name: 'site_title', length: 200 })
|
||
siteTitle: string;
|
||
|
||
@Column({ name: 'site_description', type: 'text' })
|
||
siteDescription: string;
|
||
|
||
@Column({ name: 'site_keywords', length: 500 })
|
||
siteKeywords: string;
|
||
|
||
@Column({ length: 500 })
|
||
logo: string;
|
||
|
||
@Column({ length: 500 })
|
||
favicon: string;
|
||
|
||
@Column({ name: 'contact_phone', length: 50 })
|
||
contactPhone: string;
|
||
|
||
@Column({ name: 'contact_email', length: 100 })
|
||
contactEmail: string;
|
||
|
||
@Column({ name: 'contact_address', length: 500 })
|
||
contactAddress: string;
|
||
|
||
@Column({ length: 100 })
|
||
icp: string;
|
||
|
||
@Column({ type: 'text' })
|
||
copyright: string;
|
||
|
||
@Column({ name: 'about_us', type: 'text' })
|
||
aboutUs: string;
|
||
|
||
@Column({ name: 'service_agreement', type: 'text' })
|
||
serviceAgreement: string;
|
||
|
||
@Column({ name: 'privacy_policy', type: 'text' })
|
||
privacyPolicy: string;
|
||
|
||
@Column({ name: 'social_links', type: 'json', nullable: true })
|
||
socialLinks: Record<string, string>;
|
||
|
||
@Column({
|
||
type: 'enum',
|
||
enum: ['active', 'inactive'],
|
||
default: 'active',
|
||
})
|
||
status: 'active' | 'inactive';
|
||
|
||
@CreateDateColumn({ name: 'created_at' })
|
||
createdAt: Date;
|
||
|
||
@UpdateDateColumn({ name: 'updated_at' })
|
||
updatedAt: Date;
|
||
}
|
||
```
|
||
|
||
### 2. 数据库迁移脚本
|
||
|
||
**文件**: `database/migrations/002_create_website_info.sql`
|
||
|
||
```sql
|
||
CREATE TABLE IF NOT EXISTS `website_info` (
|
||
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||
`site_name` VARCHAR(100) NOT NULL COMMENT '网站名称',
|
||
`site_title` VARCHAR(200) NOT NULL COMMENT '网站标题',
|
||
`site_description` TEXT NOT NULL COMMENT '网站描述',
|
||
`site_keywords` VARCHAR(500) NOT NULL COMMENT 'SEO关键词',
|
||
`logo` VARCHAR(500) NOT NULL COMMENT 'Logo URL',
|
||
`favicon` VARCHAR(500) NOT NULL COMMENT '网站图标',
|
||
`contact_phone` VARCHAR(50) NOT NULL COMMENT '联系电话',
|
||
`contact_email` VARCHAR(100) NOT NULL COMMENT '联系邮箱',
|
||
`contact_address` VARCHAR(500) NOT NULL COMMENT '联系地址',
|
||
`icp` VARCHAR(100) NOT NULL COMMENT 'ICP备案号',
|
||
`copyright` TEXT NOT NULL COMMENT '版权信息',
|
||
`about_us` TEXT COMMENT '关于我们',
|
||
`service_agreement` TEXT COMMENT '服务协议',
|
||
`privacy_policy` TEXT COMMENT '隐私政策',
|
||
`social_links` JSON COMMENT '社交媒体链接',
|
||
`status` ENUM('active', 'inactive') DEFAULT 'active' COMMENT '状态',
|
||
`created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||
`updated_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||
INDEX `idx_status` (`status`)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='网站信息表';
|
||
|
||
-- 插入默认数据
|
||
INSERT INTO `website_info` (
|
||
`site_name`, `site_title`, `site_description`, `site_keywords`,
|
||
`logo`, `favicon`, `contact_phone`, `contact_email`, `contact_address`,
|
||
`icp`, `copyright`, `about_us`, `service_agreement`, `privacy_policy`
|
||
) VALUES (
|
||
'租赁平台', '租赁平台 - 您的租赁服务专家', '提供优质的租赁服务', '租赁,房屋租赁,短租',
|
||
'', '', '400-000-0000', 'contact@example.com', '北京市朝阳区',
|
||
'京ICP备00000000号', '© 2024 租赁平台 版权所有', '关于我们的内容...', '服务协议内容...', '隐私政策内容...'
|
||
);
|
||
```
|
||
|
||
### 3. WebsiteInfo Service
|
||
|
||
**文件**: `apps/server/src/modules/website/info/info.service.ts`
|
||
|
||
```typescript
|
||
import { Injectable } from '@nestjs/common';
|
||
import { InjectRepository } from '@nestjs/typeorm';
|
||
import { Repository } from 'typeorm';
|
||
import { WebsiteInfo } from '@/entities/website-info.entity';
|
||
|
||
@Injectable()
|
||
export class WebsiteInfoService {
|
||
constructor(
|
||
@InjectRepository(WebsiteInfo)
|
||
private websiteInfoRepo: Repository<WebsiteInfo>,
|
||
) {}
|
||
|
||
async getInfo(): Promise<WebsiteInfo> {
|
||
// 获取第一条记录(通常只有一条)
|
||
const info = await this.websiteInfoRepo.findOne({
|
||
where: { status: 'active' },
|
||
order: { id: 'ASC' },
|
||
});
|
||
|
||
if (!info) {
|
||
throw new Error('网站信息未配置');
|
||
}
|
||
|
||
return info;
|
||
}
|
||
|
||
async updateInfo(data: Partial<WebsiteInfo>): Promise<WebsiteInfo> {
|
||
const info = await this.getInfo();
|
||
Object.assign(info, data);
|
||
return this.websiteInfoRepo.save(info);
|
||
}
|
||
}
|
||
```
|
||
|
||
### 4. WebsiteInfo Controller(公开接口)
|
||
|
||
**文件**: `apps/server/src/modules/website/info/info.controller.ts`
|
||
|
||
```typescript
|
||
import { Controller, Get } from '@nestjs/common';
|
||
import { ApiTags, ApiOperation } from '@nestjs/swagger';
|
||
import { WebsiteInfoService } from './info.service';
|
||
|
||
@ApiTags('网站信息')
|
||
@Controller('api/website/info')
|
||
export class WebsiteInfoController {
|
||
constructor(private readonly websiteInfoService: WebsiteInfoService) {}
|
||
|
||
@Get()
|
||
@ApiOperation({ summary: '获取网站信息' })
|
||
async getInfo() {
|
||
return this.websiteInfoService.getInfo();
|
||
}
|
||
}
|
||
```
|
||
|
||
### 5. WebsiteInfo 管理接口
|
||
|
||
**文件**: `apps/server/src/modules/admin/website/website.controller.ts`
|
||
|
||
```typescript
|
||
import { Controller, Put, Body, UseGuards } from '@nestjs/common';
|
||
import { ApiTags, ApiOperation, ApiBearerAuth } from '@nestjs/swagger';
|
||
import { JwtAuthGuard } from '@/common/guards/jwt-auth.guard';
|
||
import { RolesGuard } from '@/common/guards/roles.guard';
|
||
import { Roles } from '@/common/decorators/roles.decorator';
|
||
import { WebsiteInfoService } from '@/modules/website/info/info.service';
|
||
|
||
@ApiTags('网站管理')
|
||
@Controller('api/admin/website/info')
|
||
@UseGuards(JwtAuthGuard, RolesGuard)
|
||
@Roles('admin')
|
||
@ApiBearerAuth()
|
||
export class AdminWebsiteController {
|
||
constructor(private readonly websiteInfoService: WebsiteInfoService) {}
|
||
|
||
@Put()
|
||
@ApiOperation({ summary: '更新网站信息' })
|
||
async updateInfo(@Body() data: any) {
|
||
return this.websiteInfoService.updateInfo(data);
|
||
}
|
||
}
|
||
```
|
||
|
||
## 七、执行步骤
|
||
|
||
### 步骤1:创建目录结构
|
||
```bash
|
||
cd d:/project/company/rent/apps/server/src/modules
|
||
mkdir -p user/{auth,profile,guest,order,review,coupon,finance,activity}
|
||
mkdir -p merchant/{auth,profile,room,room-calendar,order,review,finance,statistics}
|
||
mkdir -p admin/{auth,user,merchant,room,order,review,coupon,activity,config,finance,website}
|
||
mkdir -p website/info
|
||
mkdir -p shared/{room,merchant,activity,upload}
|
||
```
|
||
|
||
### 步骤2:复制并修改文件
|
||
对于每个模块:
|
||
1. 复制原文件到新位置
|
||
2. 修改 Controller 的 `@Controller()` 装饰器路由前缀
|
||
3. 如果是 Module 文件,重命名类名避免冲突(如 `AuthModule` → `UserAuthModule`)
|
||
4. 复制 Service 和 DTO 文件(通常不需要修改)
|
||
|
||
### 步骤3:创建端总模块
|
||
为每个端创建总模块文件(user.module.ts, merchant.module.ts, admin.module.ts等)
|
||
|
||
### 步骤4:更新 app.module.ts
|
||
导入新的四个端模块,删除旧模块导入
|
||
|
||
### 步骤5:创建官网模块
|
||
1. 创建 WebsiteInfo 实体
|
||
2. 运行数据库迁移
|
||
3. 创建 Service、Controller
|
||
4. 创建管理接口
|
||
|
||
### 步骤6:更新前端 API 路径
|
||
使用 VS Code 全局搜索替换,按照第五节的规则批量替换
|
||
|
||
### 步骤7:测试验证
|
||
1. 启动后端服务
|
||
2. 检查 Swagger 文档
|
||
3. 测试各端的核心接口
|
||
4. 启动三个前端应用测试
|
||
|
||
### 步骤8:清理旧模块
|
||
确认新模块工作正常后,删除旧的模块文件
|
||
|
||
## 八、常见问题
|
||
|
||
### Q1: 模块导入路径错误
|
||
**问题**: Service 或 Entity 导入路径找不到
|
||
**解决**: 使用绝对路径 `@/entities/...` 或 `@/modules/...`
|
||
|
||
### Q2: 模块名称冲突
|
||
**问题**: 多个模块都叫 `AuthModule`
|
||
**解决**: 重命名为 `UserAuthModule`, `MerchantAuthModule`, `AdminAuthModule`
|
||
|
||
### Q3: 前端接口404
|
||
**问题**: 前端调用新接口返回404
|
||
**解决**: 检查是否遗漏了某些路径的替换,特别注意动态路径
|
||
|
||
### Q4: Guards 不生效
|
||
**问题**: 认证守卫没有正确应用
|
||
**解决**: 确保 JwtModule 在对应的 Auth Module 中正确导出
|
||
|
||
## 九、验证清单
|
||
|
||
- [ ] 后端服务启动无错误
|
||
- [ ] Swagger 文档显示所有新接口
|
||
- [ ] 用户端接口测试通过(登录、下单、支付等)
|
||
- [ ] 商家端接口测试通过(登录、房源管理、订单处理等)
|
||
- [ ] 管理端接口测试通过(登录、审核、财务管理等)
|
||
- [ ] 公共接口测试通过(房源列表、商家列表等)
|
||
- [ ] 官网接口测试通过(获取网站信息)
|
||
- [ ] 小程序正常运行
|
||
- [ ] 商家后台正常运行
|
||
- [ ] 平台后台正常运行
|
||
- [ ] 旧模块已删除
|
||
- [ ] 代码已提交到版本控制
|
||
|
||
## 十、回滚方案
|
||
|
||
如果重构出现问题需要回滚:
|
||
1. 使用 git 恢复到重构前的提交
|
||
2. 或者保留旧模块,在 app.module.ts 中切换回旧模块
|
||
3. 前端恢复旧的 API 路径
|
||
|
||
建议:在开始重构前创建一个 git 分支,确保可以随时回滚。
|