ef4d22a633
- admin controller: add updatedAt to interview/resume selects; add orderCount, todayOrders, totalRevenue to overview - admin.vue: enrich all tabs with more fields - overview: order cards (count, revenue) - users: wxOpenid, email, createdAt, interviewCount, vipExpireAt, role badge - interviews: user email, updatedAt, summary preview - orders: title, type, channel, paidAt, wxTransactionId, refund info - resumes: user email, updatedAt - share: sharer phone, shareCode, isActive, visitorId(IP), creditedAt - admins: email, createdAt - user.schema: add unique indexes on phone/wxOpenid/email; pre-save hook requiring at least one contact method - user/about: add WeChat contact button (open-type=contact) for customer service
77 lines
1.8 KiB
TypeScript
77 lines
1.8 KiB
TypeScript
import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose'
|
||
import { Document } from 'mongoose'
|
||
|
||
export type UserDocument = User & Document
|
||
|
||
@Schema({ timestamps: true })
|
||
export class User {
|
||
@Prop({ unique: true, sparse: true })
|
||
phone?: string
|
||
|
||
@Prop({ unique: true, sparse: true })
|
||
wxOpenid?: string
|
||
|
||
@Prop({ default: '' })
|
||
nickname?: string
|
||
|
||
@Prop({ default: '' })
|
||
avatar?: string
|
||
|
||
@Prop({ default: 0 })
|
||
interviewCount: number
|
||
|
||
@Prop({ default: 3 })
|
||
remaining: number
|
||
|
||
@Prop({ default: 'free' })
|
||
plan: string
|
||
|
||
@Prop()
|
||
vipExpireAt?: Date
|
||
|
||
@Prop()
|
||
sprintExpireAt?: Date
|
||
|
||
@Prop({ default: 0 })
|
||
sprintRemaining: number // 冲刺版剩余次数(语音分析等)
|
||
|
||
// --- 新版独立额度(产品改造 v2) ---
|
||
@Prop({ default: 1 })
|
||
interviewCredits: number // AI 面试可用次数(含首次免费)
|
||
|
||
@Prop({ default: 0 })
|
||
resumeOptimizeCredits: number // 简历优化可用次数
|
||
|
||
@Prop({ default: 0 })
|
||
resumeDownloadCredits: number // 简历下载可用次数
|
||
|
||
@Prop({ default: 0 })
|
||
freeOptimizeUsed: number // 已使用免费优化次数(上限 3)
|
||
|
||
@Prop({ default: 0 })
|
||
gravity: number // 引力值(统一额度),面试 5、优化 3、下载 2
|
||
|
||
@Prop({ default: 0 })
|
||
shareCredits: number // 已合并到 gravity,保留字段防报错
|
||
|
||
@Prop({ default: 'user' })
|
||
role: string // 'user' | 'admin'
|
||
|
||
@Prop({ default: false })
|
||
isSystemAdmin: boolean
|
||
|
||
@Prop({ unique: true, sparse: true })
|
||
email?: string
|
||
|
||
@Prop({ default: '', select: false })
|
||
password?: string
|
||
}
|
||
|
||
export const UserSchema = SchemaFactory.createForClass(User)
|
||
|
||
UserSchema.pre('save', function (next) {
|
||
if (!this.phone && !this.wxOpenid && !this.email) {
|
||
return next(new Error('用户必须至少有一个联系方式(手机号/微信/邮箱)'))
|
||
}
|
||
next()
|
||
}) |