工作记录(七)——评测以及排行榜前端

工作记录(7):评测和排行榜的前端的逻辑实现以及页面实现

一、页面和逻辑主要技术实现

 1. QuestionSubmitView.vue

搜索表单实现

这部分实现了一个灵活的搜索界面,允许用户按题号和编程语言进行筛选。使用了 Arco Design 的表单组件,实现了双向数据绑定。当用户输入或选择时,searchParams 会自动更新,触发数据重新加载。这种设计既保证了用户操作的实时响应,又避免了频繁的后端请求。表单布局采用 inline 样式,使界面更加紧凑美观。

<!-- 搜索表单,内联布局 -->
<form>
  <!-- 题号输入框 -->
  <input v-model="searchParams.questionId" placeholder="请输入题号" />

  <!-- 编程语言下拉选择 -->
  <select v-model="searchParams.language">
    <option>java</option>
    <option>cpp</option>
    <option>python</option>
  </select>
</form>
统计卡片实现

统计卡片部分展示了提交记录的核心指标:总提交数、通过数和通过率。这些数据通过实时计算得出,而不是直接存储,确保了数据的实时性和准确性。通过率的计算考虑了除零情况,确保了显示的稳定性。卡片采用了现代化的设计风格,使用阴影和渐变效果提升视觉体验。

//除零问题
const getAcceptRate = () => {
  if (total.value === 0) return 0;
  return Math.round((getAcceptedCount() / total.value)  100);
};
提交记录表格

表格实现了提交记录的详细展示,包括提交号、编程语言、判题结果等信息。使用自定义插槽来处理不同状态的显示样式,通过状态显示绿色,错误状态显示红色等。同时实现了时间的格式化显示,提升了数据的可读性。表格支持分页,优化了大数据量的展示性能。

 2. RankAcceptedView.vue

排行榜表格实现

这个组件实现了通过题目数量的排行榜功能。表格的实现考虑了分页加载和排名计算的问题。排名序号是基于当前页码和每页条数动态计算的,确保了排名的连续性和准确性。

  • 如果接口返回成功,则将数据列表赋值到本地变量。
  • 遍历每条数据,根据当前页码和每页数量,计算出全局排名序号(index),用于表格展示。
if (res.code === 0) {
  // 更新数据列表
  dataList = res.data.records;

  // 为每条数据计算排名序号
  for (每一条数据 i in dataList) {
    dataList[i].index = (当前页码 - 1) * 每页数量 + (i + 1);
  }
}

 3. RanksPointsView.vue

积分排行实现

积分排行榜的实现与通过题目排行榜类似,但关注点转向了用户积分。这个组件复用了大量 RankAcceptedView 的逻辑,但针对积分排序进行了优化。这种设计既保证了代码的复用性,又维持了功能的独立性。

  • 通过接口请求用户列表数据。
  • 请求参数包含当前的搜索条件和分页信息。
  • 结果按照“积分”字段从高到低排序,便于展示积分排名。
async function loadData() {
  // 调用后端接口,传入当前的搜索和分页参数
  // 并指定按积分字段降序排序
  res = 请求用户列表({
    ...搜索参数,
    排序字段: "points",
    排序方式: "descend"
  });
}

 4. RanksView.vue

布局结构实现

整体页面采用了现代化的布局设计,使用 flex 布局实现左侧边栏和主内容区的响应式布局。左侧边栏固定宽度,主内容区自适应,这种设计在各种屏幕尺寸下都能保持良好的显示效果。

<div class="content-layout">
  <div class="winners-sidebar">
    <!-- 前三名展示卡片 -->
  </div>
  <div class="main-content">
    <!-- 排行榜标签页 -->
  </div>
</div>
动画效果实现

为提升用户体验,实现了丰富的动画效果。包括卡片的滑入动画、悬浮效果等,这些动画都经过性能优化,使用 CSS transform 和 opacity 属性。

@keyframes slideIn {
  from {
    opacity: 0;
    transform: translateX(-20px);
  }
  to {    opacity: 1;

    transform: translateX(0);
  }
}

二、技术难点和解决方案

1.数据同步问题

  • 难点:子组件(RankAcceptedView/RanksPointsView)与父组件(RanksView)的数据同步
  • 解决方案:使用 emit 事件(update:winners)实现子组件向父组件传递前三名数据,只有在第一页时,才会取出当前数据列表的前三名。只提取每个用户的用户名和通过题数。用事件机制将前三名信息传递给父组件,便于父组件展示获奖信息等。
if (当前页码 === 1) {
  // 取出前三名用户的信息
  topThree = dataList.slice(0, 3).map(user => ({
    userName: user.userName,
    acceptedNum: user.acceptedNum
  }));

  // 通过事件将前三名数据传递给父组件
  emit('update:winners', topThree);
}

2.form 表单与searchParams连结 

表单数据与搜索参数的双向绑定机制,包括

数据绑定

   <a-form :model="searchParams" layout="inline">

  • 表单通过 v-model 与 searchParams 对象进行双向绑定
  • 当表单输入改变时,searchParams 自动更新

响应式更新

   const searchParams = ref<UserQueryRequest>({

     pageSize: 6,

     current: 1,

   });

  • searchParams 作为响应式数据
  • 当 searchParams 变化时,触发 watchEffect 重新加载数据

搜索触发机制

   watchEffect(() => {

     loadData();

   });

  • 监听 searchParams 变化
  • 自动触发数据重新加载

这种设计模式实现表单输入与搜索参数的实时同步,搜索条件变化时的自动数据刷新,减少了手动同步数据的代码,提高了代码可维护性。

三、总结

完成了评测记录页面与排行榜页面的前端逻辑和页面实现。评测页面实现灵活搜索表单、动态统计卡片及带状态标识的提交记录表格;排行榜页面构建通过题目数和积分双维度排行系统。在这个过程中解决了子组件与父组件的数据同步问题,通过事件机制传递前三名数据,实现表单与搜索参数的双向绑定与响应式更新。我i学习到了 Vue 3 中组件通信的事件机制应用,掌握了复杂表格数据的动态排名计算方法,对前端的理解更近一步。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值