✨ feat(ui): 判题结果页新增输出对比视图
- 新增 parse_diff_blocks 系列函数,将 runtimeinfo 解析为结构化的测试点对比块,支持 simple 表格和 diff -y 两种格式 - 在判题结果页插入"输出对比"区块,逐测试点并列展示期望输出与用户输出,差异行高亮 - 补充 diff-section 相关样式,移动端切换为单列布局
This commit is contained in:
@@ -133,6 +133,99 @@ i.icon.spinning {
|
||||
color: #2185d0;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
/* Diff 对比样式 */
|
||||
#diff-section {
|
||||
margin-bottom: 18px;
|
||||
}
|
||||
.diff-card {
|
||||
margin-bottom: 14px;
|
||||
border-left: 4px solid #fbbd08;
|
||||
padding: 12px 16px;
|
||||
}
|
||||
.diff-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
margin-bottom: 10px;
|
||||
padding-bottom: 8px;
|
||||
border-bottom: 1px solid #eee;
|
||||
font-weight: 600;
|
||||
color: #555;
|
||||
}
|
||||
.diff-name {
|
||||
font-family: 'Fira Mono', 'Cascadia Code', Consolas, monospace;
|
||||
font-size: 0.95em;
|
||||
}
|
||||
.diff-table {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 12px;
|
||||
}
|
||||
@media (max-width: 768px) {
|
||||
.diff-table { grid-template-columns: 1fr; }
|
||||
}
|
||||
.diff-side {
|
||||
background: #fafafa;
|
||||
border-radius: 6px;
|
||||
overflow: hidden;
|
||||
border: 1px solid #e0e0e0;
|
||||
}
|
||||
.diff-side-header {
|
||||
padding: 6px 10px;
|
||||
font-size: 0.85em;
|
||||
font-weight: 600;
|
||||
color: #fff;
|
||||
}
|
||||
.diff-expected .diff-side-header {
|
||||
background: #21ba45;
|
||||
}
|
||||
.diff-yours .diff-side-header {
|
||||
background: #db2828;
|
||||
}
|
||||
.diff-content {
|
||||
margin: 0 !important;
|
||||
padding: 8px 0 !important;
|
||||
background: #fff !important;
|
||||
font-family: 'Fira Mono', 'Cascadia Code', Consolas, monospace;
|
||||
font-size: 0.85em;
|
||||
line-height: 1.5;
|
||||
overflow-x: auto;
|
||||
max-height: 400px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
.diff-line {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
padding: 0;
|
||||
white-space: pre;
|
||||
}
|
||||
.diff-line-mismatch {
|
||||
background: rgba(255, 230, 100, 0.25);
|
||||
}
|
||||
.diff-expected .diff-line-mismatch {
|
||||
background: rgba(33, 186, 69, 0.12);
|
||||
}
|
||||
.diff-yours .diff-line-mismatch {
|
||||
background: rgba(219, 40, 40, 0.10);
|
||||
}
|
||||
.diff-lineno {
|
||||
display: inline-block;
|
||||
min-width: 38px;
|
||||
padding: 0 8px;
|
||||
text-align: right;
|
||||
color: #999;
|
||||
background: #f5f5f5;
|
||||
border-right: 1px solid #e8e8e8;
|
||||
user-select: none;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.diff-text {
|
||||
padding: 0 10px;
|
||||
flex: 1;
|
||||
word-break: break-all;
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="padding">
|
||||
@@ -143,6 +236,8 @@ i.icon.spinning {
|
||||
$verdict_memory = isset($row['memory']) ? intval($row['memory']) : 0;
|
||||
$verdict_time = isset($row['time']) ? intval($row['time']) : 0;
|
||||
$verdict_mark = isset($mark) ? $mark : (isset($row['pass_rate']) ? round($row['pass_rate']*100, 1) : 0);
|
||||
// 兜底:防止 PHP notice
|
||||
$diff_blocks = isset($diff_blocks) && is_array($diff_blocks) ? $diff_blocks : array();
|
||||
?>
|
||||
|
||||
<!-- 1. 顶部判题结果横幅 -->
|
||||
@@ -330,6 +425,63 @@ i.icon.spinning {
|
||||
</script>
|
||||
<?php } ?>
|
||||
|
||||
<!-- 3.5. 对比详情(WA/PE 时显示,diff 视图) -->
|
||||
<?php if (!empty($diff_blocks) && is_array($diff_blocks)): ?>
|
||||
<div id="diff-section">
|
||||
<h3 class="ui header" style="margin-top: 0;">
|
||||
<i class="exchange icon"></i>
|
||||
<div class="content">
|
||||
输出对比
|
||||
<div class="sub header">逐测试点对比期望输出和你的输出</div>
|
||||
</div>
|
||||
</h3>
|
||||
<?php foreach ($diff_blocks as $idx => $block): ?>
|
||||
<div class="ui segment diff-card">
|
||||
<div class="diff-header">
|
||||
<i class="file outline icon"></i>
|
||||
<span class="diff-name"><?php echo htmlspecialchars($block['name'], ENT_QUOTES, 'UTF-8'); ?></span>
|
||||
</div>
|
||||
<div class="diff-table">
|
||||
<div class="diff-side diff-expected">
|
||||
<div class="diff-side-header">
|
||||
<i class="check icon"></i> 期望输出
|
||||
</div>
|
||||
<pre class="diff-content"><?php
|
||||
$max = max(count($block['expected']), count($block['yours']));
|
||||
$lines_html = array();
|
||||
for ($li = 0; $li < $max; $li++) {
|
||||
$e = isset($block['expected'][$li]) ? $block['expected'][$li] : '';
|
||||
$y = isset($block['yours'][$li]) ? $block['yours'][$li] : '';
|
||||
$diff_class = ($e !== $y) ? ' diff-line-mismatch' : '';
|
||||
$line_no = $li + 1;
|
||||
$lines_html[] = '<div class="diff-line' . $diff_class . '" data-line="' . $line_no . '"><span class="diff-lineno">' . $line_no . '</span><span class="diff-text">' . htmlspecialchars($e, ENT_QUOTES, 'UTF-8') . '</span></div>';
|
||||
}
|
||||
echo implode('', $lines_html);
|
||||
?></pre>
|
||||
</div>
|
||||
<div class="diff-side diff-yours">
|
||||
<div class="diff-side-header">
|
||||
<i class="bug icon"></i> 你的输出
|
||||
</div>
|
||||
<pre class="diff-content"><?php
|
||||
$max = max(count($block['expected']), count($block['yours']));
|
||||
$lines_html = array();
|
||||
for ($li = 0; $li < $max; $li++) {
|
||||
$e = isset($block['expected'][$li]) ? $block['expected'][$li] : '';
|
||||
$y = isset($block['yours'][$li]) ? $block['yours'][$li] : '';
|
||||
$diff_class = ($e !== $y) ? ' diff-line-mismatch' : '';
|
||||
$line_no = $li + 1;
|
||||
$lines_html[] = '<div class="diff-line' . $diff_class . '" data-line="' . $line_no . '"><span class="diff-lineno">' . $line_no . '</span><span class="diff-text">' . htmlspecialchars($y, ENT_QUOTES, 'UTF-8') . '</span></div>';
|
||||
}
|
||||
echo implode('', $lines_html);
|
||||
?></pre>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<!-- 4. 原始错误折叠(默认收起) -->
|
||||
<div class="ui styled accordion" id="raw-info-accordion">
|
||||
<div class="title">
|
||||
|
||||
Reference in New Issue
Block a user