创新实训(七)系统消息页面 比赛通知
系统消息还有一个功能就接受有关比赛的通知
这一部分的消息生成的代码在contest_inside.php中实现
获取通知信息
执行if判断,检查客户端是否发送了名为 check_notice 的 POST 请求并采取相应操作
if (isset($_POST['check_notice'])) {
$result = DB::query("select * from contests_notice where contest_id = '${contest['id']}' order by time desc limit 10");
$ch = array();
$flag = false;
try {
while ($row = DB::fetch($result)) {
if (new DateTime($row['time']) > new DateTime($_POST['last_time'])) {
$ch[] = $row['title'].': '.$row['content'];
}
}
} catch (Exception $e) {
}
global $myUser;
$result=DB::query("select * from contests_asks where contest_id='${contest['id']}' and username='${myUser['username']}' order by reply_time desc limit 10");
try {
while ($row = DB::fetch($result)) {
if (new DateTime($row['reply_time']) > new DateTime($_POST['last_time'])) {
$ch[] = $row['question'].': '.$row['answer'];
}
}
} catch (Exception $e) {
}
if ($ch) {
die(json_encode(array('msg' => $ch, 'time' => UOJTime::$time_now_str)));
} else {
die(json_encode(array('time' => UOJTime::$time_now_str)));
}
}
详解:
-
查询比赛通知信息:
- 从数据库中查询与特定比赛
contest_id相关的通知信息,按时间降序取前 10 条。 - 使用
new DateTime将数据库中的时间字符串转换为DateTime对象,与客户端传递的last_time比较,以确定是否有新的通知。 - 如果有新通知,则将通知的标题和内容组合成字符串并存入
$ch数组中。
- 从数据库中查询与特定比赛
-
查询用户的问题和回答信息:
- 查询当前用户在该比赛中提交的问题和管理员的回复,同样按时间降序取前 10 条。
- 同样使用
new DateTime比较时间,如果有新的问题或回答,将其组合成字符串并存入$ch数组中。
-
返回 JSON 响应:
- 如果
$ch数组不为空,表示有新的通知或回答,将结果以 JSON 格式返回客户端,包括消息和当前时间。 - 如果
$ch数组为空,则只返回当前时间,表示没有新的通知或回答。
- 如果
超级管理员发送通知部分
这一部分主要在一个if分支中实现,这里只展示实现了发送通知信息的部分。
1.检查是否为超级管理员:
- 使用
isSuperUser($myUser)函数判断当前用户是否是超级管理员。
if (isSuperUser($myUser)) {
2.这个分支的前半部分会通过各种方法计算用户排名和排名变化,并将排名结果通知用户,通知部分的代码如下
// 发送rating变化通知
for ($i = 0; $i < count($standings); $i++) {
$user = queryUser($standings[$i][2][0]);
$change = $ratings[$i] - $user['rating'];
$user_link = getUserLink($user['username']);
if ($change != 0) {
$tail = '<strong style="color:red">' . ($change > 0 ? '+' : '') . $change . '</strong>';
$content = <<<EOD
<p>${user_link} 您好:</p>
<p class="indent2">您在 <a href="/contest/{$contest['id']}">{$contest['name']}</a> 这场比赛后的Rating变化为${tail},当前Rating为 <strong style="color:red">{$ratings[$i]}</strong>。</p>
EOD;
} else {
$content = <<<EOD
<p>${user_link} 您好:</p>
<p class="indent2">您在 <a href="/contest/{$contest['id']}">{$contest['name']}</a> 这场比赛后Rating没有变化。当前Rating为 <strong style="color:red">{$ratings[$i]}</strong>。</p>
EOD;
}
sendSystemMsg($user['username'], 'Rating变化通知', $content);
DB::query("update user_info set rating = {$ratings[$i]} where username = '{$standings[$i][2][0]}'");
DB::query("update contests_registrants set rank = {$standings[$i][3]} where contest_id = {$contest['id']} and username = '{$standings[$i][2][0]}'");
}
DB::query("update contests set status = 'finished' where id = {$contest['id']}");
};
$publish_result_form->submit_button_config['class_str'] = 'btn btn-danger btn-block';
$publish_result_form->submit_button_config['smart_confirm'] = '';
$publish_result_form->submit_button_config['text'] = '公布成绩';
$publish_result_form->runAtServer();
遍历 $standings 数组,对每位参赛者执行以下操作:
使用 queryUser() 函数获取用户信息,包括用户名和当前评分。
计算评分变化 $change,并根据变化情况构建通知内容 $content,包括用户名、比赛链接、评分变化和当前评分。
调用 sendSystemMsg() 函数向用户发送评分变化通知,主题为 'Rating变化通知'。
更新数据库中用户的评分信息和比赛参与者的排名信息。
系统消息页面
下面对系统消息页面的具体前端代码进行介绍,这部分代码的实现在user_system_msg.php文件中实现。
代码解释
-
初始检查和重定向:
- 如果
$myUser是null(表示用户未登录),则调用redirectToLogin()函数将用户重定向到登录页面,确保只有已验证的用户可以访问系统消息。
if ($myUser == null) { redirectToLogin(); } - 如果
-
HTML 表头行:
- 使用 heredoc 语法 (
<<<EOD ... EOD;) 定义 HTML 表格的表头行,用于显示系统消息。
$header_row = <<<EOD <tr> <th>消息</th> <th style="width:15em">时间</th> </tr> EOD; - 使用 heredoc 语法 (
-
输出系统消息的函数:
echoSysMsg($msg)函数用于将每条系统消息输出为表格行 (<tr>)。- 函数检查消息是否已读 (
$msg['read_time'] == null),如果未读,则添加class="warning"来突出显示该行。 - 显示消息标题 (
$msg['title']) 作为<h4>标题和消息内容 ($msg['content'])。 - 显示消息发送时间 (
$msg['send_time'])。
function echoSysMsg($msg) { echo $msg['read_time'] == null ? '<tr class="warning">' : '<tr>'; echo '<td>'; echo '<h4>'.$msg['title'].'</h4>'; echo $msg['content']; echo '</td>'; echo '<td>'.$msg['send_time'].'</td>'; echo '</tr>'; } -
显示页面标题:
- 调用
echoUOJPageHeader('系统消息')输出页面标题为'系统消息'。
<?php echoUOJPageHeader('系统消息') ?> - 调用
-
显示系统消息表格:
- 使用
echoLongTable()函数生成和显示包含系统消息的表格 (user_system_msg)。 - 函数根据当前认证用户 (
Auth::id()) 过滤接收者为该用户的消息。 - 按
id降序排序消息。 - 使用之前定义的
$header_row作为表头行模板。 - 对每一行调用
echoSysMsg函数输出消息详细信息。 - 提供额外选项,如设置表格类 (
'table')。
<?php echoLongTable(array('*'), 'user_system_msg', "receiver='" . Auth::id() . "'", 'order by id desc', $header_row, 'echoSysMsg', array('table_classes' => array('table'))) ?> - 使用
-
标记消息为已读:
- 更新
user_system_msg表,将接收者为当前用户的消息的read_time设置为当前时间 (now()).
<?php DB::update("update user_system_msg set read_time = now() where receiver = '" . Auth::id() . "'") ?> - 更新
-
显示页面页脚:
- 调用
echoUOJPageFooter()输出页面页脚,关闭必要的 HTML 标签。
<?php echoUOJPageFooter() ?> - 调用

浙公网安备 33010602011771号