工作记录(五):竞赛模块前端逻辑实现以及页面实现,包括竞赛主页和竞赛答题页
本次开发聚焦于竞赛模块的主要页面与核心交互逻辑,包括比赛列表、比赛进行、比赛结果等功能。通过细致的状态管理、动画设计和数据可视化,提升了整体用户体验和系统可维护性。
一、ContestsView.vue 比赛列表页面
1. 页面状态管理
比赛列表页面采用Vue 3的响应式系统,通过ref定义dataList和total来存储比赛数据和总数。searchParams对象用于管理搜索条件和分页信息,便于灵活地处理数据加载和展示。页面加载时会根据这些参数自动请求数据并更新视图。
为了让比赛时长更直观,定义了makeHoursMinutes函数,将比赛时长(秒)转换为“小时分钟”格式。该函数会先计算小时数,再判断是否有剩余分钟,最终拼接成友好的字符串,便于用户快速理解比赛持续时间。
let hours = Math.floor(duration / 3600);
let minutes = Math.floor((duration % 3600) / 60);
return hours ? `${hours}小时${minutes ? " " + minutes + "分" : ""}` : `${minutes}分`;
}
2. 比赛状态判断
比赛状态判断通过比较当前时间与比赛的开始/结束时间,动态决定比赛的可操作性。isBegin函数会判断当前时间是否晚于比赛开始时间,isEnd函数会判断当前时间是否晚于比赛结束时间。这些状态用于控制用户可执行的操作,比如未开始的比赛不能进入答题,已结束的比赛只能查看结果,保证了操作的准确性和安全性。
function isBegin(record) {
// 当前时间大于开始时间则比赛已开始
}
function isEnd(record) {
// 当前时间大于等于结束时间则比赛已结束
}
3. 奖杯与动画效果
奖杯区域采用了多种CSS动画提升视觉体验。文字动画通过关键帧实现上下浮动和缩放,配合渐变色背景和文字裁剪,营造出活泼的氛围。彩带使用SVG路径和旋转动画,左右对称地摆动,增强了节日感。奖杯本身结合了上下浮动、缩放和左右摇摆,配合阴影和变换原点,整体更具立体感和动感。这些动画通过CSS的@keyframes和transform属性实现,提升了页面的趣味性和吸引力。
@keyframes textFloat { /* 文字上下浮动和缩放 */ }
@keyframes waveLeft { /* 左彩带左右摇摆 */ }
@keyframes waveRight { /* 右彩带左右摇摆 */ }
@keyframes trophyAnimation { /* 奖杯上下浮动和旋转 */ }

二、DoContestView.vue 比赛进行页面
1. 比赛状态管理
比赛进行页需要管理多种状态,包括当前比赛信息、题目列表、剩余时间、比赛结果、通过题目统计以及代码提交表单。所有状态均采用ref响应式管理,确保页面数据和交互的实时同步。这样可以在比赛过程中动态更新题目、剩余时间和用户提交的代码,保证了比赛流程的流畅性。
2. 倒计时系统实现
倒计时系统通过与后端服务协作,支持获取剩余时间和启动新的倒计时。比赛开始时会自动调用后端接口获取剩余时间,如果没有则主动启动倒计时并设置初始值。前端会定时刷新剩余时间,确保用户始终看到准确的倒计时信息。时间结束后,系统会自动提交试卷,保证比赛的公平性和准确性。
async function getRemainingTime(duration) {
// 先尝试从后端获取剩余时间
const res = await 后端获取剩余时间();
if (res成功) {
剩余时间 = res.data;
} else {
// 获取不到则通知后端启动倒计时,并本地设置初始值
await 启动后端倒计时(duration);
剩余时间 = duration;
}
}
async function startCountDown(duration) {
// 通知后端启动倒计时
await 后端启动倒计时(duration);
}
3. 代码提交与评判
用户提交代码后,系统会将代码和题目ID发送到后端评判服务。提交成功后,前端会自动刷新比赛结果和题目通过情况,并根据评判结果给予用户即时反馈(如题目变绿色、弹窗提示等)。整个流程保证了评判的及时性和用户体验,用户可以清楚地知道自己的提交是否通过。
// 反馈信息
message.success("运行完成,代码正确");
message.error("运行错误,代码或者算法存在问题,请仔细检查");
message.error("运行失败,可能是服务器缘故,请联系工作人员" + res.message);

三、ContestResultView.vue 比赛结果页面
1. 排名与奖励
比赛结果页通过计算每个选手的排名,并根据排名动态分配积分奖励。前三名有特殊的积分和样式,前十名有额外激励,其他参赛者也能获得基础积分。getRank函数根据当前分页和行号计算实际排名,getReword函数根据排名分配不同的积分奖励,getRankClass函数为不同排名提供独特的样式类名,配合CSS实现了醒目的视觉效果,对前三名选手的特殊样式处理。
function getRankClass(rowIndex) {
// 返回不同排名的样式
const rank = getRank(rowIndex);
if (rank === 1) return 'rank-first';
if (rank === 2) return 'rank-second';
if (rank === 3) return 'rank-third';
return '';
}
2. 成绩展示组件
每个选手的每道题成绩以卡片形式展示,包含分数和耗时。getQuestionScore和getQuestionConsume函数分别获取题目的得分和耗时信息。特别设计了perfect-score样式类,当选手获得满分时会触发特殊的视觉效果。时间消耗的显示帮助评估解题效率,为同分情况下的排名提供参考依据。
function getQuestionScore(record, column) {
// 通过列信息确定题目索引,然后返回该题目的分数
题目索引 = 由column信息推算得到
return record.题目分数列表[题目索引]?.score
}
function getQuestionConsume(record, column) {
// 通过列信息确定题目索引,然后返回该题目的耗时
题目索引 = 由column信息推算得到
return record.题目分数列表[题目索引]?.consume
}

四、总结
本次开发实现了竞赛模块的主要页面和核心交互逻辑。通过响应式状态管理、前后端协同的倒计时与评判流程、丰富的动画效果和数据可视化,极大提升了系统的易用性和美观度。在实践中,我进一步掌握了复杂页面状态的组织方法、动画与交互的性能优化技巧,以及数据驱动的可视化设计思路,为后续功能扩展和用户体验提升打下了坚实基础。
12万+

被折叠的 条评论
为什么被折叠?



