**AllGroup表 **
字段名称 | 字段类型 | 字段说明 | 约束 |
---|---|---|---|
id | INT | 组id | PRIMARY KEY、AUTO_INCREMENT |
groupname | VARCHAR(50) | 组名称 | NOT NULL, UNIQUE |
groupdesc | VARCHAR(200) | 组功能描述 | DEFAULT ‘’ |
**GroupUser表 **
字段名称 | 字段类型 | 字段说明 | 约束 |
---|---|---|---|
groupid | INT | 组id | NOT NULL、联合主键 |
userid | INT | 组员id | NOT NULL、联合主键 |
grouprole | ENUM(‘creator’, ‘normal’) | 组内角色 | DEFAULT ‘normal’ |
#ifndef __GROUP_USER_H__
#define __GROUP_USER_H__
#include "user.hpp"
#include
class GroupUser : public User
{
public:
GroupUser() = default;
void setRole(const std::string& role) { _role = role; }
std::string getRole() { return _role; }
private:
std::string _role;
};
#endif // __GROUP_USER_H__
#ifndef __GROUP_MODEL_H
#define __GROUP_MODEL_H
#include "group.hpp"
#include
#include
class GroupModel
{
public:
// 创建群组
bool createGroup(Group &group);
// 加入群组
void addGroup(int userid, int groupid, std::string role);
// 查询用户所在群组信息
std::vector<Group> queryGroups(int userid);
// 根据指定的groupid查询群组用户id列表,除userid自己,主要用户群聊业务给群组其它成员群发消息
std::vector<int> queryGroupUsers(int userid, int groupid);
};
#endif // __GROUP_MODEL_H
#include "group_model.hpp"
#include "db.h"
// 创建群组(设置群组名字和描述)
bool GroupModel::createGroup(Group &group)
{
char sql[1024] = {0};
snprintf(sql, sizeof(sql), "insert into allgroup(groupname, groupdesc) values('%s', '%s')",
group.getName().c_str(), group.getDesc().c_str());
MySQL mysql;
if (mysql.connect())
{
if (mysql.update(sql))
{
group.setId(mysql_insert_id(mysql.getConnection()));
return true;
}
}
return false;
}
// 加入群组(用户ID 加入群组ID 在群组角色)
void GroupModel::addGroup(int userid, int groupid, std::string role)
{
char sql[1024] = {0};
snprintf(sql, sizeof(sql), "insert into groupuser values(%d, %d, '%s')",
groupid, userid, role.c_str());
MySQL mysql;
if (mysql.connect())
{
mysql.update(sql);
}
}
// 查询用户所在群组信息
std::vector<Group> GroupModel::queryGroups(int userid)
{
/**
* // TODO:MySQL联表查询
* 1. 先根据userid在groupuser表中查询出该用户所属的群组信息
* 2. 再根据群组信息,查询属于该群组的所有用户的userid,并且和user表进行多表联合查询,查出用户的详细信息
*/
char sql[1024] = {0};
snprintf(sql, sizeof(sql), "select a.id,a.groupname,a.groupdesc from allgroup a inner join \
groupuser b on a.id = b.groupid where b.userid=%d",
userid);
std::vector<Group> groupVec;
MySQL mysql;
if (mysql.connect())
{
MYSQL_RES *res = mysql.query(sql);
if (res != nullptr)
{
MYSQL_ROW row;
// 查出userid所有的群组信息
while ((row = mysql_fetch_row(res)) != nullptr)
{
Group group;
group.setId(atoi(row[0]));
group.setName(row[1]);
group.setDesc(row[2]);
groupVec.push_back(group);
}
mysql_free_result(res);
}
}
// 查询群组的用户信息
for (Group &group : groupVec)
{
snprintf(sql, sizeof(sql), "select a.id,a.name,a.state,b.grouprole from user a \
inner join groupuser b on b.userid = a.id where b.groupid=%d",
group.getId());
MYSQL_RES *res = mysql.query(sql);
if (res != nullptr)
{
MYSQL_ROW row;
while ((row = mysql_fetch_row(res)) != nullptr)
{
GroupUser user;
user.setId(atoi(row[0]));
user.setName(row[1]);
user.setState(row[2]);
user.setRole(row[3]);
group.getUsers().push_back(user);
}
mysql_free_result(res);
}
}
return groupVec;
}
// 根据指定的groupid查询群组用户id列表,除userid自己,主要用户群聊业务给群组其它成员群发消息
std::vector<int> GroupModel::queryGroupUsers(int userid, int groupid)
{
char sql[1024] = {0};
sprintf(sql, "select userid from groupuser where groupid = %d and userid != %d", groupid, userid);
vector<int> idVec;
MySQL mysql;
if (mysql.connect())
{
MYSQL_RES *res = mysql.query(sql);
if (res != nullptr)
{
MYSQL_ROW row;
while ((row = mysql_fetch_row(res)) != nullptr)
{
idVec.push_back(atoi(row[0]));
}
mysql_free_result(res);
}
}
return idVec;
}
// 创建群组业务
void ChatService::createGroup(const TcpConnectionPtr &conn, json &js, Timestamp time)
{
int userId = js["id"].get<int>();
std::string name = js["groupname"];
std::string desc = js["groupesc"];
// 存储新创建的群组消息
Group group(-1, name, desc);
if (_groupModel.createGroup(group))
{
// 存储群组创建人信息
_groupModel.addGroup(userId, group.getId(), "creator");
}
}
// 加入群组业务
void ChatService::addGroup(const TcpConnectionPtr &conn, json &js, Timestamp time)
{
int userId = js["id"].get<int>();
int groupId = js["groupid"].get<int>();
_groupModel.addGroup(userId, groupId, "normal");
}
// 群组聊天业务
void ChatService::groupChat(const TcpConnectionPtr &conn, json &js, Timestamp time)
{
int userId = js["id"].get<int>();
int groupId = js["groupid"].get<int>();
std::vector<int> userIdVec = _groupModel.queryGroupUsers(userId, groupId);
lock_guard<mutex> lock(_connMutex);
for (int id : userIdVec)
{
auto it = _userConnMap.find(id);
if (it != _userConnMap.end())
{
// 转发群消息
it->second->send(js.dump());
}
else
{
// 查询toid是否在线
User user = _userModel.query(id);
if (user.getState() == "online")
{
// 向群组成员publish信息
_redis.publish(id, js.dump());
}
else
{
//转储离线消息
_offlineMsgModel.insert(id, js.dump());
}
}
}
}
这是之前的所有群组
登录张三的用户,创建了两个学习群组。Java和PHP
登录新的用户,加入群组13
{"msgid":1008,"id":15,"groupid":13}
还是有一些问题的,比如重复让同一成员加入群组,这里不会提示报错,看日后迭代吧。