好友:一键申请提示

This commit is contained in:
luying
2021-02-02 19:47:57 +08:00
parent 5da98956b9
commit 1fb4e7b9be
12 changed files with 245 additions and 37 deletions

View File

@@ -1,13 +1,15 @@
import { Application, BackendSession } from "pinus"; import { Application, BackendSession } from "pinus";
import { resResult, getRandEelm } from "../../../pubUtils/util"; import { resResult, getRandEelm, getResStr } from "../../../pubUtils/util";
import { STATUS, ROLE } from "../../../consts"; import { STATUS, ROLE, FRIEND_DROP_TYPE, FRIEND_RELATION_TYPE } from "../../../consts";
import Role, { RoleModel, RoleType } from "../../../db/Role"; import { RoleModel, RoleType } from "../../../db/Role";
import { getBeforeDaySeconds } from "../../../pubUtils/timeUtil"; import { getBeforeDaySeconds } from "../../../pubUtils/timeUtil";
import { FriendApplyModel } from "../../../db/FriendApply"; import { FriendApplyModel } from "../../../db/FriendApply";
import { FriendApplyParams, FriendListParam } from "../../../domain/roleField/friend"; import { FriendApplyParams, FriendListParam, FriendRecommendParams } from "../../../domain/roleField/friend";
import { FriendShipModel, FriendShipType } from "../../../db/FriendShip"; import { FriendShipModel, FriendShipType } from "../../../db/FriendShip";
import { FriendRelationModel } from "../../../db/FriendRelation"; import { FriendRelationModel } from "../../../db/FriendRelation";
import { isRoleOnline } from "../../../services/redisService"; import { isRoleOnline } from "../../../services/redisService";
import { increaseFrdCnt, getRecommendType } from "../../../services/friendService";
import { FriendPointModel } from "../../../db/FriendPoint";
export default function (app: Application) { export default function (app: Application) {
return new FriendHandler(app); return new FriendHandler(app);
@@ -25,9 +27,41 @@ export class FriendHandler {
const day = getBeforeDaySeconds(1); const day = getBeforeDaySeconds(1);
const { lv } = await RoleModel.findByRoleId(roleId, ROLE.GET_LV); const { lv } = await RoleModel.findByRoleId(roleId, ROLE.GET_LV);
const allList = await RoleModel.getRecommedList(roleId, lv - 5, lv + 5, day); let allList = await RoleModel.getRecommedList(lv - 5, lv + 5, day);
let list = getRandEelm(allList, 10);
if(!list.length) list = allList; let myFriendRelation = await FriendRelationModel.findFriendByRole(roleId, false);
let paramAllList = new Array<FriendRecommendParams>();
for(let role of allList) {
let type = getRecommendType(myFriendRelation, roleId, role.roleId);
if(type == FRIEND_RELATION_TYPE.NORMAL) {
let param = new FriendRecommendParams(role);
param.setType(type);
paramAllList.push(param);
}
}
let list = getRandEelm(paramAllList, 6);
if(!list.length) list = paramAllList;
return resResult(STATUS.SUCCESS, { list });
}
// 搜索好友
public async searchUser(msg: { value: string }, session: BackendSession) {
let roleId: string = session.get('roleId');
let { value } = msg;
let allList = await RoleModel.searchByNameOrId(value);
let myFriendRelation = await FriendRelationModel.findFriendByRole(roleId, false);
let list = new Array<FriendRecommendParams>();
for(let role of allList) {
let type = getRecommendType(myFriendRelation, roleId, role.roleId);
let param = new FriendRecommendParams(role);
param.setType(type);
list.push(param);
}
return resResult(STATUS.SUCCESS, { list }); return resResult(STATUS.SUCCESS, { list });
} }
@@ -39,18 +73,38 @@ export class FriendHandler {
let roleIds = msg.roleIds; let roleIds = msg.roleIds;
const role = await RoleModel.findByRoleId(roleId, ROLE.GET_ROLE_ID); const role = await RoleModel.findByRoleId(roleId, ROLE.GET_ROLE_ID);
let myFriendRelation = await FriendRelationModel.findFriendByRole(roleId, false);
let str = '', resultRoleIds = new Array<string>();
for(let hisRoleId of roleIds) { for(let hisRoleId of roleIds) {
let type = getRecommendType(myFriendRelation, roleId, hisRoleId);
if(type == FRIEND_RELATION_TYPE.HAS_FRIEND) {
str = getResStr(STATUS.FRIEND_HAS_ADD); continue;
} else if(type == FRIEND_RELATION_TYPE.HAS_BLOCKED) {
str = getResStr(STATUS.FRIEND_HAS_BLOCKED); continue;
} else if (type == FRIEND_RELATION_TYPE.MYSELF) {
str = getResStr(STATUS.FRIEND_YOURSELF); continue;
}
let incResult = await RoleModel.increaseFriendApplyCnt(hisRoleId, 1, 50);
if(!incResult) {
str = getResStr(STATUS.FRIEND_HIS_APPLY_MAX); continue;
}
await FriendApplyModel.createApply(hisRoleId, role); await FriendApplyModel.createApply(hisRoleId, role);
resultRoleIds.push(hisRoleId);
} }
return resResult(STATUS.SUCCESS, { return resResult(STATUS.SUCCESS, {
isSuccess: true isSuccess: str == '',
msg: str,
roleIds: resultRoleIds
}); });
} }
// 获取申请列表 // 获取申请列表
public async getApplyList(msg: { lastApplyCode: string }, session: BackendSession) { public async getApplyList(msg: { }, session: BackendSession) {
// TODO 分页
let roleId: string = session.get('roleId'); let roleId: string = session.get('roleId');
let list = await FriendApplyModel.getApplyList(roleId); let list = await FriendApplyModel.getApplyList(roleId);
@@ -72,28 +126,58 @@ export class FriendHandler {
let { applyCodeList, isPass } = msg; let { applyCodeList, isPass } = msg;
let role = await RoleModel.findByRoleId(roleId); let role = await RoleModel.findByRoleId(roleId);
let friendCnt = role.friendCnt;
let myFriendRelation = await FriendRelationModel.findFriendByRole(roleId, false);
let applyList = await FriendApplyModel.getApplyListByCode(applyCodeList); let applyList = await FriendApplyModel.getApplyListByCode(applyCodeList);
let result = new Array<FriendApplyParams>(); let list = new Array<FriendListParam>();
let str = '', resultApplyCodeList = new Array<string>();
if(isPass) { if(isPass) {
for(let apply of applyList) { for(let apply of applyList) {
let type = getRecommendType(myFriendRelation, roleId, apply.frdRoleId);
if(type == FRIEND_RELATION_TYPE.HAS_FRIEND) {
str = getResStr(STATUS.FRIEND_HAS_ADD); continue;
} else if(type == FRIEND_RELATION_TYPE.HAS_BLOCKED) {
str = getResStr(STATUS.FRIEND_HAS_BLOCKED); continue;
} else if (type == FRIEND_RELATION_TYPE.MYSELF) {
str = getResStr(STATUS.FRIEND_YOURSELF); continue;
}
// 好友数量校验
let friend = <RoleType>apply.friend; let friend = <RoleType>apply.friend;
// TODO检查我的好友人数上限检查加过好友没有 str = await increaseFrdCnt(role, friend, friendCnt);
// TODO检查对方的好友人数上限 if(str != '') continue;
// 创建friendShip // 创建friendShip
let friendShip = await FriendShipModel.createFriendShip([roleId, friend.roleId]); let friendShip = await FriendShipModel.createFriendShip([roleId, friend.roleId]);
if(!friendShip) continue; if(!friendShip) {
// 创建或push我的好友relation str = getResStr(STATUS.FRIEND_SHIP_CREATE_ERROR); continue;
let result1 = await FriendRelationModel.addFriend(roleId, friend, friendShip);
// 创建或push他的好友relation
let result2 = await FriendRelationModel.addFriend(friend.roleId, role, friendShip);
}
} }
// await FriendApplyModel.deleteApply(applyCodeList); await FriendRelationModel.addFriend(roleId, friend, friendShip);
await FriendRelationModel.addFriend(friend.roleId, role, friendShip);
let param = new FriendListParam(friend, friendShip);
let isOnline = await isRoleOnline(friend.roleId);
param.setOnline(isOnline);
list.push(param);
resultApplyCodeList.push(apply.applyCode);
}
} else {
resultApplyCodeList = applyCodeList;
}
await FriendApplyModel.deleteApply(resultApplyCodeList);
return resResult(STATUS.SUCCESS, { return resResult(STATUS.SUCCESS, {
list: result isSuccess: str == '',
msg: str,
applyCodeList: resultApplyCodeList,
list,
friendCnt
}); });
} }
@@ -127,9 +211,12 @@ export class FriendHandler {
} }
let { friendCnt = 0, blockCnt = 0 } = role; let { friendCnt = 0, blockCnt = 0 } = role;
let frdPointRec = await FriendPointModel.getFrdPointRecToday(roleId, FRIEND_DROP_TYPE.SEND_GIFT);
let { cnt: todayReceiveCnt = 0, sendCnt: todaySendCnt = 0 } = frdPointRec||{};
return resResult(STATUS.SUCCESS, { return resResult(STATUS.SUCCESS, {
todayReceiveCnt: 0, todayReceiveCnt,
todaySendCnt: 0, todaySendCnt,
list, list,
friendCnt, blockCnt friendCnt, blockCnt
}); });

View File

@@ -0,0 +1,51 @@
import { gameData } from "../pubUtils/data";
import { RoleType, RoleModel } from "../db/Role";
import { FriendRelationType } from "../db/FriendRelation";
import { getResStr } from "../pubUtils/util";
import { STATUS, FRIEND_RELATION_TYPE } from "../consts";
/**
* 增加双方好友数
* @param role1 我方
* @param role2 对方
* @returns 是否添加成功
*/
export async function increaseFrdCnt(role1: RoleType, role2: RoleType, originalFriendCnt: number) {
let { roleId, lv, friendCnt } = role1;
let dicFriend = gameData.roleFriend.get(lv);
if(friendCnt >= dicFriend.frdCnt) return getResStr(STATUS.FRIEND_MY_CNT_MAX);
let { roleId: _roleId, lv: _lv, friendCnt: _friendCnt } = role2;
let _dicFriend = gameData.roleFriend.get(_lv);
if(_friendCnt >= _dicFriend.frdCnt) return getResStr(STATUS.FRIEND_THEY_CNT_MAX);
let incMyFrdCnt = await RoleModel.increaseFriendCnt(roleId, 1, dicFriend.frdCnt);
if(!incMyFrdCnt) return getResStr(STATUS.FRIEND_MY_CNT_MAX);
let incHisFrdCnt = await RoleModel.increaseFriendCnt(_roleId, 1, _dicFriend.frdCnt);
if(!incHisFrdCnt) { // 回滚
await RoleModel.increaseFriendCnt(roleId, -1, dicFriend.frdCnt);
return getResStr(STATUS.FRIEND_THEY_CNT_MAX);
}
originalFriendCnt = incMyFrdCnt.friendCnt;
return '';
}
export function getRecommendType(myFriendRelation: FriendRelationType, myRoleId: string, roleId: string) {
if(myRoleId == roleId) {
return FRIEND_RELATION_TYPE.MYSELF;
}
let friendList = myFriendRelation? myFriendRelation.friends: [];
let blackList = myFriendRelation? myFriendRelation.blacklist: [];
let hasFriend = friendList.find(cur => cur.roleId == roleId);
if(hasFriend) {
return FRIEND_RELATION_TYPE.HAS_FRIEND;
}
let hasBlcklist = blackList.find(cur => cur.roleId == roleId);
if(hasBlcklist) {
return FRIEND_RELATION_TYPE.HAS_BLOCKED;
}
return FRIEND_RELATION_TYPE.NORMAL;
}

View File

@@ -2,6 +2,7 @@
export enum ROLE { export enum ROLE {
// 玩家列表显示基础数据 // 玩家列表显示基础数据
SHOW_SIMPLE = 'roleId roleName ce headHid sHid lv title job quitTime vLv guildName', SHOW_SIMPLE = 'roleId roleName ce headHid sHid lv title job quitTime vLv guildName',
SHOW_FRIEND_APPLY_LIST = 'roleId roleName ce headHid sHid lv title job quitTime vLv guildName friendCnt recFrdApplyCnt',
HANDLE_APPLY = 'roleId friendCnt lv', HANDLE_APPLY = 'roleId friendCnt lv',
GET_LV = 'lv', GET_LV = 'lv',

View File

@@ -243,7 +243,8 @@ export const FUNCS_ID = {
} }
export const FRIEND_DROP_TYPE = { export const FRIEND_DROP_TYPE = {
COM_BATTLE: 1 COM_BATTLE: 1,
SEND_GIFT: 2
} }
// 每日情谊点上限 // 每日情谊点上限
@@ -362,3 +363,10 @@ export const MAIL_TYPE = {
}; };
export const CHAT_SERVER = 'chat-server-1'; export const CHAT_SERVER = 'chat-server-1';
export enum FRIEND_RELATION_TYPE {
NORMAL = 1,
HAS_FRIEND = 2,
HAS_BLOCKED = 3,
MYSELF = 4
}

View File

@@ -231,7 +231,7 @@ export const STATUS = {
EQUIP_NOT_EQUIPED_HERO: { code: 30509, simStr: '装备不能被该武将穿戴' }, EQUIP_NOT_EQUIPED_HERO: { code: 30509, simStr: '装备不能被该武将穿戴' },
EQUIP_LEVEL_LIMIT: { code: 30510, simStr: '装备穿戴等级限制' }, EQUIP_LEVEL_LIMIT: { code: 30510, simStr: '装备穿戴等级限制' },
EQUIP_NOT_MATCH_JEWEL: { code: 30511, simStr: '装备不能镶嵌该宝石' }, EQUIP_NOT_MATCH_JEWEL: { code: 30511, simStr: '装备不能镶嵌该宝石' },
//全局养成30600-30799 //全局养成30600-30699
ROLE_REACH_MAX_TITLE_LEVEL: { code: 30600, simStr: '玩家已达到最高的爵位' }, ROLE_REACH_MAX_TITLE_LEVEL: { code: 30600, simStr: '玩家已达到最高的爵位' },
ROLE_TERAPH_NOT_STRENGTHEN: { code: 30601, simStr: '玩家神像不能强化' }, ROLE_TERAPH_NOT_STRENGTHEN: { code: 30601, simStr: '玩家神像不能强化' },
ROLE_TERAPH_NOT_QUILITY: { code: 30602, simStr: '玩家神像不能进阶' }, ROLE_TERAPH_NOT_QUILITY: { code: 30602, simStr: '玩家神像不能进阶' },
@@ -241,6 +241,14 @@ export const STATUS = {
ROLE_SCHOOL_POSITION_UNLOCK_NOT_NEED: { code: 30605, simStr: '该位置已解锁' }, ROLE_SCHOOL_POSITION_UNLOCK_NOT_NEED: { code: 30605, simStr: '该位置已解锁' },
ROLE_SCROLL_REACH_MAX: { code: 30606, simStr: '已经升到可以升的最高等级' }, ROLE_SCROLL_REACH_MAX: { code: 30606, simStr: '已经升到可以升的最高等级' },
// 好友30700-30799
FRIEND_MY_CNT_MAX: { code: 30700, simStr: '好友数量已达上限' },
FRIEND_THEY_CNT_MAX: { code: 30701, simStr: '玩家好友已满' },
FRIEND_HAS_ADD: { code: 30702, simStr: '该玩家已是您的好友' },
FRIEND_HAS_BLOCKED: { code: 30703, simStr: '该玩家在您的黑名单' },
FRIEND_YOURSELF: { code: 30704, simStr: '不能添加自己为好友' },
FRIEND_HIS_APPLY_MAX: { code: 30705, simStr: '该玩家申请达上限' },
FRIEND_SHIP_CREATE_ERROR: { code: 30706, simStr: '创建失败' },
// 社交相关状态 40000 - 49999 // 社交相关状态 40000 - 49999

View File

@@ -37,7 +37,7 @@ export default class FriendApply extends BaseModel {
public static async getApplyList(roleId: string) { public static async getApplyList(roleId: string) {
const list: FriendApplyType[] = await FriendApplyModel.find({ roleId }, { _id: 0 }) const list: FriendApplyType[] = await FriendApplyModel.find({ roleId }, { _id: 0 })
// .select(select) // .select(select)
.populate('friend', ROLE.SHOW_SIMPLE, 'Role') .populate('friend', ROLE.SHOW_FRIEND_APPLY_LIST, 'Role')
.lean({ getters: true }); .lean({ getters: true });
return list; return list;
} }
@@ -46,7 +46,7 @@ export default class FriendApply extends BaseModel {
public static async getApplyListByCode(applyCodeList: string[]) { public static async getApplyListByCode(applyCodeList: string[]) {
const list: FriendApplyType[] = await FriendApplyModel.find({ applyCode: { $in: applyCodeList } }, { _id: 0 }) const list: FriendApplyType[] = await FriendApplyModel.find({ applyCode: { $in: applyCodeList } }, { _id: 0 })
// .select(select) // .select(select)
.populate('friend', ROLE.SHOW_SIMPLE, 'Role') .populate('friend', ROLE.SHOW_FRIEND_APPLY_LIST, 'Role')
.lean({ getters: true }); .lean({ getters: true });
return list; return list;
} }

View File

@@ -14,6 +14,8 @@ export default class FriendPoint extends BaseModel {
@prop({ required: true, default: 0 }) @prop({ required: true, default: 0 })
cnt: number; // 当天获取的点数 cnt: number; // 当天获取的点数
@prop({ required: true, default: 0 }) @prop({ required: true, default: 0 })
sendCnt: number; // 当天赠送的点数
@prop({ required: true, default: 0 })
type: number; // 情谊点统计的类型,不同功能都可能有每日获取上限 type: number; // 情谊点统计的类型,不同功能都可能有每日获取上限
/** /**

View File

@@ -41,12 +41,17 @@ export default class FriendRelation extends BaseModel {
// 获取列表 // 获取列表
public static async findFriendByRole(roleId: string) { public static async findFriendByRole(roleId: string, populate = true) {
const result: FriendRelationType = await FriendRelationModel.findOne({ roleId }) let document = FriendRelationModel.findOne({ roleId })
.populate('friends.role', ROLE.SHOW_SIMPLE, 'Role')
.populate('friends.friendShip', null, 'FriendShip')
.lean({ getters: true, virtuals: true }); .lean({ getters: true, virtuals: true });
if (populate) {
document
.populate('friends.role', ROLE.SHOW_SIMPLE, 'Role')
.populate('friends.friendShip', null, 'FriendShip');
}
let result: FriendRelationType = await document;
return result; return result;
} }

View File

@@ -79,6 +79,7 @@ export default class FriendShip extends BaseModel {
return result; return result;
} }
// 查询关系
public static async deleteAccount(roleId: string) { public static async deleteAccount(roleId: string) {
let result = await FriendShipModel.deleteMany({ $or: [{ roleIdA: roleId }, { roleIdB: roleId }] }); let result = await FriendShipModel.deleteMany({ $or: [{ roleIdA: roleId }, { roleIdB: roleId }] });
return result; return result;

View File

@@ -222,6 +222,8 @@ export default class Role extends BaseModel {
friendCnt: number; // 好友人数 friendCnt: number; // 好友人数
@prop({ required: true, default: 0 }) @prop({ required: true, default: 0 })
blockCnt: number; // 黑名单人数 blockCnt: number; // 黑名单人数
@prop({ required: true, default: 0 })
recFrdApplyCnt: number; // 玩家收取好友申请数量
public static async findAllByUid(uid: number, lean = true) { public static async findAllByUid(uid: number, lean = true) {
const role: RoleType[] = await RoleModel.find({ 'userInfo.uid': uid }).select('roleId roleName serverId').lean(lean); const role: RoleType[] = await RoleModel.find({ 'userInfo.uid': uid }).select('roleId roleName serverId').lean(lean);
@@ -445,11 +447,25 @@ export default class Role extends BaseModel {
} }
// 获取好友推荐列表 // 获取好友推荐列表
public static async getRecommedList(roleId: string, minLv: number, maxLv: number, time: number) { public static async getRecommedList(minLv: number, maxLv: number, time: number) {
const result = await RoleModel.find({ loginTime: { $gt: time }, lv: { $gte: minLv, $lte: maxLv }, roleId: { $ne: roleId } }, { _id: 0 }) const result = await RoleModel.find({ loginTime: { $gt: time }, lv: { $gte: minLv, $lte: maxLv } }, { _id: 0 })
.select(ROLE.SHOW_SIMPLE) .select(ROLE.SHOW_FRIEND_APPLY_LIST)
.sort({quitTime: -1, lv: -1, ce: -1}) .sort({quitTime: -1, lv: -1, ce: -1})
.limit(100).lean({ getters: true }); .limit(200).lean({ getters: true });
return result;
}
// 查询玩家
public static async searchByNameOrId(value: string) {
const result = await RoleModel.find({
$or: [
{ roleName: { $regex: new RegExp(value.toString(), 'i') } },
{ roleId: value }
]
}, { _id: 0 })
.select(ROLE.SHOW_FRIEND_APPLY_LIST)
.sort({quitTime: -1, lv: -1, ce: -1})
.limit(200).lean({ getters: true });
return result; return result;
} }
@@ -467,7 +483,13 @@ export default class Role extends BaseModel {
// 增加好友数量 // 增加好友数量
public static async increaseFriendCnt(roleId: string, inc: number, max: number) { public static async increaseFriendCnt(roleId: string, inc: number, max: number) {
const result = await RoleModel.findOneAndUpdate({ roleId, friendCnt: {$lt: max}}, {$inc: { friendCnt: inc }}, {new: true}).lean(); const result = await RoleModel.findOneAndUpdate({ roleId, friendCnt: {$lte: max - inc}}, {$inc: { friendCnt: inc }}, {new: true}).lean();
return result;
}
// 增加好友申请数量
public static async increaseFriendApplyCnt(roleId: string, inc: number, max: number) {
const result = await RoleModel.findOneAndUpdate({ roleId, recFrdApplyCnt: {$lte: max - inc}}, {$inc: { recFrdApplyCnt: inc }}, {new: true}).lean();
return result; return result;
} }
} }

View File

@@ -21,11 +21,30 @@ export class FriendParams {
} }
} }
export class FriendRecommendParams extends FriendParams {
friendCnt: number = 0;
recFrdApplyCnt: number = 0;
type: number;
constructor(role: RoleType) {
super(role);
if(role.friendCnt) this.friendCnt = role.friendCnt;
if(role.recFrdApplyCnt) this.recFrdApplyCnt = role.recFrdApplyCnt;
}
setType(type: number) {
this.type = type;
}
}
export class FriendApplyParams extends FriendParams { export class FriendApplyParams extends FriendParams {
applyCode: string; applyCode: string;
friendCnt: number = 0;
constructor(applyCode: string, role: RoleType) { constructor(applyCode: string, role: RoleType) {
super(role); super(role);
this.applyCode = applyCode; this.applyCode = applyCode;
if(role.friendCnt) this.friendCnt = role.friendCnt;
} }
} }
@@ -35,8 +54,8 @@ export class FriendListParam extends FriendParams {
quitTime: number = 0; quitTime: number = 0;
friendValue: number = 0; friendValue: number = 0;
friendLv: number = 1; friendLv: number = 1;
canReceive: boolean = false; canReceive: boolean = false; // 初始没人送肯定不能领取
canSend: boolean = false; canSend: boolean = true; // 初始可以赠送
constructor(role: RoleType, friendship: FriendShipType) { constructor(role: RoleType, friendship: FriendShipType) {
super(role); super(role);

View File

@@ -324,6 +324,10 @@ export function resResult(status: { code: number, simStr: string }, data = null,
return { code, msg: customMsg || simStr, data }; return { code, msg: customMsg || simStr, data };
} }
export function getResStr(status: { code: number, simStr: string }) {
return status.simStr;
}
// 消除 js 浮点计算bug // 消除 js 浮点计算bug
export const cal = { export const cal = {