import { FastifyRequest, FastifyReply, FastifyInstance } from 'fastify' import { MemberService } from '../services/member.service' import { CreateMemberBody, UpdateMemberBody, ListMemberQuery, MemberResponse, UpdateGuestBody, MemberLoginBody, ResetPasswordBody } from '../dto/member.dto' import { VipLevel, MemberStatus } from '../entities/member.entity' import { UserService } from '../services/user.service' export class MemberController { private memberService: MemberService private userService: UserService constructor(app: FastifyInstance) { this.memberService = new MemberService(app) this.userService = new UserService(app) } async createGuest(request: FastifyRequest<{ Querystring: { code?: string } }>, reply: FastifyReply) { try { const { code } = request.query || {} const ip = request.ip || (request.headers['x-forwarded-for'] as string) || (request.headers['x-real-ip'] as string) || 'unknown' const user = await this.memberService.createGuest(code, ip) const token = await reply.jwtSign({ id: user.id, name: user.name, role: user.role }) return reply.code(201).send({ user: { id: user.id, name: user.name, vipLevel: VipLevel.GUEST }, token }) } catch (error) { return reply.code(500).send({ message: '创建游客失败', error }) } } async upgradeGuest(request: FastifyRequest<{ Body: UpdateGuestBody }>, reply: FastifyReply) { try { const { userId, name, password, email, phone } = request.body if (!name || !password) { return reply.code(400).send({ message: '用户名和密码为必填字段' }) } if (name.length < 3 || name.length > 20) { return reply.code(400).send({ message: '用户名长度必须在3-20个字符之间' }) } if (password.length < 6) { return reply.code(400).send({ message: '密码长度不能少于6个字符' }) } if (email && !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)) { return reply.code(400).send({ message: '邮箱格式不正确' }) } if (phone && !/^1[3-9]\d{9}$/.test(phone)) { return reply.code(400).send({ message: '手机号格式不正确' }) } await this.memberService.upgradeGuest(userId, name, password, email, phone) return reply.send({ message: '游客账户转换成功' }) } catch (error) { const errorMessage = error instanceof Error ? error.message : '更新游客失败' if (errorMessage.includes('不存在')) { return reply.code(404).send({ message: errorMessage }) } else if (errorMessage.includes('已被使用') || errorMessage.includes('格式')) { return reply.code(400).send({ message: errorMessage }) } return reply.code(500).send({ message: '更新游客失败', error: errorMessage }) } } async memberLogin(request: FastifyRequest<{ Body: MemberLoginBody }>, reply: FastifyReply) { try { const { name, password } = request.body if (!name || !password) { return reply.code(400).send({ message: '请输入用户名和密码' }) } const loginResult = await this.memberService.validateMemberLogin(name, password) if (!loginResult) { return reply.code(401).send({ message: '用户名或密码错误' }) } const { user, member } = loginResult const token = await reply.jwtSign({ id: user.id, name: user.name, role: user.role }) await this.memberService.checkVipExpireTime(member) return reply.send({ user: { id: user.id, name: user.name, role: user.role, vipLevel: member.vipLevel }, token }) } catch (error) { return reply.code(500).send(error) } } async profile(request: FastifyRequest, reply: FastifyReply) { try { const user = await this.userService.findById(request.user.id) if (!user) { return reply.code(404).send({ message: '会员信息不存在' }) } const member = await this.memberService.findByUserId(user.id) if (!member) { return reply.code(404).send({ message: '会员信息不存在' }) } await this.memberService.checkVipExpireTime(member) return reply.send({ id: user.id, name: user.name, role: user.role, vipLevel: member.vipLevel, vipExpireTime: member.vipExpireTime }) } catch (error) { return reply.code(500).send(error) } } async resetPassword(request: FastifyRequest<{ Body: ResetPasswordBody }>, reply: FastifyReply) { try { const { password } = request.body if (password.length < 8 || !/(?=.*[a-z])(?=.*[A-Z])(?=.*\d)/.test(password)) { return reply.code(400).send({ message: '密码长度必须至少8位,包含大小写字母和数字' }) } await this.userService.resetPassword(request.user.id, password) return reply.send({ message: '密码重置成功' }) } catch (error) { return reply.code(500).send(error) } } async updateVipLevel( request: FastifyRequest<{ Params: { id: string } Body: { vipLevel: VipLevel; vipExpireTime?: Date } }>, reply: FastifyReply ) { try { const id = parseInt(request.params.id) const { vipLevel, vipExpireTime } = request.body const updatedMember = await this.memberService.updateVipLevel(id, vipLevel, vipExpireTime) return reply.send({ member: { vipLevel: updatedMember.vipLevel, vipExpireTime: updatedMember.vipExpireTime } }) } catch (error) { return reply.code(500).send({ message: '更新VIP等级失败', error }) } } async create(request: FastifyRequest<{ Body: CreateMemberBody }>, reply: FastifyReply) { try { const { userId, email, phone, vipLevel, status, vipExpireTime } = request.body // 检查用户是否已存在 const existingMember = await this.memberService.findByUserId(userId) if (existingMember) { return reply.code(400).send({ message: '该用户已经是会员' }) } // 检查邮箱是否已存在 if (email) { const existingEmail = await this.memberService.findByEmail(email) if (existingEmail) { return reply.code(400).send({ message: '邮箱已被使用' }) } } // 检查手机号是否已存在 if (phone) { const existingPhone = await this.memberService.findByPhone(phone) if (existingPhone) { return reply.code(400).send({ message: '手机号已被使用' }) } } const member = await this.memberService.create({ userId, email, phone, vipLevel, status, vipExpireTime }) return reply.code(201).send({ message: '创建会员成功' }) } catch (error) { return reply.code(500).send({ message: '创建会员失败', error }) } } async getById(request: FastifyRequest<{ Params: { id: string } }>, reply: FastifyReply) { try { const id = parseInt(request.params.id) const member = await this.memberService.findById(id) return reply.send({ member: { id: member.id, userId: member.userId, email: member.email, phone: member.phone, vipLevel: member.vipLevel, status: member.status, vipExpireTime: member.vipExpireTime, lastLoginAt: member.lastLoginAt, createdAt: member.createdAt, updatedAt: member.updatedAt } }) } catch (error) { return reply.code(404).send({ message: '会员不存在' }) } } async getByUserId(request: FastifyRequest<{ Params: { userId: string } }>, reply: FastifyReply) { try { const userId = parseInt(request.params.userId) const member = await this.memberService.findByUserId(userId) if (!member) { return reply.code(404).send({ message: '会员不存在' }) } return reply.send({ member: { id: member.id, userId: member.userId, email: member.email, phone: member.phone, vipLevel: member.vipLevel, status: member.status, vipExpireTime: member.vipExpireTime, lastLoginAt: member.lastLoginAt, createdAt: member.createdAt, updatedAt: member.updatedAt } }) } catch (error) { return reply.code(500).send({ message: '查询会员失败', error }) } } async list(request: FastifyRequest<{ Querystring: ListMemberQuery }>, reply: FastifyReply) { try { const { page, size, vipLevel, status, userId } = request.query const result = await this.memberService.list(page || 0, size || 20, { vipLevel, status, userId }) return reply.send(result) } catch (error) { return reply.code(500).send({ message: '查询会员列表失败', error }) } } async update(request: FastifyRequest<{ Body: UpdateMemberBody }>, reply: FastifyReply) { try { const { id, userId, email, phone, vipLevel, status, vipExpireTime } = request.body // 检查会员是否存在 try { await this.memberService.findById(id) } catch (error) { return reply.code(404).send({ message: '会员不存在' }) } // 检查邮箱是否已被其他会员使用 if (email) { const existingEmail = await this.memberService.findByEmail(email) if (existingEmail && existingEmail.id !== id) { return reply.code(400).send({ message: '邮箱已被其他会员使用' }) } } // 检查手机号是否已被其他会员使用 if (phone) { const existingPhone = await this.memberService.findByPhone(phone) if (existingPhone && existingPhone.id !== id) { return reply.code(400).send({ message: '手机号已被其他会员使用' }) } } const updatedMember = await this.memberService.update(id, { userId, email, phone, vipLevel, status, vipExpireTime }) return reply.send({ member: { id: updatedMember.id, userId: updatedMember.userId, email: updatedMember.email, phone: updatedMember.phone, vipLevel: updatedMember.vipLevel, status: updatedMember.status, vipExpireTime: updatedMember.vipExpireTime, lastLoginAt: updatedMember.lastLoginAt, createdAt: updatedMember.createdAt, updatedAt: updatedMember.updatedAt } }) } catch (error) { return reply.code(500).send({ message: '更新会员失败', error }) } } async delete(request: FastifyRequest<{ Params: { id: string } }>, reply: FastifyReply) { try { const id = parseInt(request.params.id) // 检查会员是否存在 try { await this.memberService.findById(id) } catch (error) { return reply.code(404).send({ message: '会员不存在' }) } await this.memberService.delete(id) return reply.send({ message: '删除会员成功' }) } catch (error) { return reply.code(500).send({ message: '删除会员失败', error }) } } async getAllMembers(request: FastifyRequest, reply: FastifyReply) { try { const members = await this.memberService.findAllMembers() return reply.send({ members }) } catch (error) { return reply.code(500).send({ message: '获取所有会员失败', error }) } } async updateStatus( request: FastifyRequest<{ Params: { id: string } Body: { status: MemberStatus } }>, reply: FastifyReply ) { try { const id = parseInt(request.params.id) const { status } = request.body const updatedMember = await this.memberService.updateStatus(id, status) return reply.send({ member: { id: updatedMember.id, userId: updatedMember.userId, email: updatedMember.email, phone: updatedMember.phone, vipLevel: updatedMember.vipLevel, status: updatedMember.status, vipExpireTime: updatedMember.vipExpireTime, lastLoginAt: updatedMember.lastLoginAt, createdAt: updatedMember.createdAt, updatedAt: updatedMember.updatedAt } }) } catch (error) { return reply.code(500).send({ message: '更新会员状态失败', error }) } } async updateLastLogin(request: FastifyRequest<{ Params: { id: string } }>, reply: FastifyReply) { try { const id = parseInt(request.params.id) await this.memberService.updateLastLogin(id) return reply.send({ message: '更新最后登录时间成功' }) } catch (error) { return reply.code(500).send({ message: '更新最后登录时间失败', error }) } } async getStatistics(request: FastifyRequest, reply: FastifyReply) { try { const vipLevelStats = await this.memberService.countByVipLevel() const statusStats = await this.memberService.countByStatus() return reply.send({ vipLevelStats, statusStats }) } catch (error) { return reply.code(500).send({ message: '获取统计数据失败', error }) } } }