Files
autoAiWorkSys/api/controller_admin/invite_register.js
张成 cfbcbc39fd 11
2025-12-19 15:54:52 +08:00

356 lines
10 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* 邀请注册管理控制器(后台管理)
* 提供邀请注册相关的接口,不需要登录验证
*/
const Framework = require("../../framework/node-core-framework.js");
const dayjs = require('dayjs');
const email_service = require('../services/email_service.js');
module.exports = {
/**
* @swagger
* /admin_api/invite/register:
* post:
* summary: 邀请注册
* description: 通过邀请码注册新用户注册成功后给邀请人增加3天试用期
* tags: [后台-邀请注册]
* requestBody:
* required: true
* content:
* application/json:
* schema:
* type: object
* required:
* - email
* - password
* - email_code
* properties:
* email:
* type: string
* description: 邮箱地址
* example: 'user@example.com'
* password:
* type: string
* description: 密码
* example: 'password123'
* email_code:
* type: string
* description: 验证码
* example: '123456'
* invite_code:
* type: string
* description: 邀请码(选填)
* example: 'INV123_ABC123'
* responses:
* 200:
* description: 注册成功
*/
'POST /invite/register': async (ctx) => {
try {
const body = ctx.getBody();
const { email, password, email_code, invite_code } = body;
// 验证必填参数
if (!email || !password || !email_code) {
return ctx.fail('邮箱、密码和验证码不能为空');
}
// 验证邮箱格式
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
if (!emailRegex.test(email)) {
return ctx.fail('邮箱格式不正确');
}
// 验证密码长度
if (password.length < 6) {
return ctx.fail('密码长度不能少于6位');
}
// 验证验证码
const emailVerifyResult = await verifyEmailCode(email, email_code);
if (!emailVerifyResult.success) {
return ctx.fail(emailVerifyResult.message || '验证码错误或已过期');
}
const { pla_account } = await Framework.getModels();
// 检查邮箱是否已注册
const existingUser = await pla_account.findOne({
where: { login_name: email }
});
if (existingUser) {
return ctx.fail('该邮箱已被注册');
}
// 验证邀请码(如果提供了邀请码)
let inviter = null;
let inviter_id = null;
if (invite_code) {
// 解析邀请码获取邀请人ID
// 邀请码格式INV{user_id}_{timestamp}
const inviteMatch = invite_code.match(/^INV(\d+)_/);
if (!inviteMatch) {
return ctx.fail('邀请码格式不正确');
}
inviter_id = parseInt(inviteMatch[1]);
// 验证邀请人是否存在
inviter = await pla_account.findOne({
where: { id: inviter_id }
});
if (!inviter) {
return ctx.fail('邀请码无效,邀请人不存在');
}
}
// 生成设备SN码基于邮箱和时间戳
const sn_code = `SN${Date.now()}${Math.random().toString(36).substr(2, 6).toUpperCase()}`;
// 创建新用户
const newUser = await pla_account.create({
name: email.split('@')[0], // 默认使用邮箱用户名作为名称
sn_code: sn_code,
device_id: '', // 设备ID由客户端登录时提供
platform_type: 'boss', // 默认平台类型
login_name: email,
pwd: password,
keyword: '',
is_enabled: 1,
is_delete: 0,
authorization_date: null,
authorization_days: 0
});
// 给邀请人增加3天试用期
if (inviter) {
const inviterData = inviter.toJSON();
const currentAuthDate = inviterData.authorization_date;
const currentAuthDays = inviterData.authorization_days || 0;
let newAuthDate = currentAuthDate;
let newAuthDays = currentAuthDays + 3; // 增加3天
// 如果当前没有授权日期,则从今天开始
if (!currentAuthDate) {
newAuthDate = new Date();
} else {
// 如果当前授权已过期,从今天开始计算
const currentEndDate = dayjs(currentAuthDate).add(currentAuthDays, 'day');
const now = dayjs();
if (currentEndDate.isBefore(now)) {
newAuthDate = new Date();
newAuthDays = 3; // 重新设置为3天
}
}
// 更新邀请人的授权信息
await pla_account.update(
{
authorization_date: newAuthDate,
authorization_days: newAuthDays
},
{ where: { id: inviter_id } }
);
// 记录邀请记录
const { invite_record } = await Framework.getModels();
await invite_record.create({
inviter_id: inviter_id,
inviter_sn_code: inviter.sn_code,
invitee_id: newUser.id,
invitee_sn_code: newUser.sn_code,
invitee_phone: email, // 使用邮箱代替手机号
invite_code: invite_code,
register_time: new Date(),
reward_status: 1, // 已发放
reward_type: 'trial_days',
reward_value: 3,
is_delete: 0
});
console.log(`[邀请注册] 用户 ${email} 通过邀请码 ${invite_code} 注册成功,邀请人 ${inviter.sn_code} 获得3天试用期`);
} else {
console.log(`[邀请注册] 用户 ${email} 注册成功(无邀请码)`);
}
return ctx.success({
message: '注册成功',
user: {
id: newUser.id,
sn_code: newUser.sn_code,
login_name: newUser.login_name
}
});
} catch (error) {
console.error('邀请注册失败:', error);
return ctx.fail('注册失败: ' + error.message);
}
},
/**
* @swagger
* /admin_api/invite/send-email-code:
* post:
* summary: 发送验证码
* description: 发送验证码到指定邮箱地址
* tags: [后台-邀请注册]
* requestBody:
* required: true
* content:
* application/json:
* schema:
* type: object
* required:
* - email
* properties:
* email:
* type: string
* description: 邮箱地址
* example: 'user@example.com'
* responses:
* 200:
* description: 发送成功
*/
'POST /invite/send-email-code': async (ctx) => {
try {
const body = ctx.getBody();
const { email } = body;
if (!email) {
return ctx.fail('邮箱地址不能为空');
}
// 验证邮箱格式
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
if (!emailRegex.test(email)) {
return ctx.fail('邮箱格式不正确');
}
// 发送验证码
const emailResult = await sendEmailCode(email);
if (!emailResult.success) {
return ctx.fail(emailResult.message || '发送验证码失败');
}
return ctx.success({
message: '验证码已发送',
expire_time: emailResult.expire_time || 300 // 默认5分钟过期
});
} catch (error) {
console.error('发送验证码失败:', error);
return ctx.fail('发送验证码失败: ' + error.message);
}
}
};
/**
* 发送验证码
* @param {string} email 邮箱地址
* @returns {Promise<{success: boolean, message?: string, expire_time?: number}>}
*/
async function sendEmailCode(email) {
try {
// 生成6位随机验证码
const code = Math.floor(100000 + Math.random() * 900000).toString();
// 将验证码存储到缓存中可以使用Redis或内存缓存
// 格式email_code:{email} = {code, expire_time}
const expire_time = Date.now() + 5 * 60 * 1000; // 5分钟后过期
// 这里应该存储到缓存中暂时使用全局变量生产环境应使用Redis
if (!global.emailCodeCache) {
global.emailCodeCache = {};
}
global.emailCodeCache[email] = {
code: code,
expire_time: expire_time
};
// 调用邮件服务发送验证码
const email_result = await email_service.send_verification_code(email, code);
if (!email_result.success) {
// 如果邮件发送失败,删除已生成的验证码
delete global.emailCodeCache[email];
return {
success: false,
message: email_result.message || '发送验证码失败'
};
}
console.log(`[邮箱验证] 验证码已发送到 ${email}: ${code} (5分钟内有效)`);
return {
success: true,
expire_time: 300
};
} catch (error) {
console.error('发送验证码失败:', error);
return {
success: false,
message: error.message || '发送验证码失败'
};
}
}
/**
* 验证验证码
* @param {string} email 邮箱地址
* @param {string} code 验证码
* @returns {Promise<{success: boolean, message?: string}>}
*/
async function verifyEmailCode(email, code) {
try {
if (!global.emailCodeCache) {
return {
success: false,
message: '验证码不存在或已过期'
};
}
const cached = global.emailCodeCache[email];
if (!cached) {
return {
success: false,
message: '验证码不存在或已过期'
};
}
// 检查是否过期
if (Date.now() > cached.expire_time) {
delete global.emailCodeCache[email];
return {
success: false,
message: '验证码已过期,请重新获取'
};
}
// 验证码是否正确
if (cached.code !== code) {
return {
success: false,
message: '验证码错误'
};
}
// 验证成功后删除缓存
delete global.emailCodeCache[email];
return {
success: true
};
} catch (error) {
console.error('验证验证码失败:', error);
return {
success: false,
message: error.message || '验证失败'
};
}
}