Browse Source

新增团队域名功能,包括控制器、服务、路由和DTO的实现,支持团队域名的创建、查询、更新和删除操作,确保用户权限验证和错误处理的完整性。

wuyi 3 months ago
parent
commit
2d04517cf0

+ 126 - 0
src/controllers/team-domain.controller.ts

@@ -0,0 +1,126 @@
+import { FastifyRequest, FastifyReply, FastifyInstance } from 'fastify'
+import { TeamDomainService } from '../services/team-domain.service'
+import {
+  CreateTeamDomainBody,
+  UpdateTeamDomainBody,
+  ListTeamDomainQuery,
+  TeamDomainParams
+} from '../dto/team-domain.dto'
+import { UserRole } from '../entities/user.entity'
+import { TeamMembersService } from '../services/team-members.service'
+import { TeamService } from '../services/team.service'
+
+export class TeamDomainController {
+  private teamDomainService: TeamDomainService
+  private teamMembersService: TeamMembersService
+  private teamService: TeamService
+
+  constructor(app: FastifyInstance) {
+    this.teamDomainService = new TeamDomainService(app)
+    this.teamMembersService = new TeamMembersService(app)
+    this.teamService = new TeamService(app)
+  }
+
+  async create(request: FastifyRequest<{ Body: CreateTeamDomainBody }>, reply: FastifyReply) {
+    try {
+      const teamDomain = await this.teamDomainService.create(request.body)
+      return reply.code(201).send(teamDomain)
+    } catch (error) {
+      return reply.code(500).send({ message: '创建团队域名失败' })
+    }
+  }
+
+  async findById(request: FastifyRequest<{ Params: TeamDomainParams }>, reply: FastifyReply) {
+    try {
+      const { id } = request.params
+      const teamDomain = await this.teamDomainService.findById(id)
+      return reply.send(teamDomain)
+    } catch (error) {
+      return reply.code(404).send({ message: '团队域名不存在' })
+    }
+  }
+
+  async findAll(request: FastifyRequest<{ Querystring: ListTeamDomainQuery }>, reply: FastifyReply) {
+    try {
+      const user = request.user
+      if (!user) {
+        return reply.code(403).send({ message: '用户未登录' })
+      }
+
+      if (user.role === UserRole.PROMOTER) {
+        const teamMembers = await this.teamMembersService.findByUserId(user.id)
+        request.query.teamId = teamMembers.teamId
+      } else if (user.role === UserRole.TEAM) {
+        const team = await this.teamService.findByUserId(user.id)
+        request.query.teamId = team.id
+      }
+
+      const result = await this.teamDomainService.findAll(request.query)
+      return reply.send(result)
+    } catch (error) {
+      console.error(error)
+      return reply.code(500).send({ message: '获取团队域名列表失败' })
+    }
+  }
+
+  async update(request: FastifyRequest<{ Params: TeamDomainParams; Body: UpdateTeamDomainBody }>, reply: FastifyReply) {
+    try {
+      const { id } = request.params
+      const updateData = { ...request.body, id }
+      const user = request.user
+
+      if (!user) {
+        return reply.code(403).send({ message: '用户未登录' })
+      }
+
+      if (user.role !== UserRole.ADMIN) {
+        return reply.code(403).send({ message: '无权限' })
+      }
+
+      const updatedTeamDomain = await this.teamDomainService.update(updateData)
+      return reply.send(updatedTeamDomain)
+    } catch (error) {
+      return reply.code(500).send({ message: '更新团队域名失败' })
+    }
+  }
+
+  async delete(request: FastifyRequest<{ Params: TeamDomainParams }>, reply: FastifyReply) {
+    try {
+      const { id } = request.params
+      const user = request.user
+
+      if (!user) {
+        return reply.code(403).send({ message: '用户未登录' })
+      }
+
+      if (user.role !== UserRole.ADMIN) {
+        return reply.code(403).send({ message: '无权限' })
+      }
+
+      await this.teamDomainService.delete(id)
+      return reply.send({ message: '团队域名已删除' })
+    } catch (error) {
+      return reply.code(500).send({ message: '删除团队域名失败' })
+    }
+  }
+
+  async findByTeamId(request: FastifyRequest<{ Params: { teamId: number } }>, reply: FastifyReply) {
+    try {
+      const { teamId } = request.params
+      const user = request.user
+
+      if (!user) {
+        return reply.code(403).send({ message: '用户未登录' })
+      }
+
+      if (user.role !== UserRole.ADMIN) {
+        return reply.code(403).send({ message: '无权限' })
+      }
+
+      const teamDomains = await this.teamDomainService.findByTeamId(Number(teamId))
+      return reply.send(teamDomains)
+    } catch (error) {
+      return reply.code(500).send({ message: '获取团队域名失败' })
+    }
+  }
+}

+ 25 - 0
src/dto/team-domain.dto.ts

@@ -0,0 +1,25 @@
+import { FastifyRequest } from 'fastify'
+import { Pagination } from './common.dto'
+
+export interface CreateTeamDomainBody {
+  teamId: number
+  domain: string
+  description: string
+}
+
+export interface UpdateTeamDomainBody {
+  id: number
+  teamId?: number
+  domain?: string
+  description?: string
+}
+
+export interface ListTeamDomainQuery extends Pagination {
+  id?: number
+  teamId?: number
+  domain?: string
+}
+
+export interface TeamDomainParams {
+  id: number
+}

+ 22 - 0
src/entities/team-domain.entity.ts

@@ -0,0 +1,22 @@
+import { Column, CreateDateColumn, Entity, PrimaryGeneratedColumn, UpdateDateColumn } from 'typeorm'
+
+@Entity()
+export class TeamDomain {
+  @PrimaryGeneratedColumn()
+  id: number
+
+  @Column()
+  teamId: number
+
+  @Column()
+  domain: string
+
+  @Column({ nullable: true })
+  description: string
+
+  @CreateDateColumn()
+  createdAt: Date
+
+  @UpdateDateColumn()
+  updatedAt: Date
+}

+ 56 - 0
src/routes/team-domain.routes.ts

@@ -0,0 +1,56 @@
+import { FastifyInstance } from 'fastify'
+import { TeamDomainController } from '../controllers/team-domain.controller'
+import { authenticate, hasAnyRole, hasRole } from '../middlewares/auth.middleware'
+import { UserRole } from '../entities/user.entity'
+import {
+  CreateTeamDomainBody,
+  UpdateTeamDomainBody,
+  ListTeamDomainQuery,
+  TeamDomainParams
+} from '../dto/team-domain.dto'
+
+export default async function teamDomainRoutes(fastify: FastifyInstance) {
+  const teamDomainController = new TeamDomainController(fastify)
+
+  // 创建团队域名
+  fastify.post<{ Body: CreateTeamDomainBody }>(
+    '/',
+    { onRequest: [authenticate, hasRole(UserRole.ADMIN)] },
+    teamDomainController.create.bind(teamDomainController)
+  )
+
+  // 获取团队域名列表
+  fastify.get<{ Querystring: ListTeamDomainQuery }>(
+    '/',
+    { onRequest: [authenticate, hasAnyRole(UserRole.ADMIN, UserRole.TEAM, UserRole.PROMOTER)] },
+    teamDomainController.findAll.bind(teamDomainController)
+  )
+
+  // 获取单个团队域名
+  fastify.get<{ Params: TeamDomainParams }>(
+    '/:id',
+    { onRequest: [authenticate, hasAnyRole(UserRole.ADMIN, UserRole.TEAM, UserRole.PROMOTER)] },
+    teamDomainController.findById.bind(teamDomainController)
+  )
+
+  // 更新团队域名
+  fastify.put<{ Params: TeamDomainParams; Body: UpdateTeamDomainBody }>(
+    '/:id',
+    { onRequest: [authenticate, hasAnyRole(UserRole.ADMIN, UserRole.TEAM)] },
+    teamDomainController.update.bind(teamDomainController)
+  )
+
+  // 删除团队域名
+  fastify.delete<{ Params: TeamDomainParams }>(
+    '/:id',
+    { onRequest: [authenticate, hasAnyRole(UserRole.ADMIN, UserRole.TEAM)] },
+    teamDomainController.delete.bind(teamDomainController)
+  )
+
+  // 根据团队ID获取域名列表
+  fastify.get<{ Params: { teamId: number } }>(
+    '/team/:teamId',
+    { onRequest: [authenticate, hasAnyRole(UserRole.ADMIN, UserRole.TEAM, UserRole.PROMOTER)] },
+    teamDomainController.findByTeamId.bind(teamDomainController)
+  )
+}

+ 109 - 0
src/services/team-domain.service.ts

@@ -0,0 +1,109 @@
+import { Repository, Like } from 'typeorm'
+import { FastifyInstance } from 'fastify'
+import { TeamDomain } from '../entities/team-domain.entity'
+import { PaginationResponse } from '../dto/common.dto'
+import { CreateTeamDomainBody, UpdateTeamDomainBody, ListTeamDomainQuery } from '../dto/team-domain.dto'
+import { UserService } from './user.service'
+import { TeamService } from './team.service'
+import { TeamMembersService } from './team-members.service'
+
+export class TeamDomainService {
+  private teamDomainRepository: Repository<TeamDomain>
+  private userService: UserService
+  private teamService: TeamService
+  private teamMembersService: TeamMembersService
+  constructor(app: FastifyInstance) {
+    this.teamDomainRepository = app.dataSource.getRepository(TeamDomain)
+    this.userService = new UserService(app)
+    this.teamService = new TeamService(app)
+    this.teamMembersService = new TeamMembersService(app)
+  }
+
+  async create(data: CreateTeamDomainBody): Promise<TeamDomain> {
+    await this.teamService.findById(data.teamId)
+
+    const existingDomain = await this.teamDomainRepository.findOne({
+      where: { domain: data.domain }
+    })
+    if (existingDomain) {
+      throw new Error('域名已存在')
+    }
+
+    const teamDomain = this.teamDomainRepository.create(data)
+    return this.teamDomainRepository.save(teamDomain)
+  }
+
+  async findById(id: number): Promise<TeamDomain> {
+    return this.teamDomainRepository.findOneOrFail({ where: { id } })
+  }
+
+  async findAll(query: ListTeamDomainQuery): Promise<PaginationResponse<TeamDomain>> {
+    const { page, size, id, teamId, domain } = query
+
+    const where: any = {}
+
+    if (id) {
+      where.id = id
+    }
+
+    if (teamId) {
+      where.teamId = teamId
+    }
+
+    if (domain) {
+      where.domain = Like(`%${domain}%`)
+    }
+
+    const [teamDomains, total] = await this.teamDomainRepository.findAndCount({
+      where,
+      skip: (Number(page) || 0) * (Number(size) || 20),
+      take: Number(size) || 20,
+      order: { createdAt: 'DESC' }
+    })
+
+    return {
+      content: teamDomains,
+      metadata: {
+        total: Number(total),
+        page: Number(page) || 0,
+        size: Number(size) || 20
+      }
+    }
+  }
+
+  async update(data: UpdateTeamDomainBody): Promise<TeamDomain> {
+    const { id, ...updateData } = data
+
+    // 先获取现有记录
+    const existingDomain = await this.findById(id)
+
+    // 如果要更新域名,检查是否重复
+    if (updateData.domain && updateData.domain !== existingDomain.domain) {
+      const duplicateDomain = await this.teamDomainRepository.findOne({
+        where: { domain: updateData.domain }
+      })
+      if (duplicateDomain) {
+        throw new Error('域名已存在')
+      }
+    }
+
+    // 如果要更新团队ID,验证团队是否存在
+    if (updateData.teamId) {
+      await this.teamService.findById(updateData.teamId)
+    }
+
+    await this.teamDomainRepository.update(id, updateData)
+    return this.findById(id)
+  }
+
+  async delete(id: number): Promise<void> {
+    await this.teamDomainRepository.delete(id)
+  }
+
+  async findByTeamId(teamId: number): Promise<TeamDomain[]> {
+    return await this.teamDomainRepository.find({
+      where: { teamId },
+      order: { createdAt: 'DESC' }
+    })
+  }
+}