feat: 商业版支持邀请返佣功能

This commit is contained in:
xiaojunnuo
2026-05-18 13:25:35 +08:00
parent 1bdcfe646f
commit f9a310b6c3
33 changed files with 1317 additions and 14 deletions
@@ -64,6 +64,7 @@ export class LoginController extends BaseController {
mobile: body.mobile,
smsCode: body.smsCode,
randomStr: body.randomStr,
inviteCode: body.inviteCode,
});
this.writeTokenCookie(token);
@@ -3,6 +3,7 @@ import { BaseController, Constants, SysSettingsService } from '@certd/lib-server
import { RegisterType, UserService } from '../../../modules/sys/authority/service/user-service.js';
import { CodeService } from '../../../modules/basic/service/code-service.js';
import { checkComm, checkPlus } from '@certd/plus-core';
import { InviteService } from '@certd/commercial-core';
export type RegisterReq = {
type: RegisterType;
@@ -14,6 +15,7 @@ export type RegisterReq = {
validateCode: string;
captcha:any;
inviteCode?: string;
};
/**
@@ -29,6 +31,9 @@ export class RegisterController extends BaseController {
@Inject()
sysSettingsService: SysSettingsService;
@Inject()
inviteService: InviteService;
@Post('/register', { description: Constants.per.guest })
public async register(
@Body(ALL)
@@ -53,10 +58,13 @@ export class RegisterController extends BaseController {
}
await this.codeService.checkCaptcha(body.captcha,{remoteIp});
const newUser = await this.userService.register(body.type, {
const registerUser = {
username: body.username,
password: body.password,
} as any);
} as any;
const newUser = await this.userService.register(body.type, registerUser, async txManager => {
await this.inviteService.bindInvitee(registerUser.id, body.inviteCode, txManager);
});
return this.ok(newUser);
} else if (body.type === 'mobile') {
if (sysPublicSettings.mobileRegisterEnabled === false) {
@@ -70,12 +78,15 @@ export class RegisterController extends BaseController {
smsCode: body.validateCode,
throwError: true,
});
const newUser = await this.userService.register(body.type, {
const registerUser = {
username: body.username,
phoneCode: body.phoneCode,
mobile: body.mobile,
password: body.password,
} as any);
} as any;
const newUser = await this.userService.register(body.type, registerUser, async txManager => {
await this.inviteService.bindInvitee(registerUser.id, body.inviteCode, txManager);
});
return this.ok(newUser);
} else if (body.type === 'email') {
if (sysPublicSettings.emailRegisterEnabled === false) {
@@ -87,11 +98,14 @@ export class RegisterController extends BaseController {
validateCode: body.validateCode,
throwError: true,
});
const newUser = await this.userService.register(body.type, {
const registerUser = {
username: body.username,
email: body.email,
password: body.password,
} as any);
} as any;
const newUser = await this.userService.register(body.type, registerUser, async txManager => {
await this.inviteService.bindInvitee(registerUser.id, body.inviteCode, txManager);
});
return this.ok(newUser);
}
}
@@ -11,6 +11,7 @@ import {
SysSuiteSetting
} from "@certd/lib-server";
import { AppKey, getPlusInfo, isComm } from "@certd/plus-core";
import { SysInviteCommissionSetting } from "@certd/commercial-core";
import { cloneDeep } from "lodash-es";
import { getVersion } from "../../utils/version.js";
import { http } from "@certd/basic";
@@ -57,6 +58,16 @@ export class BasicSettingsController extends BaseController {
};
}
public async getInviteSetting() {
if (!isComm()) {
return { enabled: false };
}
const setting = await this.sysSettingsService.getSetting<SysInviteCommissionSetting>(SysInviteCommissionSetting);
return {
enabled: setting.enabled,
};
}
public async getSiteEnv() {
const env: SysSiteEnv = {
agent: this.agentConfig
@@ -92,6 +103,7 @@ export class BasicSettingsController extends BaseController {
const plusInfo = await this.plusInfo();
const headerMenus = await this.getHeaderMenus();
const suiteSetting = await this.getSuiteSetting();
const inviteSetting = await this.getInviteSetting();
const version = await getVersion();
return this.ok({
sysPublic,
@@ -101,6 +113,7 @@ export class BasicSettingsController extends BaseController {
plusInfo,
headerMenus,
suiteSetting,
inviteSetting,
app: {
time: new Date().getTime(),
version
@@ -19,6 +19,7 @@ import { isPlus } from "@certd/plus-core";
import { AddonService } from "@certd/lib-server";
import { OauthBoundService } from "./oauth-bound-service.js";
import { PasskeyService } from "./passkey-service.js";
import { InviteService } from "@certd/commercial-core";
/**
*/
@@ -49,6 +50,9 @@ export class LoginService {
@Inject()
passkeyService: PasskeyService;
@Inject()
inviteService: InviteService;
checkIsBlocked(username: string) {
const blockDurationKey = `login_block_duration:${username}`;
const value = cache.get(blockDurationKey);
@@ -111,7 +115,7 @@ export class LoginService {
}
async loginBySmsCode(req: { mobile: string; phoneCode: string; smsCode: string; randomStr: string }) {
async loginBySmsCode(req: { mobile: string; phoneCode: string; smsCode: string; randomStr: string; inviteCode?: string }) {
this.checkIsBlocked(req.mobile)
@@ -129,11 +133,14 @@ export class LoginService {
let info = await this.userService.findOne({phoneCode, mobile: mobile});
if (info == null) {
//用户不存在,注册
info = await this.userService.register('mobile', {
const registerUser = {
phoneCode,
mobile,
password: '',
} as any);
} as any;
info = await this.userService.register('mobile', registerUser, async txManager => {
await this.inviteService.bindInvitee(registerUser.id, req.inviteCode, txManager);
});
}
this.clearCacheOnSuccess(mobile);
return this.onLoginSuccess(info);
@@ -264,4 +271,3 @@ export class LoginService {
const user = await this.passkeyService.loginByPasskey(credential, challenge, ctx);
return this.generateToken(user);
}}