功能描述
1、类似CSDN论坛 右上角的消息通知 如果有新消息 整个页面不刷新 右上角的消息数字即时+1
2、类似于论坛评论区 ,发布评论之后,不刷新页面就可以立刻看到自己的评论
(2020-5-3更新)最终解决方案:使用Vue绑定评论区数据,v-for生成ul li标签,提交评论后,用axios(ajax)同步数据,就能实现只刷新评论区。
新浪微博的评论区实现方式
观察了一下新浪微博的评论区实现,从下面的图可以看出,因为时间固定显示为10秒前,因此可以推断:
点击“评论”之后,评论框的 div 只是在本地 append 的,而不是去刷新整个评论区(除非你去手动刷新整个页面)。可以参考这个思路
web 页面的解决方案
网上提供的 n 多种实现方式,可以参考一下思路:
1)通过ajax定时提交刷新,不知道你是全部刷新还是通过ajax的方式提交刷新,理论上如果通和AJAX刷新的话应是可以的。
2)使用html5的websocket功能。
3)思路:在获取页面的时候,分配session然后去做定阅通知,编辑完了之后发消息给定阅的频道,再更新
4)用 jira
5) 这个地方基本上都是采用的轮训吧,只有一些实时性非常高的才会选择使用WebSocket 另外还有一种采用消息中间件的方式
6)signalr 应该是可以的
winform 的解决方案
winform就比较好实现了,用委托或者订阅吧
附:(障眼法)本地追加div的思路及示例
效果:点击“写评论”后,下方追加一个富文本编辑框(使用WangEditor)div。
目前点击保存按钮后的的刷新方式是使用window.location.reload();
刷新整个页面,此时浏览器拖动条还会默认保持在原来的位置,所以用户体验还好。
若想要实现在本地追加新评论div
,可以参照下方 js 代码的 CommentNode(...)
函数。
HTML
引入 CSS JS
<link href="/static/bootstrap/css/bootstrap.min.css" rel="stylesheet">
<link rel="stylesheet" type="text/css" href="/static/js/easyui/themes/icon.css">
<script src="/static/js/jquery-2.1.1.min.js"></script>
<script src="/static/bootstrap/js/bootstrap.min.js"></script>
<script src="/static/js/echarts-4.2.1.js" charset="UTF-8"></script>
<link rel="stylesheet" type="text/css" href="/static/css/editorStyle.css"><!--自定义CSS-->
<script type="text/javascript" src="/static/js/jquery.form.min.js"></script>
<script type="text/javascript" src="/static/js/wangEditor.min.js"></script>
<script src="/static/js/paramconvert.js" charset="UTF-8"></script><!--自定义JS-->
<script src="/static/js/editorUtils.js" charset="UTF-8"></script><!--自定义JS-->
Body 核心代码
<!--评论区begin-->
<h4 style="display: inline">简评</h4>
<button type="button"
style="position:absolute;right: 68px"
onclick="javascript:appendHtml('others-comment-area',new WangEditorNode('{{p_code}}', 'others','{{ query_date }}'))"
class="btn btn-primary btn-sm">写评论
</button>
<!-- List group -->
<ul id="others-comment-area" class="list-group" style="padding-top: 10px">
{% for node in others_list %}
<li class="list-group-item">
<div class="username" style="display: inline">用户:{{ node.user }}</div>
<p>{{ node.update_time }}</p>
<div class="btn-group btn-group-sm" role="group">
<button type="button" onclick="javascript:appendHtml('others-comment-area',new WangEditorModifyNode('{{ p_code }}','others','{{ node.rich_text }}',{{ node.id }}))"
class="btn btn-warning">修改
</button>
<button type="button" onclick="javascript:deleteEditor({{ node.id }})"
class="btn btn-danger">删除
</button>
</div>
{{ node.rich_text |safe }}
</li>
{% endfor %}
</ul>
<!--评论区end-->
editorUtils.js
手动拼接 HTML,感觉回到了 Servlet 时代
多亏 PyCharm 在粘贴的时候会自动转义符号,不然自己拼左斜线和双引号肯定被绕晕…
function appendHtml(div_id, node) {
delAllEditorNode();//先删除旧的wangEditor
// $('#future-spot-comment-area').append(new CommentNode('testuser', '2020-4-21 22:03:33', 'rich_text', 55).getNodeHtml());
$('#' + div_id).append(node.getNodeHtml());
// $('#future-spot-comment-area').append(new WangEditorNode('RB.SHF', 'cost').getNodeHtml());
var E = window.wangEditor;
var editor = new E('#div1', '#div2');
editor.customConfig.uploadImgShowBase64 = true; // 使用 base64 保存图片
var $textplace = $('#textplace');
editor.customConfig.onchange = function (html) {
$textplace.val(html)// 监控变化,同步更新到 textarea
};
editor.create();
$textplace.val(editor.txt.html());// 初始化 textarea 的值
// wait for the DOM to be loaded
$(document).ready(function () {
// bind 'myForm' and provide a simple callback function
$('#editor_form').ajaxForm(function (message) {
var messageJson = JSON.parse(message);
if (messageJson.status == '0') {
alert("保存成功!");
window.location.reload();
} else {
alert("保存失败,请联系管理员!" + message);
}
});
});
}
function CommentNode(user, update_time, rich_text, id) {
this.user = user;
this.update_time = update_time;
this.rich_text = rich_text;
this.id = id;
this.nodeHtml = "";
this.getNodeHtml = function () {
this.nodeHtml += "<li class=\"list-group-item\">";
this.nodeHtml += "<div class=\"username\" style=\"display: inline\">用户:";
this.nodeHtml += user;
this.nodeHtml += "</div>";
this.nodeHtml += "<p>";
this.nodeHtml += update_time;
this.nodeHtml += "</p>";
this.nodeHtml += "<div class=\"btn-group btn-group-sm\" role=\"group\">";
this.nodeHtml += "<button type=\"button\" οnclick=\"javascript:modifyEditor(";
this.nodeHtml += id;
this.nodeHtml += ")\" class=\"btn btn-warning\">修改</button>";
this.nodeHtml += "<button type=\"button\" οnclick=\"javascript:deleteEditor(";
this.nodeHtml += ")\" class=\"btn btn-danger\">删除</button>";
this.nodeHtml += "</div>";
this.nodeHtml += rich_text;
this.nodeHtml += "</li>";
return this.nodeHtml;
}
}
function WangEditorNode(p_code, attribute, query_date) {
this.nodeHtml="";
this.getNodeHtml = function () {
this.nodeHtml += "<div class=\"editor-node\">";
this.nodeHtml += "<div id=\"div1\" class=\"toolbar\"></div>";
this.nodeHtml += "<div id=\"div2\" class=\"text\"></div>";
this.nodeHtml += "<form id=\"editor_form\" action=\"/api/editor\" method=\"post\">";
this.nodeHtml += "<textarea id=\"textplace\" name=\"textplace\" style=\"display: none\"></textarea>";
this.nodeHtml += "<input type=\"hidden\" name=\"p_code\" value=\"";
this.nodeHtml += p_code;
this.nodeHtml += "\"/>";
this.nodeHtml += "<input type=\"hidden\" name=\"attribute\" value=\"";
this.nodeHtml += attribute;
this.nodeHtml += "\"/>";
this.nodeHtml += "<input type=\"hidden\" name=\"query_date\" value=\"";
this.nodeHtml += query_date;
this.nodeHtml += "\"/>";
this.nodeHtml += "<input type=\"submit\" value=\"保存\">";
this.nodeHtml += "</form>";
this.nodeHtml += "</div>";
return this.nodeHtml;
}
}
function WangEditorModifyNode(p_code, attribute, rich_text, id) {
this.nodeHtml="";
this.getNodeHtml = function () {
this.nodeHtml += "<div class=\"editor-node\">";
this.nodeHtml += "<div id=\"div1\" class=\"toolbar\"></div>";
this.nodeHtml += "<div id=\"div2\" class=\"text\">";
this.nodeHtml += rich_text;
this.nodeHtml += "</div>";
this.nodeHtml += "<form id=\"editor_form\" action=\"/api/editor/update?id=";
this.nodeHtml += id;
this.nodeHtml += "\" method=\"post\">";
this.nodeHtml += "<textarea id=\"textplace\" name=\"textplace\" style=\"display: none\"></textarea>";
this.nodeHtml += "<input type=\"hidden\" name=\"p_code\" value=\"";
this.nodeHtml += p_code;
this.nodeHtml += "\"/>";
this.nodeHtml += "<input type=\"hidden\" name=\"attribute\" value=\"";
this.nodeHtml += attribute;
this.nodeHtml += "\"/>";
this.nodeHtml += "<input type=\"submit\" value=\"保存\">";
this.nodeHtml += "</form>";
this.nodeHtml += "</div>";
return this.nodeHtml;
}
}
function delAllEditorNode() {
$(".editor-node").remove();
}
function deleteEditor(id) {
console.log("删除, id = " + id);
$.ajax({
url: "/api/editor/" + id,
type: "delete",
processData: false,
contentType: false,
success: function (data) {
alert("删除成功!如误删除,可联系管理员恢复。");
window.location.reload();
},
error: function (data) {
alert("删除失败" + data);
}
})
}
function modifyEditor(id) {
console.log("修改, id = " + id);
window.open('/api/editor/' + id, '_blank');
}