| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519 |
- import { FastifyRequest, FastifyReply, FastifyInstance } from 'fastify'
- import { MemberService } from '../services/member.service'
- import {
- CreateMemberBody,
- UpdateMemberBody,
- ListMemberQuery,
- MemberResponse,
- UpdateGuestBody,
- MemberLoginBody,
- ResetPasswordBody,
- RegisterBody,
- UpdateProfileBody
- } 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; ref?: string } }>, reply: FastifyReply) {
- try {
- const { code, ref } = request.query || {}
- const ip =
- request.ip ||
- (request.headers['x-forwarded-for'] as string) ||
- (request.headers['x-real-ip'] as string) ||
- 'unknown'
- let domain = undefined
- if (ref) {
- domain = ref
- } else {
- domain = request.headers.origin
- }
- const user = await this.memberService.createGuest(code, domain, 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: '创建游客失败' })
- }
- }
- 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: '更新游客失败' })
- }
- }
- async register(request: FastifyRequest<{ Body: RegisterBody }>, reply: FastifyReply) {
- try {
- const { name, password, email, phone, code } = 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: '手机号格式不正确' })
- }
- // 获取客户端IP
- const ip =
- request.ip ||
- (request.headers['x-forwarded-for'] as string) ||
- (request.headers['x-real-ip'] as string) ||
- 'unknown'
- // 调用注册服务
- const { user, member } = await this.memberService.register(name, password, email, phone, code, ip)
- // 生成JWT token
- const token = await reply.jwtSign({ id: user.id, name: user.name, role: user.role })
- return reply.code(201).send({
- message: '注册成功',
- user: {
- id: user.id,
- name: user.name,
- role: user.role,
- vipLevel: member.vipLevel
- },
- token
- })
- } catch (error) {
- const errorMessage = error instanceof Error ? error.message : '注册失败'
- if (errorMessage.includes('已被使用')) {
- return reply.code(400).send({ message: errorMessage })
- }
- return reply.code(500).send({ message: '注册失败' })
- }
- }
- 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({ message: '登录失败' })
- }
- }
- 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({ message: '获取会员信息失败' })
- }
- }
- async resetPassword(request: FastifyRequest<{ Body: ResetPasswordBody }>, reply: FastifyReply) {
- try {
- const { password } = request.body
- if (password.length < 6) {
- 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({ message: '重置密码失败' })
- }
- }
- async updateProfile(request: FastifyRequest<{ Body: UpdateProfileBody }>, reply: FastifyReply) {
- try {
- const { name, email } = request.body
- // 验证必填字段
- if (!name) {
- return reply.code(400).send({ message: '用户名为必填字段' })
- }
- // 验证用户名格式
- if (name.length < 3 || name.length > 20) {
- return reply.code(400).send({ message: '用户名长度必须在3-20个字符之间' })
- }
- // 验证邮箱格式
- if (email && !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)) {
- return reply.code(400).send({ message: '邮箱格式不正确' })
- }
- await this.memberService.updateProfile(request.user.id, name, email)
- return reply.send({ message: '个人信息更新成功' })
- } catch (error) {
- const errorMessage = error instanceof Error ? error.message : '更新个人信息失败'
- if (errorMessage.includes('已被使用')) {
- return reply.code(400).send({ message: errorMessage })
- }
- return reply.code(500).send({ message: '更新个人信息失败' })
- }
- }
- 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等级失败' })
- }
- }
- 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: '创建会员失败' })
- }
- }
- 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: '查询会员失败' })
- }
- }
- 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: '查询会员列表失败' })
- }
- }
- 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: '更新会员失败' })
- }
- }
- 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: '删除会员失败' })
- }
- }
- 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: '获取所有会员失败' })
- }
- }
- 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: '更新会员状态失败' })
- }
- }
- 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: '更新最后登录时间失败' })
- }
- }
- 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: '获取统计数据失败' })
- }
- }
- }
|