Files
autoAiWorkSys/api/controller_admin/invite_register.js
张成 41e03daa50 1
2025-12-16 15:55:42 +08:00

341 lines
9.8 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');
module.exports = {
/**
* @swagger
* /admin_api/invite/register:
* post:
* summary: 邀请注册
* description: 通过邀请码注册新用户注册成功后给邀请人增加3天试用期
* tags: [后台-邀请注册]
* requestBody:
* required: true
* content:
* application/json:
* schema:
* type: object
* required:
* - phone
* - password
* - sms_code
* - invite_code
* properties:
* phone:
* type: string
* description: 手机号
* example: '13800138000'
* password:
* type: string
* description: 密码
* example: 'password123'
* sms_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 { phone, password, sms_code, invite_code } = body;
// 验证参数
if (!phone || !password || !sms_code || !invite_code) {
return ctx.fail('手机号、密码、短信验证码和邀请码不能为空');
}
// 验证手机号格式
const phoneRegex = /^1[3-9]\d{9}$/;
if (!phoneRegex.test(phone)) {
return ctx.fail('手机号格式不正确');
}
// 验证密码长度
if (password.length < 6) {
return ctx.fail('密码长度不能少于6位');
}
// 验证短信验证码(这里需要调用短信验证服务)
const smsVerifyResult = await verifySmsCode(phone, sms_code);
if (!smsVerifyResult.success) {
return ctx.fail(smsVerifyResult.message || '短信验证码错误或已过期');
}
const { pla_account } = await Framework.getModels();
// 检查手机号是否已注册
const existingUser = await pla_account.findOne({
where: { login_name: phone }
});
if (existingUser) {
return ctx.fail('该手机号已被注册');
}
// 解析邀请码获取邀请人ID
// 邀请码格式INV{user_id}_{timestamp}
const inviteMatch = invite_code.match(/^INV(\d+)_/);
if (!inviteMatch) {
return ctx.fail('邀请码格式不正确');
}
const inviter_id = parseInt(inviteMatch[1]);
// 验证邀请人是否存在
const 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: phone, // 默认使用手机号作为名称
sn_code: sn_code,
device_id: '', // 设备ID由客户端登录时提供
platform_type: 'boss', // 默认平台类型
login_name: phone,
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: phone,
invite_code: invite_code,
register_time: new Date(),
reward_status: 1, // 已发放
reward_type: 'trial_days',
reward_value: 3,
is_delete: 0
});
console.log(`[邀请注册] 用户 ${phone} 通过邀请码 ${invite_code} 注册成功,邀请人 ${inviter.sn_code} 获得3天试用期`);
}
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-sms:
* post:
* summary: 发送短信验证码
* description: 发送短信验证码到指定手机号
* tags: [后台-邀请注册]
* requestBody:
* required: true
* content:
* application/json:
* schema:
* type: object
* required:
* - phone
* properties:
* phone:
* type: string
* description: 手机号
* example: '13800138000'
* responses:
* 200:
* description: 发送成功
*/
'POST /invite/send-sms': async (ctx) => {
try {
const body = ctx.getBody();
const { phone } = body;
if (!phone) {
return ctx.fail('手机号不能为空');
}
// 验证手机号格式
const phoneRegex = /^1[3-9]\d{9}$/;
if (!phoneRegex.test(phone)) {
return ctx.fail('手机号格式不正确');
}
// 发送短信验证码
const smsResult = await sendSmsCode(phone);
if (!smsResult.success) {
return ctx.fail(smsResult.message || '发送短信验证码失败');
}
return ctx.success({
message: '短信验证码已发送',
expire_time: smsResult.expire_time || 300 // 默认5分钟过期
});
} catch (error) {
console.error('发送短信验证码失败:', error);
return ctx.fail('发送短信验证码失败: ' + error.message);
}
}
};
/**
* 发送短信验证码
* @param {string} phone 手机号
* @returns {Promise<{success: boolean, message?: string, expire_time?: number}>}
*/
async function sendSmsCode(phone) {
try {
// TODO: 实现真实的短信发送逻辑
// 这里可以使用第三方短信服务(如阿里云、腾讯云等)
// 生成6位随机验证码
const code = Math.floor(100000 + Math.random() * 900000).toString();
// 将验证码存储到缓存中可以使用Redis或内存缓存
// 格式sms_code:{phone} = {code, expire_time}
const expire_time = Date.now() + 5 * 60 * 1000; // 5分钟后过期
// 这里应该存储到缓存中暂时使用全局变量生产环境应使用Redis
if (!global.smsCodeCache) {
global.smsCodeCache = {};
}
global.smsCodeCache[phone] = {
code: code,
expire_time: expire_time
};
// TODO: 调用真实的短信发送接口
console.log(`[短信验证] 发送验证码到 ${phone}: ${code} (5分钟内有效)`);
// 模拟发送成功
return {
success: true,
expire_time: 300
};
} catch (error) {
console.error('发送短信验证码失败:', error);
return {
success: false,
message: error.message || '发送短信验证码失败'
};
}
}
/**
* 验证短信验证码
* @param {string} phone 手机号
* @param {string} code 验证码
* @returns {Promise<{success: boolean, message?: string}>}
*/
async function verifySmsCode(phone, code) {
try {
if (!global.smsCodeCache) {
return {
success: false,
message: '验证码不存在或已过期'
};
}
const cached = global.smsCodeCache[phone];
if (!cached) {
return {
success: false,
message: '验证码不存在或已过期'
};
}
// 检查是否过期
if (Date.now() > cached.expire_time) {
delete global.smsCodeCache[phone];
return {
success: false,
message: '验证码已过期,请重新获取'
};
}
// 验证码是否正确
if (cached.code !== code) {
return {
success: false,
message: '验证码错误'
};
}
// 验证成功后删除缓存
delete global.smsCodeCache[phone];
return {
success: true
};
} catch (error) {
console.error('验证短信验证码失败:', error);
return {
success: false,
message: error.message || '验证失败'
};
}
}