首次完整推送,
V:1.20240808.006
This commit is contained in:
@ -0,0 +1,192 @@
|
||||
const {
|
||||
dbCmd,
|
||||
userCollection
|
||||
} = require('../../common/constants')
|
||||
const {
|
||||
ERROR
|
||||
} = require('../../common/error')
|
||||
/**
|
||||
* 获取随机邀请码,邀请码由大写字母加数字组成,由于存在手动输入邀请码的场景,从可选字符中去除 0、1、I、O
|
||||
* @param {number} len 邀请码长度,默认6位
|
||||
* @returns {string} 随机邀请码
|
||||
*/
|
||||
function getRandomInviteCode (len = 6) {
|
||||
const charArr = ['2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K', 'L', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z']
|
||||
let code = ''
|
||||
for (let i = 0; i < len; i++) {
|
||||
code += charArr[Math.floor(Math.random() * charArr.length)]
|
||||
}
|
||||
return code
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取可用的邀请码,至多尝试十次以获取可用邀请码。从10亿可选值中随机,碰撞概率较低
|
||||
* 也有其他方案可以尝试,比如在数据库内设置一个从0开始计数的数字,每次调用此方法时使用updateAndReturn使数字加1并返回加1后的值,根据这个值生成对应的邀请码,比如(22222A + 1 == 22222B),此方式性能理论更好,但是不适用于旧项目
|
||||
* @param {object} param
|
||||
* @param {string} param.inviteCode 初始随机邀请码
|
||||
*/
|
||||
async function getValidInviteCode () {
|
||||
let retry = 10
|
||||
let code
|
||||
let codeValid = false
|
||||
while (retry > 0 && !codeValid) {
|
||||
retry--
|
||||
code = getRandomInviteCode()
|
||||
const getUserRes = await userCollection.where({
|
||||
my_invite_code: code
|
||||
}).limit(1).get()
|
||||
if (getUserRes.data.length === 0) {
|
||||
codeValid = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if (!codeValid) {
|
||||
throw {
|
||||
errCode: ERROR.SET_INVITE_CODE_FAILED
|
||||
}
|
||||
}
|
||||
return code
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据邀请码查询邀请人
|
||||
* @param {object} param
|
||||
* @param {string} param.inviteCode 邀请码
|
||||
* @param {string} param.queryUid 受邀人id,非空时校验不可被下家或自己邀请
|
||||
* @returns
|
||||
*/
|
||||
async function findUserByInviteCode ({
|
||||
inviteCode,
|
||||
queryUid
|
||||
} = {}) {
|
||||
if (typeof inviteCode !== 'string') {
|
||||
throw {
|
||||
errCode: ERROR.SYSTEM_ERROR
|
||||
}
|
||||
}
|
||||
// 根据邀请码查询邀请人
|
||||
let getInviterRes
|
||||
if (queryUid) {
|
||||
getInviterRes = await userCollection.where({
|
||||
_id: dbCmd.neq(queryUid),
|
||||
inviter_uid: dbCmd.not(dbCmd.all([queryUid])),
|
||||
my_invite_code: inviteCode
|
||||
}).get()
|
||||
} else {
|
||||
getInviterRes = await userCollection.where({
|
||||
my_invite_code: inviteCode
|
||||
}).get()
|
||||
}
|
||||
if (getInviterRes.data.length > 1) {
|
||||
// 正常情况下不可能进入此条件,以防用户自行修改数据库出错,在此做出判断
|
||||
throw {
|
||||
errCode: ERROR.SYSTEM_ERROR
|
||||
}
|
||||
}
|
||||
const inviterRecord = getInviterRes.data[0]
|
||||
if (!inviterRecord) {
|
||||
throw {
|
||||
errCode: ERROR.INVALID_INVITE_CODE
|
||||
}
|
||||
}
|
||||
return inviterRecord
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据邀请码生成邀请信息
|
||||
* @param {object} param
|
||||
* @param {string} param.inviteCode 邀请码
|
||||
* @param {string} param.queryUid 受邀人id,非空时校验不可被下家或自己邀请
|
||||
* @returns
|
||||
*/
|
||||
async function generateInviteInfo ({
|
||||
inviteCode,
|
||||
queryUid
|
||||
} = {}) {
|
||||
const inviterRecord = await findUserByInviteCode({
|
||||
inviteCode,
|
||||
queryUid
|
||||
})
|
||||
// 倒叙拼接当前用户邀请链
|
||||
const inviterUid = inviterRecord.inviter_uid || []
|
||||
inviterUid.unshift(inviterRecord._id)
|
||||
return {
|
||||
inviterUid,
|
||||
inviteTime: Date.now()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查当前用户是否可以接受邀请,如果可以返回用户记录
|
||||
* @param {string} uid
|
||||
*/
|
||||
async function checkInviteInfo (uid) {
|
||||
// 检查当前用户是否已有邀请人
|
||||
const getUserRes = await userCollection.doc(uid).field({
|
||||
my_invite_code: true,
|
||||
inviter_uid: true
|
||||
}).get()
|
||||
const userRecord = getUserRes.data[0]
|
||||
if (!userRecord) {
|
||||
throw {
|
||||
errCode: ERROR.ACCOUNT_NOT_EXISTS
|
||||
}
|
||||
}
|
||||
if (userRecord.inviter_uid && userRecord.inviter_uid.length > 0) {
|
||||
throw {
|
||||
errCode: ERROR.CHANGE_INVITER_FORBIDDEN
|
||||
}
|
||||
}
|
||||
return userRecord
|
||||
}
|
||||
|
||||
/**
|
||||
* 指定用户接受邀请码邀请
|
||||
* @param {object} param
|
||||
* @param {string} param.uid 用户uid
|
||||
* @param {string} param.inviteCode 邀请人的邀请码
|
||||
* @returns
|
||||
*/
|
||||
async function acceptInvite ({
|
||||
uid,
|
||||
inviteCode
|
||||
} = {}) {
|
||||
await checkInviteInfo(uid)
|
||||
const {
|
||||
inviterUid,
|
||||
inviteTime
|
||||
} = await generateInviteInfo({
|
||||
inviteCode,
|
||||
queryUid: uid
|
||||
})
|
||||
|
||||
if (inviterUid === uid) {
|
||||
throw {
|
||||
errCode: ERROR.INVALID_INVITE_CODE
|
||||
}
|
||||
}
|
||||
|
||||
// 更新当前用户的邀请人信息
|
||||
await userCollection.doc(uid).update({
|
||||
inviter_uid: inviterUid,
|
||||
invite_time: inviteTime
|
||||
})
|
||||
|
||||
// 更新当前用户邀请的用户的邀请人信息,这步可能较为耗时
|
||||
await userCollection.where({
|
||||
inviter_uid: uid
|
||||
}).update({
|
||||
inviter_uid: dbCmd.push(inviterUid)
|
||||
})
|
||||
|
||||
return {
|
||||
errCode: 0,
|
||||
errMsg: ''
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
acceptInvite,
|
||||
generateInviteInfo,
|
||||
getValidInviteCode
|
||||
}
|
Reference in New Issue
Block a user