SYZOJ前端改版实战:从Vue技术栈到用户体验全面升级
发布时间:2026/9/9 11:05:25 锦皓数字建站

简介ZHZXOJ-Web 是一套基于 SYZOJ 前端改版的在线评测系统OJ前端项目主要由 JavaScript 编写适合 Web 前端开发者、OJ 二次开发爱好者参考。虽然作者已停止维护但代码中保留了前端页面结构与 Nginx 启用 HTTPS 的配置片段可作为搭建或改造评测系统时的备查素材。包内共 524 个文件压缩包约 12.48MB。其中 211 个 js、105 个 css 和 49 个 ejs 覆盖交互逻辑、样式布局与模板渲染另有 ts、json、svg 及多种字体文件支撑前端工程化构建与图标字体显示整体结构清晰便于按需查看核心模块。已有 209 人浏览学习。对想快速了解 SYZOJ 前端结构、或准备在 OJ 前台上做二次开发的读者可直接从这套代码中提取 Nginx 配置思路与前端页面设计节省从零搭建环境与排查 HTTPS 问题的精力。 接手ZHZXOJ-Web之前我对SYZOJ这个开源在线评测系统Online Judge并不陌生——高校ACM集训队、算法训练营、课程实验平台里到处能看到它的身影。但说实话SYZOJ默认前端给我最直观的感受是“功能齐全但视觉和交互还停留在工具型阶段”尤其是题目列表、提交记录和个人中心这几个高频页面在2025年的Web环境下已经有点跟不上用户预期了。ZHZXOJ-Web这个项目做的就是基于SYZOJ前端的系统性改版不动后端评测核心只把前端体验彻底重做一遍。这篇文章就把我改版过程中的完整思路、实操细节、踩坑记录都整理出来给准备做OJ二次开发或者接手SYZOJ、HustOJ这类开源项目前端的朋友一个可参考的路线图。1. 改版前先看清楚底子SYZOJ前端架构拆解1.1 核心依赖与技术栈动手改版之前我花了两天时间把SYZOJ的源码仓库完整过了一遍尤其是前端目录。这里要强调一点做二次开发最忌讳上来就改你得先摸清项目底子是什么、为什么这样设计后面改起来才不会踩雷。SYZOJ的前端是典型的Vue中后台技术栈我这边拉到的版本核心依赖大概是这样的依赖版本区间负责什么Vue2.6.x基础框架组件化开发Vue Router3.x前端路由控制页面跳转Vuex3.x全局状态管理存用户信息、题目列表缓存等Element UI2.15.x桌面端组件库表格、弹窗、表单就靠它axios0.21.xHTTP请求和后端API通信CodeMirror5.x代码编辑器支持多语言语法高亮marked / katex对应版本题目描述Markdown渲染 数学公式解析这个组合在当年的开源OJ生态里非常典型选择它的理由也很务实Vue 2 Element UI 能快速搭出后台管理系统风格的界面组件覆盖度高社区资料多学校实验室或者个人开发者接手成本低。代价就是视觉风格偏“中后台”默认的蓝白主题、表格密度、弹窗交互和现在流行的极简主义技术社区风确实有差距——这正是我们改版的核心切入点。1.2 目录结构与前端数据流SYZOJ前端的目录结构是标准的Vue CLI工程布局这里我列一个精简版src/ ├── api/ // 所有后端接口封装按模块拆文件 ├── router/ // 路由配置含动态路由逻辑 ├── store/ // Vuex模块处理用户态、评测状态等 ├── views/ // 页面组件登录、题目、提交记录、管理后台 ├── components/ // 公共组件如Markdown渲染、代码编辑器封装 └── utils/ // 工具函数axios封装、token操作等理解这个项目的数据流比记住目录结构更重要。整个OJ前端的数据流其实是一条线用户登录后拿到tokenaxios请求拦截器给每个请求带Authorization头后端返回题目列表、题解、排行、提交记录用户提交代码后前端提交一次POST /api/submission拿到 submission id然后通过轮询接口查状态直到评测完成。整个链路不复杂但改版过程中涉及到的权限控制、状态刷新、接口字段适配全都围绕这条线展开。2. 改版整体设计改什么、不改什么、先后顺序定清楚2.1 改版目标与风格定位拿到项目我做的第一件事不是写代码而是拉了一份需求清单把“必须改”“可以改”“坚决不动”三部分分开。必须改的是用户感知最强的地方首页布局、题目列表展示形态、代码编辑器配色、提交结果反馈动效。这些直接决定用户打开网站的第一印象。可以改的是暗色模式、移动端适配、管理后台的表格密度调整。坚决不动的是后端接口字段、登录鉴权逻辑、评测状态机——前两者动了就要和后端联调返工评测状态机更是OJ的命脉前端只能展示不能改变定义。风格定位上我选择了偏“极简技术社区”的路线主色调从SYZOJ默认的深蓝改成冷静的中性深灰品牌点缀色卡片化布局代替传统的通栏表格留白加大字体用系统默认字体栈保证不管在什么设备上打开都干净利落。2.2 功能模块优先级划分改版范围确认后我把所有改动项排了个优先级核心原则是先保证“能正常用”再追求“用得爽”。优先级模块改动内容P0登录/注册、路由权限保持逻辑不变只更新UI样式和校验反馈P0题目列表与题目详情重构列表为卡片/列表双形态Markdown渲染升级P0评测流程提交按钮、等待动画、结果状态展示重做P1个人中心与提交历史新增统计卡片优化长列表展示P1排行榜表格视觉瘦身新增按题目/按通过数筛选P2暗色模式、移动端响应式全站CSS变量化适配小屏我个人强烈建议排序时把“评测流程”放在很高的优先级OJ的本质是“提交流程顺畅”如果用户写完代码点提交后按钮状态、等待反馈、结果展示任何一个环节体验拉胯前端做得再好看也没有用。这个思路适用于所有类似工具型产品的改版。3. 核心模块改版实操从登录到评测全链路3.1 登录态与权限路由改造SYZOJ的权限模型分普通用户、管理员、超级管理员三层路由配置里用meta.role标注了每个页面的可见权限。改版时我保留了这套模型但把路由守卫的逻辑重写得更健壮。先看下改造后的核心逻辑我用的是Vue Router的beforeEach守卫加动态路由注册的组合拳// src/router/index.js 核心片段 const whiteList [/login, /register, /problem/list, /home] router.beforeEach((to, from, next) { const token store.getters.token if (token) { if (to.path /login) { next({ path: / }) } else if (store.getters.roles.length 0) { // 刷新页面时用户信息丢失先拉取再放行 store.dispatch(fetchUserInfo).then(() { store.dispatch(generateRoutes).then(accessRoutes { router.addRoutes(accessRoutes) next({ ...to, replace: true }) }) }).catch(() { store.dispatch(logout) next(/login?redirect${to.path}) }) } else { next() } } else { if (whiteList.includes(to.path)) next() else next(/login?redirect${to.path}) } })这里最关键也最容易踩坑的是“刷新页面后路由丢失”。因为动态路由是登录后addRoutes挂上去的F5一刷新Vuex状态清空动态路由就没了直接跳404。解决办法就是上面代码里注释那一行刷新后先调fetchUserInfo根据角色重新生成路由再放行。这个方案我实测稳定但要注意generateRoutes必须返回Promise否则then里拿不到路由数组。3.2 题目列表与Markdown渲染优化题目列表页是OJ流量最大的页面之一。SYZOJ默认是传统表格视图每一行一个题目字段是编号、标题、通过率、难度。对于体验要求高的站点这种形态太素了。我的做法是提供“表格/卡片”双视图切换默认展示卡片视图每张卡片突出题目标题右上角标注难度色块入门绿色、提高橙色、困难红色下方展示通过率进度条和提交人数。切换按钮放在页面右上角用localStorage记忆用户偏好下次进来还是上次的视图。题目详情的Markdown渲染是另一个重点。SYZOJ的题面包含大量公式、图表和代码块默认渲染方案是marked katex但直接v-html输出存在两个问题XSS注入风险、代码高亮缺失。我的渲染管线长这样import { marked } from marked import hljs from highlight.js import katex from katex import DOMPurify from dompurify function renderMarkdown(md) { // 先处理公式块避免marked把$符号当普通文本 let html md.replace(/\$\$([\s\S]?)\$\$/g, (match, tex) { return katex.renderToString(tex, { throwOnError: false, displayMode: true }) }) // 再用marked渲染开启代码高亮 html marked.parse(html, { highlight: code hljs.highlightAuto(code).value }) // 最后统一过白名单过滤 return DOMPurify.sanitize(html) }顺序很重要先处理公式再转Markdown最后sanitize——如果颠倒过来katex.renderToString生成的HTML会被Markdown解析器二次转义公式直接乱掉。DOMPurify这一步绝对不能省OJ题面里有大量用户生成内容不过滤等于给XSS开大门。3.3 代码编辑器与评测流程对接SYZOJ默认用CodeMirror 5我保留了它——CodeMirror 6虽然新但迁移成本高而且5的生态对OJ场景覆盖得很完整。你要做的不是换编辑器而是把交互体验做细。编辑器改造重点有三个第一语言模式自动切换。题目详情接口会返回languages字段用户选题号后直接根据默认语言创建编辑器实例。CodeMirror的mode需要映射表const langToMode { cpp: text/x-csrc, c: text/x-csrc, java: text/x-java, python: text/x-python, javascript: text/javascript }第二快捷键提交流程。我绑定了Ctrl/Cmd Enter直接提交代码并且在提交前做二次确认弹窗。这个弹窗看起来是小事实际上对防止手误点错题号提交帮助巨大。第三提交后的状态轮询。这个是OJ前端的灵魂。提交成功后前端开始以1秒为间隔轮询评测结果接口比对状态码映射成中文提示const statusMap { 0: 等待评测, 1: 正在编译, 2: 编译失败, 3: 运行中, 4: 通过 (AC), 5: 答案错误 (WA), 6: 时间超限 (TLE), 7: 内存超限 (MLE), 8: 运行时错误 (RE), 9: 系统错误 }轮询不能无限跑我加了一个30次的上限大约30秒超过后提示用户刷新查看结果。实际评测快的题两三秒就出结果30秒足够覆盖绝大多数情况而且避免了极端情况下的请求堆积。4. 暗色模式、性能优化与加餐功能4.1 全站CSS变量化与暗色模式P2级别的暗色模式我放在了基础功能稳定之后做。SYZOJ原版大量使用Element UI默认主题色直接写死成#409EFF想支持暗色模式必须先把颜色抽成CSP变量。做法是在全局样式文件里定义一套语义化变量:root { --app-bg: #f5f6fa; --card-bg: #ffffff; --text-primary: #2c3e50; --text-secondary: #7f8c9b; --border-color: #e4e7ed; --accent-color: #3861fb; } [data-themedark] { --app-bg: #1e1f22; --card-bg: #2b2d31; --text-primary: #e0e0e0; --text-secondary: #9aa0aa; --border-color: #4b4d52; --accent-color: #6c8cff; }Element UI 的主题变量通过element-variables.scss覆盖切换暗色模式时给document.documentElement设置>devServer: { proxy: { /api: { target: http://localhost:3000, changeOrigin: true, pathRewrite: { ^/api: } } } }难的是之前有人直接在前端代码里写死了后端地址导致生产环境也走代理逻辑上线后接口全挂。改版时我统一改成读取环境变量VUE_APP_API_BASE彻底解决这个问题。第二个坑是Markdown渲染的XSS漏洞。原版代码直接v-html渲染用户提交的题解我测试的时候用一段包含img onerroralert(1)的题解直接弹窗了。这个在高危漏洞里属于典型存储型XSS如果OJ被写恶意题解的人盯上所有浏览题解的用户都可能中招。DOMPurify是必须上的而且要在渲染管线的最后一步调用。第三个坑是轮询接口的请求堆积。用户连续提交多次代码时如果每次提交都开一个独立的轮询定时器页面一卡定时器全挤在一起发请求接口压力直接翻倍。我的解法是全局只保留一个轮询队列新的提交进来先取消旧的定时器确保同一时刻最多只有一个活跃轮询循环。写在最后的实际体会ZHZXOJ-Web这个项目做下来最大的感触是开源项目二次开发真正难的不是写代码而是克制——知道哪些地方该大改哪些地方该保持原样。SYZOJ的评测逻辑、权限模型、接口设计是多年积累沉淀下来的轻易改动只会给自己挖坑。前端改版的价值恰恰在于不改逻辑也能让一个老系统的体验焕然一新。如果你正准备改版一个类似的开源项目我的建议是先把接口文档和权限模型啃透再谈视觉升级——地基稳了上面怎么装修都行。另外就是暗色模式和移动端适配尽量提前规划不要等页面全写完了再回头补成本完全不是一个量级。本文还有配套的精品资源点击获取
锦
锦皓数字建站
深耕本土企业品牌数字化升级,专注原创端正雅致商务官网,从视觉设计到稳定运维全程保驾护航。