feat: 登录页密码+验证码双模式 / 首页岗位优化 / 法律页面 / 后端接口完善
- 前端:登录页重构,支持密码登录、验证码登录、注册三种模式 - 前端:首页热门岗位添加「参考示例」标签,去虚构数据 - 前端:面试页顶部优化,岗位名+状态标签展示 - 前端:新增用户协议、隐私政策页面及免责声明 - 后端:新增 POST /api/user/register 注册接口 - 后端:新增 POST /api/user/set-password 设置密码接口 - 后端:修复 user.schema.ts unique 索引导致 null 冲突问题 - 后端:新增 payment-order.schema、positions.schema、site-config.schema - 后端:package.json 新增 postbuild 脚本自动复制证书 - 管理后台:新增订单管理 Tab
This commit is contained in:
@@ -32,6 +32,20 @@ export class UserController {
|
||||
return this.userService.loginByEmail(email, code)
|
||||
}
|
||||
|
||||
// 密码登录
|
||||
@Public()
|
||||
@Post('password-login')
|
||||
async passwordLogin(@Body('email') email: string, @Body('password') password: string) {
|
||||
return this.userService.loginByPassword(email, password)
|
||||
}
|
||||
|
||||
// 邮箱+密码注册
|
||||
@Public()
|
||||
@Post('register')
|
||||
async register(@Body('email') email: string, @Body('password') password: string) {
|
||||
return this.userService.registerWithPassword(email, password)
|
||||
}
|
||||
|
||||
// 微信静默登录
|
||||
@Public()
|
||||
@Post('wx-login')
|
||||
@@ -53,4 +67,9 @@ export class UserController {
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,10 +5,10 @@ export type UserDocument = User & Document
|
||||
|
||||
@Schema({ timestamps: true })
|
||||
export class User {
|
||||
@Prop({ unique: true, sparse: true })
|
||||
@Prop({ sparse: true })
|
||||
phone?: string
|
||||
|
||||
@Prop({ unique: true, sparse: true })
|
||||
@Prop({ sparse: true })
|
||||
wxOpenid?: string
|
||||
|
||||
@Prop({ default: '' })
|
||||
@@ -35,8 +35,11 @@ export class User {
|
||||
@Prop({ default: false })
|
||||
isSystemAdmin: boolean
|
||||
|
||||
@Prop({ unique: true, sparse: true })
|
||||
@Prop({ sparse: true })
|
||||
email?: string
|
||||
|
||||
@Prop({ default: '' })
|
||||
password?: string
|
||||
}
|
||||
|
||||
export const UserSchema = SchemaFactory.createForClass(User)
|
||||
@@ -1,4 +1,5 @@
|
||||
import { Injectable, HttpException, HttpStatus } from '@nestjs/common'
|
||||
import * as bcrypt from 'bcrypt'
|
||||
import { Injectable, HttpException, HttpStatus } from '@nestjs/common'
|
||||
import { InjectModel } from '@nestjs/mongoose'
|
||||
import { Model } from 'mongoose'
|
||||
import { JwtService } from '@nestjs/jwt'
|
||||
@@ -104,13 +105,59 @@ export class UserService {
|
||||
|
||||
// 按邮箱查找或创建用户
|
||||
let user = await this.userModel.findOne({ email }).exec()
|
||||
let isNew = false
|
||||
if (!user) {
|
||||
isNew = true
|
||||
const nick = email.split('@')[0]
|
||||
user = await this.userModel.create({ email, nickname: nick, remaining: 3 })
|
||||
}
|
||||
return { ...this.generateAuthResponse(user), isNew, hasPassword: !!user.password }
|
||||
}
|
||||
|
||||
// 🔐 密码登录
|
||||
async loginByPassword(email: string, password: string) {
|
||||
const user = await this.userModel.findOne({ email }).exec()
|
||||
if (!user) throw new HttpException('账号不存在', HttpStatus.NOT_FOUND)
|
||||
if (!user.password) throw new HttpException('该账号未设置密码,请使用验证码登录', HttpStatus.UNAUTHORIZED)
|
||||
const match = await bcrypt.compare(password, user.password)
|
||||
if (!match) throw new HttpException('密码错误', HttpStatus.UNAUTHORIZED)
|
||||
return this.generateAuthResponse(user)
|
||||
}
|
||||
|
||||
// 📝 邮箱+密码注册
|
||||
async registerWithPassword(email: string, password: string) {
|
||||
if (!email || !email.includes('@')) {
|
||||
throw new HttpException('请输入正确的邮箱地址', HttpStatus.BAD_REQUEST)
|
||||
}
|
||||
if (!password || password.length < 6) {
|
||||
throw new HttpException('密码至少6位', HttpStatus.BAD_REQUEST)
|
||||
}
|
||||
const existing = await this.userModel.findOne({ email }).exec()
|
||||
if (existing) {
|
||||
if (existing.password) {
|
||||
throw new HttpException('该邮箱已注册,请直接登录', HttpStatus.CONFLICT)
|
||||
}
|
||||
// 已有验证码注册的用户,补充设置密码
|
||||
existing.password = await bcrypt.hash(password, 10)
|
||||
await existing.save()
|
||||
return this.generateAuthResponse(existing)
|
||||
}
|
||||
const nick = email.split('@')[0]
|
||||
const hashed = await bcrypt.hash(password, 10)
|
||||
const user = await this.userModel.create({ email, nickname: nick, password: hashed, remaining: 3 })
|
||||
return this.generateAuthResponse(user)
|
||||
}
|
||||
|
||||
// 🔑 已登录用户设置/修改密码
|
||||
async setPassword(userId: string, password: string) {
|
||||
if (!password || password.length < 6) {
|
||||
throw new HttpException('密码至少6位', HttpStatus.BAD_REQUEST)
|
||||
}
|
||||
const hashed = await bcrypt.hash(password, 10)
|
||||
await this.userModel.findByIdAndUpdate(userId, { password: hashed })
|
||||
return { message: '密码设置成功' }
|
||||
}
|
||||
|
||||
async getInfo(userId: string) {
|
||||
const user = await this.userModel.findById(userId).exec()
|
||||
if (!user) throw new HttpException('用户不存在', HttpStatus.NOT_FOUND)
|
||||
|
||||
Reference in New Issue
Block a user