user_msg.php 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308
  1. <?php
  2. if ($myUser == null) {
  3. redirectToLogin();
  4. }
  5. function handleMsgPost() {
  6. global $myUser;
  7. if (!isset($_POST['receiver'])) {
  8. return 'fail';
  9. }
  10. if (!isset($_POST['message'])) {
  11. return 'fail';
  12. }
  13. if (0 > strlen($_POST['message']) || strlen($_POST['message']) > 65535) {
  14. return 'fail';
  15. }
  16. $receiver = $_POST['receiver'];
  17. $esc_message = DB::escape($_POST['message']);
  18. $sender = $myUser['username'];
  19. if (!validateUsername($receiver) || !queryUser($receiver)) {
  20. return 'fail';
  21. }
  22. DB::query("insert into user_msg (sender, receiver, message, send_time) values ('$sender', '$receiver', '$esc_message', now())");
  23. return "ok";
  24. }
  25. function getConversations() {
  26. global $myUser;
  27. $username = $myUser['username'];
  28. $result = DB::query( "select * from user_msg where sender = '$username' or receiver = '$username' order by send_time DESC" );
  29. $ret = array();
  30. while ($msg = DB::fetch($result)) {
  31. if ($msg['sender'] !== $username) {
  32. if (isset($ret[$msg['sender']])) {
  33. $ret[$msg['sender']][1] |= ($msg['read_time'] == null);
  34. continue;
  35. }
  36. $ret[$msg['sender']] = array($msg['send_time'], ($msg['read_time'] == null));
  37. } else {
  38. if (isset($ret[$msg['receiver']])) {
  39. continue;
  40. }
  41. $ret[$msg['receiver']] = array($msg['send_time'], 0);
  42. }
  43. }
  44. $res = [];
  45. foreach ($ret as $name => $con) {
  46. $res[] = [$con[0], $con[1], $name];
  47. }
  48. usort($res, function($a, $b) {
  49. return -strcmp($a[0], $b[0]);
  50. });
  51. return json_encode($res);
  52. }
  53. function getHistory() {
  54. global $myUser;
  55. $username = $myUser['username'];
  56. if (!isset($_GET['conversationName']) || !validateUsername($_GET['conversationName'])) {
  57. return '[]';
  58. }
  59. if (!isset($_GET['pageNumber']) || !validateUInt($_GET['pageNumber'])) {
  60. return '[]';
  61. }
  62. $conversationName = $_GET['conversationName'];
  63. $pageNumber = ($_GET['pageNumber'] - 1) * 10;
  64. DB::query("update user_msg set read_time = now() where sender = '$conversationName' and receiver = '$username' and read_time is null");
  65. $result = DB::query("select * from user_msg where (sender = '$username' and receiver = '$conversationName') or (sender = '$conversationName' and receiver = '$username') order by send_time DESC limit $pageNumber, 11");
  66. $ret = array();
  67. while ($msg = DB::fetch($result)) {
  68. $ret[] = array($msg['message'], $msg['send_time'], $msg['read_time'], $msg['id'], ($msg['sender'] == $username));
  69. }
  70. return json_encode($ret);
  71. }
  72. /*
  73. function deleteMsg($msgId) {
  74. return 1;
  75. $str = <<<EOD
  76. select * from user_msg
  77. where id = $msgId
  78. and read_time is null
  79. EOD;
  80. $result = DB::query($str);
  81. if (DB::fetch($result)) {
  82. $str = <<<EOD
  83. delete from user_msg
  84. where id = $msgId
  85. EOD;
  86. DB::query($str);
  87. return 1;
  88. }
  89. return 0;
  90. }
  91. */
  92. if (isset($_POST['user_msg'])) {
  93. crsf_defend();
  94. die(handleMsgPost());
  95. } elseif (isset($_GET['getConversations'])) {
  96. die(getConversations());
  97. } elseif (isset($_GET['getHistory'])) {
  98. die(getHistory());
  99. }
  100. ?>
  101. <?php echoUOJPageHeader('私信') ?>
  102. <h1 class="page-header">私信</h1>
  103. <div id="conversations">
  104. </div>
  105. <div id="history" style="display:none">
  106. <div class="card">
  107. <div class="card-header">
  108. <button type="button" id="goBack" class="btn btn-info btn-sm" style="position:absolute">返回</button>
  109. <div id="conversation-name" class="text-center"></div>
  110. </div>
  111. <div class="card-body">
  112. <ul class="pagination top-buffer-no justify-content-between">
  113. <li class="previous"><a class="btn btn-outline-secondary text-primary" href="#" id="pageLeft">&larr; 更早的消息</a></li>
  114. <li class="text-center" id="pageShow" style="line-height:32px"></li>
  115. <li class="next"><a class="btn btn-outline-secondary text-primary" href="#" id="pageRight">更新的消息 &rarr;</a></li>
  116. </ul>
  117. <div id="history-list" style="min-height: 200px;">
  118. </div>
  119. <ul class="pagination top-buffer-no justify-content-between">
  120. <li class="previous"><a class="btn btn-outline-secondary text-primary" href="#history" id="pageLeft2">&larr; 更早的消息</a></li>
  121. <li class="next"><a class="btn btn-outline-secondary text-primary" href="#history" id="pageRight2">更新的消息 &rarr;</a></li>
  122. </ul>
  123. <hr />
  124. <form id="form-message">
  125. <div class="form-group" id="form-group-message">
  126. <textarea id="input-message" class="form-control"></textarea>
  127. <span id="help-message" class="help-block"></span>
  128. </div>
  129. <div class="text-right">
  130. <button type="submit" id="message-submit" class="btn btn-info btn-md">发送</button>
  131. </div>
  132. </form>
  133. </div>
  134. </div>
  135. </div>
  136. <script type="text/javascript">
  137. $(document).ready(function() {
  138. $.ajaxSetup({async:false});
  139. refreshConversations();
  140. <?php if (isset($_GET['enter'])): ?>
  141. enterConversation(<?= json_encode($_GET['enter']) ?>);
  142. <?php endif ?>
  143. });
  144. </script>
  145. <script type="text/javascript">
  146. function addButton(conversationName, send_time, type) {
  147. $("#conversations").append(
  148. '<div class="row top-buffer-sm">' +
  149. '<div class="col-sm-3">' +
  150. '<button type="button" class="btn btn-' + ( type ? 'warning' : 'primary' ) + ' btn-block" ' +
  151. 'onclick="enterConversation(\'' + conversationName + '\')">' +
  152. conversationName +
  153. '</button>' +
  154. '</div>' +
  155. '<div class="col-sm-9" style="line-height:34px">' +
  156. '最后发送时间:' + send_time +
  157. '</div>' +
  158. '</div>'
  159. );
  160. }
  161. function addBubble(content, send_time, read_time, msgId, conversation, page, type) {
  162. $("#history-list").append(
  163. '<div style=' + (type ? "margin-left:40%;margin-right:0%;" : "margin-left:0%;margin-right:40%;") + '>' +
  164. '<div class="card mb-4">' +
  165. '<div class="card-body" style="background:' + (type ? '#4d92d8' : '#beb7b7') + '; word-break: break-all">' +
  166. '<div style="white-space:pre-wrap" ' + (type ? 'class="text-right"' : 'class="text-left"') + '>' +
  167. htmlspecialchars(content) +
  168. '</div>' +
  169. '</div>' +
  170. '<div>' +
  171. '<div class="row">' +
  172. '<div class="col-sm-6">' +
  173. '发送时间:' + send_time +
  174. '</div>' +
  175. '<div class="col-sm-6 text-right">' +
  176. '查看时间:' + (read_time == null ? '<strong>未查看</strong>' : read_time) +
  177. '</div>' +
  178. '</div>' +
  179. '</div>' +
  180. '</div>' +
  181. '</div>'
  182. );
  183. }
  184. function submitMessagePost(conversationName) {
  185. if ($('#input-message').val().length == 0 || $('#input-message').val().length >= 65536) {
  186. $('#help-message').text('私信长度必须在1~65535之间。');
  187. $('#form-group-message').addClass('has-error');
  188. return;
  189. }
  190. $('#help-message').text('');
  191. $('#form-group-message').removeClass('has-error');
  192. $.post('/user/msg', {
  193. user_msg : 1,
  194. receiver : conversationName,
  195. message : $('#input-message').val(),
  196. _token : uojCsrfToken
  197. }, function(msg) {
  198. $('#input-message').val("");
  199. });
  200. }
  201. function refreshHistory(conversation, page) {
  202. $("#history-list").empty();
  203. var ret = false;
  204. $('#conversation-name').text(conversation);
  205. $('#pageShow').text("第" + page.toString() + "页");
  206. $.get('/user/msg', {
  207. getHistory : '',
  208. conversationName : conversation,
  209. pageNumber : page
  210. }, function(msg) {
  211. var result = JSON.parse(msg);
  212. var cnt = 0, flag = 0, F = 0;
  213. if (result.length == 11) flag = 1, F = 1;
  214. result.reverse();
  215. for (msg in result) {
  216. if (flag) {flag = 0; continue;}
  217. var message = result[msg];
  218. addBubble(message[0], message[1], message[2], message[3], conversation, page, message[4]);
  219. if ((++cnt) + 1 == result.length && F) break;
  220. }
  221. if (result.length == 11) ret = true;
  222. });
  223. return ret;
  224. }
  225. function refreshConversations() {
  226. $("#conversations").empty();
  227. $.get('/user/msg', {
  228. getConversations : ""
  229. }, function(msg) {
  230. var result = JSON.parse(msg);
  231. for (i in result) {
  232. var conversation = result[i];
  233. if (conversation[1] == 1) {
  234. addButton(conversation[2], conversation[0], conversation[1]);
  235. }
  236. }
  237. for (i in result) {
  238. var conversation = result[i];
  239. if (conversation[1] == 0) {
  240. addButton(conversation[2], conversation[0], conversation[1]);
  241. }
  242. }
  243. }
  244. );
  245. }
  246. function enterConversation(conversationName) {
  247. var slideTime = 300;
  248. var page = 1;
  249. $("#conversations").hide(slideTime);
  250. var changeAble = refreshHistory(conversationName, page);
  251. $("#history").slideDown(slideTime);
  252. $('#form-message').unbind("submit").submit(function() {
  253. submitMessagePost(conversationName);
  254. page = 1;
  255. changeAble = refreshHistory(conversationName, page);
  256. refreshConversations();
  257. return false;
  258. });
  259. $('#goBack').unbind("click").click(function() {
  260. refreshConversations();
  261. $("#history").slideUp(slideTime);
  262. $("#conversations").show(slideTime);
  263. return;
  264. });
  265. $('#pageLeft').unbind("click").click(function() {
  266. if (changeAble) page++;
  267. changeAble = refreshHistory(conversationName, page);
  268. return false;
  269. });
  270. $('#pageLeft2').unbind("click").click(function() {
  271. if (changeAble) page++;
  272. changeAble = refreshHistory(conversationName, page);
  273. });
  274. $('#pageRight').unbind("click").click(function() {
  275. if (page > 1) page--;
  276. changeAble = refreshHistory(conversationName, page);
  277. return false;
  278. });
  279. $('#pageRight2').unbind("click").click(function() {
  280. if (page > 1) page--;
  281. changeAble = refreshHistory(conversationName, page);
  282. });
  283. }
  284. </script>
  285. <?php echoUOJPageFooter() ?>