一、聊天消息表(普通消息,申请消息,群聊消息)
CREATE TABLE MSG_INFO ( MSG_Id INT PRIMARY KEY AUTO_INCREMENT, -- 消息标识 MSG_Type INT DEFAULT 0, -- 消息类型 0 普通消息 1、申请消息 , 2、群聊消息 MSG_GroupId INT DEFAULT 0, -- 分组id //可选用 User_Id INT DEFAULT 0, -- 发送申请的用户 User_Ided INT DEFAULT 0, -- 申请用户 MSG_Content LongText, -- 消息内容 MSG_State INT DEFAULT 0, -- 默认未读 消息类型 0 即已读,未读, 消息类型为 1 则 0未读 1是等待处理 2 同意 3拒绝 MSG_Updated datetime DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间-消息撤销时间', MSG_IsValid INT, -- 消息是否有效 MSG_Created DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP() -- 用户创建时间 )
二、我们要模拟从消息中查询申请消息
1、首选我们要可以注册
-- 分组 INSERT INTO SubGroup ( `SubG_GroupName`, `Acco_ID`, `SubG_Created`) VALUES ( '我的好友1', 7, '2019-09-30 10:17:42'); -- 注册好友 -- 好友表 -没有好友 INSERT INTO `Test`.`Friend` ( `User_Id`, `Frie_ById`, `Frie_Created`, `Acco_ID`) VALUES ('12', '5', '2019-09-30 10:15:42', '12'); -- 用户和分组关系表 -也没有好友分组关系的 INSERT INTO `Test`.`User_SubGroup` ( `User_Id`, `SubG_ById`, `Acco_ID`, `UsSu_Created`) VALUES ( '12', '4', '12', '2019-09-30 10:23:55'); SELECT * FROM SubGroup AS a LEFT JOIN User_SubGroup AS b ON a.SubG_ID = b.SubG_ById LEFT JOIN Friend AS c ON b.User_Id = c.Frie_ById LEFT JOIN Users AS d ON d.User_Id = c.Frie_ById WHERE a.Acco_ID=12
注册代码:
public class RegisterController : Controller { public IActionResult Index() { return View(); } [HttpPost] public async Task<IActionResult> AddUser([FromForm(Name = "file")] IFormFile file, string name, string password) { DbContext db = new DbContext(); Users user = db.Db.Queryable<Users>().Where(p => p.UserName == name).First(); //T_AccountModel userAccount = db.Db.Context..FirstOrDefault(t => t.UserName == Account); if (user != null) { return Json(new { State = false, Code = 0, Msg = "该用户名已被注册!", Time = DateTime.Now.ToString() }); } //图片上传 string date = DateTime.Now.ToString("yyyy-MM-dd"); string url = "/Upload/" + date + "/"; string path = Path.Combine(Environment.CurrentDirectory, "Upload", date); if (!System.IO.Directory.Exists(path))//判断上传路径是否存在 { System.IO.Directory.CreateDirectory(path); } string filePath = string.Empty; string fileName = string.Empty; if (file.Length > 0) { string fileFormat = System.IO.Path.GetExtension(file.FileName);//获取文件后缀格式 fileName = Guid.NewGuid().ToString("n") + fileFormat; filePath = Path.Combine(path, fileName);//中间处理为唯一格式文件 url = url + fileName; using (var stream = new FileStream(filePath, FileMode.Create)) { try { //保存文件 await file.CopyToAsync(stream); } catch (Exception ex) { return Json(new { State = false, Code = 0, Msg = "文件保存失败!", Time = DateTime.Now.ToString() }); } } } //return Json(new { Status = 1, Message = "保存成功" }); Users userModel = new Users { UserName = name, PassWord = password, Avatar = url }; int userId = db.Db.Insertable(userModel).ExecuteReturnIdentity();//insert if (userId != 0) { SubGroup subGroup = new SubGroup { Groupname = "我的好友", Acco_ID = userId, }; int res = db.Db.Insertable(subGroup).ExecuteReturnIdentity();//insert if (res != 0) { return Json(new { State = true, Code = 1, Msg = "用户注册成功!", Time = DateTime.Now.ToString() }); } else { return Json(new { State = false, Code = 0, Msg = "用户注册失败!", Time = DateTime.Now.ToString() }); } //https://www.cnblogs.com/ZaraNet/p/9988180.html } else { return Json(new { State = false, Code = 0, Msg = "用户注册失败!", Time = DateTime.Now.ToString() }); } // } }
html
@{ Layout = null; } <html> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>注册中心</title> <!-- Bootstrap 核心 CSS 文件 --> <link href="https://cdn.bootcss.com/normalize/8.0.1/normalize.min.css" rel="stylesheet"> <link rel="stylesheet" href="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/css/bootstrap.min.css"> <script src="https://cdn.staticfile.org/jquery/2.1.1/jquery.min.js"></script> <script src="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/js/bootstrap.min.js"></script> <script src="~/lib/upload.js"></script> <script src="https://cdn.bootcss.com/layer/2.3/layer.js"></script> <style> /*web background*/ .container { display: table; height: 100%; } .row { display: table-cell; vertical-align: middle; } /* centered columns styles */ .row-centered { text-align: center; } .col-centered { display: inline-block; float: none; text-align: left; margin-right: -4px; } </style> </head> <body> <div class="container"> <div class="row row-centered"> <div class="well col-md-4 col-xs-8 col-sm-7 col-centered"> <h2 style="text-align:center;padding-bottom:30px;">用户注册</h2> <div action="/login" method="post" role="form"> <div class="input-group input-group-md form-group" style="margin:20px auto"> <div id="drop_area" ></div> </div> <div class="input-group input-group-md form-group"> <span class="input-group-addon" id="sizing-addon1"><i class="glyphicon glyphicon-user" aria-hidden="true"></i></span> <input type="text" class="form-control" id="name" placeholder="请输入用户名" /> </div> <div class="input-group input-group-md form-group"> <span class="input-group-addon" id="sizing-addon1"><i class="glyphicon glyphicon-lock"></i></span> <input type="password" class="form-control" id="password" name="password" placeholder="请输入密码" /> </div> <br /> <button type="submit" class="btn btn-info btn-block">登录</button> </div> </div> </div> </div> <script type="text/javascript"> var files; $(function () { var dragImgUpload = new DragImgUpload("#drop_area", { callback: function (ele) { //回调函数,可以传递给后台等等 files = ele[0]; //console.log(file.name); } }) $('.btn-block').click(function () { if (!files) { layer.msg('请上传图片'); return ; } if ($('#name').val() == "") { layer.msg('请输入用户名'); return; } if ($('#password').val() == "") { layer.msg('请输入密码'); return; } var formData = new FormData(); formData.append("name", $('#name').val()); formData.append("password", $('#password').val()); formData.append("file", files); $.ajax({ url: '/Register/AddUser', type: 'post', timeout: 5000, contentType: false, enctype: 'multipart/form-data', //告诉jQuery不要去设置Content-Type请求头 processData: false, //告诉jQuery不要去处理发送的数据 data: formData, success: function (data) { console.log(data) if (data.state || data.code == 1) { window.location.href = '@Url.Action("Index", "Login")'; } else { //console.log("登陆异常!" + data) layer.msg(data.msg); } }, fail: function (err, status) { console.log("请求失败!" + err) }, error: function (err) { console.log("请求异常!"+err) } }); }); }); </script> </body> </html>
消息盒子-我们要从数据库的拿到消息盒子所以signalr要配合数据查询
因为前端调用Signalr内方法,所以在signalr 内写数据库操作。反之不能(想都不要想,不可以,难道控制器ajax请求触发推送消息吗,哪怕是个别的,我都有Signalr了。)
解决办法:(从项目model拿到创建一个DbHelper类库内,提供项目调用和Signalr调用,解决类库调用项目出现的依赖冲突。)
消息盒子和消息列表的问题:
消息盒子用Signalr从数据库读取(1、解决多个端的问题。2、不用ajax单独获取是否了 第二次 第三次的推送,不如直接一开始就用Signalr 是否有消息)
消息状态:0未读 1已读 2同意 3拒绝
A发送申请通知,又发一次通知,B点击之前第一个好友请求
针对第二种情况(单一用户多请求、获取请求添加列表不获取发送请求列表):A展示以及显示:-一开始分页获取所有用户请求,根据请求操作状态展示。
拿到数据 渲后前端判断如果0 则请求将拿到的后台数据更改已读,
然后点,同意则前端自动处理 该用户其他变灰,后台设置该用户其他所有请求无效,无效则灰色
点击拒绝 ,等价 前端数据该用的数据变灰,请求到后台更改这个消息为3拒绝,并且所有信息为灰色,即不可点击
多端的情况:
但是如果单户多端,则是点击该用户也要通知下自己放一个监听即可。仅通知更改状态,第二种情况,A户多端有一条,b户多端也有多条,就要a 添加 更改,就要更改与这个相关信息b端的所有相互的请求通知,并通知那个用户b页面则消息无效即可。b页面接受消息仅更改a用户请求通知的信息状态(a点击通知后台已经把这个全部改了)哪怕b从刷新也没关系。所以 a添加的时候 ,更改本页面,也要更改a的其他页面(signalr过滤本标志即可省力),并通知b其他页面,这个信息,区别是 ab是同一个监听是处理的 ,后台根据 a的id b的id 遍历发送 a的id参数 id 即可b的页面id即可
其实做的就是四步骤:
1、页面根据申请状态渲染
2、申请列表点击操作的时候,更改状态。
3、2步骤点击后,后台处理该用户所有消息为失效。并且设置该消息为操作的状态。
4、2步骤点击后,页面将该用户设置失效,并且通知B用户状态。
(具体这里A可以一直申请好友通知信息,比如B点击同意,B后台此A与B的好友请求全部失效,并更改此消息状态为2,通知用户标识为A的用户更改-为了单户多端)
(然后继续通知操作的那个用户B,更改B页面的B与A的好友为失效状态)
这里未作申请消息处理日志以及我的申请没法查看,只可以查看别人申请给你的信息,你点击同意的,就直接添加到好友。