2230a95b45
- New GravityTransaction schema tracks all gravity changes (registration, interview/optimize/download deduction, purchase, monthly topup, migration) - GravityTopUpService: bulk log for monthly VIP topup - PaymentController.activateMembership: log plan_set transactions - QuotaService: add logTransaction, wire into all gravity-modifying methods - UserService: log registration grants (phone/wx/email/password) - GET /user/gravity-transactions?page=&limit= API - Frontend: user.vue '明细' button + paginated popup - Docs: update PROJECT-STATUS v4.10, FEATURE-LIST, DEPLOYMENT
101 lines
3.1 KiB
TypeScript
101 lines
3.1 KiB
TypeScript
import { Controller, Post, Get, Put, Query, Body, Req, HttpCode, HttpStatus, UseGuards } from '@nestjs/common'
|
|
import { UserService } from './user.service'
|
|
import { Public } from '../../common/decorators/public.decorator'
|
|
import { CurrentUser } from '../../common/decorators/current-user.decorator'
|
|
import { JwtAuthGuard } from '../../common/guards/jwt-auth.guard'
|
|
|
|
@Controller('user')
|
|
export class UserController {
|
|
constructor(private userService: UserService) {}
|
|
|
|
@Public()
|
|
@Post('send-code')
|
|
@HttpCode(HttpStatus.OK)
|
|
async sendCode(@Body('phone') phone: string) {
|
|
return this.userService.sendCode(phone)
|
|
}
|
|
|
|
@Public()
|
|
@Post('login')
|
|
@HttpCode(HttpStatus.OK)
|
|
async login(@Body('phone') phone: string, @Body('code') code: string, @Req() req) {
|
|
return this.userService.loginByPhone(phone, code, req.ip)
|
|
}
|
|
|
|
// 📧 邮箱验证码登录(H5 用)
|
|
@Public()
|
|
@Post('send-email-code')
|
|
@HttpCode(HttpStatus.OK)
|
|
async sendEmailCode(@Body('email') email: string) {
|
|
return this.userService.sendEmailCode(email)
|
|
}
|
|
|
|
/** 绑定微信 openid 到当前登录用户 */
|
|
@UseGuards(JwtAuthGuard)
|
|
@Post('bind-wx')
|
|
@HttpCode(HttpStatus.OK)
|
|
async bindWx(@CurrentUser('userId') userId: string, @Body('code') code: string) {
|
|
return this.userService.bindWxOpenid(userId, code)
|
|
}
|
|
|
|
@Public()
|
|
@Post('email-login')
|
|
@HttpCode(HttpStatus.OK)
|
|
async emailLogin(@Body('email') email: string, @Body('code') code: string, @Req() req) {
|
|
return this.userService.loginByEmail(email, code, req.ip)
|
|
}
|
|
|
|
// 密码登录
|
|
@Public()
|
|
@Post('password-login')
|
|
@HttpCode(HttpStatus.OK)
|
|
async passwordLogin(@Body('email') email: string, @Body('password') password: string, @Req() req) {
|
|
return this.userService.loginByPassword(email, password, req.ip)
|
|
}
|
|
|
|
// 邮箱+密码注册
|
|
@Public()
|
|
@Post('register')
|
|
@HttpCode(HttpStatus.OK)
|
|
async register(@Body('email') email: string, @Body('password') password: string, @Req() req) {
|
|
return this.userService.registerWithPassword(email, password, req.ip)
|
|
}
|
|
|
|
// 微信静默登录
|
|
@Public()
|
|
@Post('wx-login')
|
|
@HttpCode(HttpStatus.OK)
|
|
async wxLogin(@Body('code') code: string, @Req() req) {
|
|
return this.userService.loginByWx(code, undefined, req.ip)
|
|
}
|
|
|
|
@Get('info')
|
|
async getInfo(@CurrentUser('userId') userId: string) {
|
|
return this.userService.getInfo(userId)
|
|
}
|
|
|
|
@Put('update')
|
|
async update(@CurrentUser('userId') userId: string, @Body() data: { nickname?: string; avatar?: string }) {
|
|
return this.userService.update(userId, data)
|
|
}
|
|
|
|
@Get('usage')
|
|
async getUsage(@CurrentUser('userId') userId: string) {
|
|
return this.userService.getUsage(userId)
|
|
}
|
|
|
|
@Post('set-password')
|
|
async setPassword(@CurrentUser('userId') userId: string, @Body('password') password: string) {
|
|
return this.userService.setPassword(userId, password)
|
|
}
|
|
|
|
@Get('gravity-transactions')
|
|
async getGravityTransactions(
|
|
@CurrentUser('userId') userId: string,
|
|
@Query('page') page = '1',
|
|
@Query('limit') limit = '20',
|
|
) {
|
|
return this.userService.getGravityTransactions(userId, parseInt(page), parseInt(limit))
|
|
}
|
|
}
|