一、超管端设计优化 - 文档管理SOP体系建立,docs目录重组 - 统一用户管理:跨租户全局视角,合并用户管理+公众用户 - 活动监管全模块重构:全部活动(统计卡片+阶段筛选+SuperDetail详情页)、报名数据/作品数据/评审进度(两层合一扁平列表)、成果发布(去Tab+统计+隐藏写操作) - 菜单精简:移除评委管理/评审规则/通知管理 - Bug修复:租户编辑丢失隐藏菜单、pageSize限制、主色统一 二、UGC绘本创作社区P0 - 数据库:10张新表(user_works/user_work_pages/work_tags等) - 子女账号独立化:Child升级为独立User,家长切换+独立登录 - 用户作品库:CRUD+发布审核,8个API - AI创作流程:提交→生成→保存到作品库,4个API - 作品广场:首页改造为推荐流,标签+搜索+排序 - 内容审核(超管端):作品审核+作品管理+标签管理 - 活动联动:WorkSelector作品选择器 - 布局改造:底部5Tab(发现/创作/活动/作品库/我的) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
5.9 KiB
5.9 KiB
后端接口生成规范
概述
本规范用于快速生成 NestJS 后端接口,包含:
- Controller(路由定义)
- Service(业务逻辑)
- DTO(参数校验)
- 前端 API 调用
快速生成指令格式
请生成后端接口:
模块名称:xxx
接口路径:GET/POST /api/xxx
功能描述:xxx
查询参数:
- 参数1(类型,必填/选填)
- 参数2(类型,必填/选填)
返回字段:
- 字段1(来源表.字段)
- 字段2(关联表.字段)
关联查询:
- 表1 -> 表2(关联字段)
排序:字段名 + 排序方式
分页:是/否
文件结构
backend/src/模块名/
├── 模块名.module.ts # 模块定义
├── 模块名.controller.ts # 路由控制器
├── 模块名.service.ts # 业务逻辑
└── dto/
├── query-xxx.dto.ts # 查询参数 DTO
└── create-xxx.dto.ts # 创建参数 DTO
frontend/src/api/
└── 模块名.ts # 前端 API 调用
Controller 模板
import { Controller, Get, Query, Param, UseGuards } from '@nestjs/common';
import { JwtAuthGuard } from '../auth/jwt-auth.guard';
import { XxxService } from './xxx.service';
import { QueryXxxDto } from './dto/query-xxx.dto';
@Controller('api/xxx')
@UseGuards(JwtAuthGuard)
export class XxxController {
constructor(private readonly xxxService: XxxService) {}
@Get(':id/list')
async getList(
@Param('id') id: string,
@Query() queryDto: QueryXxxDto,
) {
return this.xxxService.findAll(+id, queryDto);
}
}
Service 模板
import { Injectable } from '@nestjs/common';
import { PrismaService } from '../prisma/prisma.service';
import { QueryXxxDto } from './dto/query-xxx.dto';
@Injectable()
export class XxxService {
constructor(private prisma: PrismaService) {}
async findAll(parentId: number, queryDto: QueryXxxDto) {
const { page = 1, pageSize = 10, ...filters } = queryDto;
const skip = (page - 1) * pageSize;
// 构建查询条件
const where: any = { parentId };
if (filters.field1) {
where.field1 = { contains: filters.field1 };
}
const [list, total] = await Promise.all([
this.prisma.table.findMany({
where,
skip,
take: pageSize,
orderBy: { sortField: 'desc' },
include: {
// 关联查询
},
}),
this.prisma.table.count({ where }),
]);
return { list, total, page, pageSize };
}
}
DTO 模板
import { IsOptional, IsString, IsInt, Min } from 'class-validator';
import { Type } from 'class-transformer';
export class QueryXxxDto {
@IsOptional()
@Type(() => Number)
@IsInt()
@Min(1)
page?: number = 1;
@IsOptional()
@Type(() => Number)
@IsInt()
@Min(1)
pageSize?: number = 10;
@IsOptional()
@IsString()
field1?: string;
@IsOptional()
@IsString()
field2?: string;
}
前端 API 模板
import request from '@/utils/request'
export interface QueryXxxParams {
page?: number
pageSize?: number
field1?: string
field2?: string
}
export interface XxxItem {
id: number
// ... 其他字段
}
export interface XxxListResponse {
list: XxxItem[]
total: number
page: number
pageSize: number
}
export const xxxApi = {
getList(parentId: number, params: QueryXxxParams): Promise<XxxListResponse> {
return request.get(`/api/xxx/${parentId}/list`, { params })
},
}
Prisma 关联查询示例
常用关联模式
// 用户信息 + 租户 + 学生班级年级
user: {
include: {
tenant: {
select: { id: true, name: true },
},
student: {
include: {
class: {
include: {
grade: {
select: { id: true, name: true },
},
},
},
},
},
},
}
// 指导老师列表
teachers: {
include: {
user: {
select: { id: true, username: true, nickname: true },
},
},
}
// 报名信息 + 用户 + 团队
registration: {
include: {
user: {
select: { id: true, username: true, nickname: true },
},
team: {
select: { id: true, teamName: true },
},
},
}
示例:赛果发布详情接口
请生成后端接口:
模块名称:results(已存在,需修改)
接口路径:GET /api/contests/:id/results/works
功能描述:获取赛事的作品列表(用于赛果发布)
查询参数:
- page(number,选填,默认1)
- pageSize(number,选填,默认10)
- workNo(string,选填,作品编号模糊搜索)
- accountNo(string,选填,报名账号模糊搜索)
返回字段:
- id, workNo, title, finalScore(作品表)
- registration.user.nickname, username(用户表)
- registration.user.tenant.name(租户表)
- registration.user.student.class.name, grade.name(班级年级)
- registration.teachers[].user.nickname(指导老师)
关联查询:
- ContestWork -> ContestRegistration(registrationId)
- ContestRegistration -> User(userId)
- User -> Tenant(tenantId)
- User -> Student -> Class -> Grade
- ContestRegistration -> ContestRegistrationTeacher -> User
排序:finalScore DESC
分页:是
注意事项
- 权限控制:Controller 需要添加
@UseGuards(JwtAuthGuard)和权限装饰器 - 参数校验:DTO 使用 class-validator 进行校验
- 分页处理:统一使用 page/pageSize 参数
- 空值处理:查询条件为空时不添加到 where 条件
- 关联数据:使用 Prisma 的 include 进行关联查询
- 性能优化:只 select 需要的字段,避免查询过多数据
- 错误处理:Service 层抛出 NestJS 内置异常