P6. 对局列表和排行榜功能
P6. 对局列表和排行榜功能
- 0 概述
- 1 对局列表功能
- 1.1 分页配置
- 1.2 后端按页获取对局列表接口
- 1.3 前端展示传回来的对局列表
- 1.4 录像回放功能
- 1.4.1 录像回放的流程
- 1.4.2 录像回放的实现
- 1.5 前端分页展示
- 2 排行榜功能
- 2.1 排行榜的实现
0 概述
- 本节主要介绍了如何实现对局列表和排行榜,对局列表包含对局录像的回放的实现,最重要的是掌握怎么写分页功能。
1 对局列表功能
1.1 分页配置
由于对局数量很多,不可能放在同一页上展示,因此要实现分页功能。后端的 Mybatis 分页配置:
MybatisConfig:
@Configuration
public class MybatisConfig {@Beanpublic MybatisPlusInterceptor mybatisPlusInterceptor() {MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));return interceptor;}
}
1.2 后端按页获取对局列表接口
service.impl
需要传入参数
page,表示当前要获取的是哪一页的列表。
通过 MyBatis 提供的 API 来实现分页查询的功能,查询的页面按最新对局顺序排列。
@Override
public JSONObject getRecordList(Integer page) {IPage<Record> recordIPage = new Page<>(page, 8); // 每页展示8条QueryWrapper<Record> queryWrapper = new QueryWrapper<>();queryWrapper.orderByDesc("id");List<Record> records = recordMapper.selectPage(recordIPage, queryWrapper).getRecords();List<JSONObject> items = new ArrayList<>();for (Record record : records) {JSONObject item = new JSONObject();User userA = userMapper.selectById(record.getAId());User userB = userMapper.selectById(record.getBId());item.put("a_photo", userA.getPhoto());item.put("a_username", userA.getUsername());item.put("b_photo", userB.getPhoto());item.put("b_username", userB.getUsername());item.put("record", record);String result = "Draw";if ("A".equals(record.getLoser())) result = "B Win";else if ("B".equals(record.getLoser())) result = "A Win";item.put("result", result);items.add(item);}JSONObject resp = new JSONObject();resp.put("records", items);resp.put("records_count", recordMapper.selectCount(null));return resp;
}
1.3 前端展示传回来的对局列表
写一个表格来展示每个对局的信息,先获取一页的信息进行调试:
<template><ContentField><table class="table table-striped table-hover" style="text-align: center;"><thead><tr><th>A</th><th>B</th><th>对战结果</th><th>对战时间</th><th>操作</th></tr></thead><tbody><tr v-for="record in records" :key="record.record.id"><td>s<img :src="record.a_photo" alt="" class="record-user-photo"> <span class="record-user-username">{{ record.a_username }}</span></td><td><img :src="record.b_photo" alt="" class="record-user-photo"> <span class="record-user-username">{{ record.b_username }}</span></td><td>{{ record.result }}</td><td>{{ record.record.createtime }}</td><td><button type="button" class="btn btn-secondary">查看录像</button></td></tr></tbody></table></ContentField>
</template><script>
import ContentField from '../../components/ContentField.vue'
import { useStore } from 'vuex';
import { ref } from 'vue';
import $ from 'jquery';export default {components: {ContentField},setup() {const store = useStore();let records = ref([]);let current_page = 1;let total_records = 0;console.log(total_records);const pull_page = page => {current_page = page;$.ajax({url: "http://127.0.0.1:3000/record/getlist/",data: {page,},type: "get",headers: {Authorization: "Bearer " + store.state.user.token,},success(resp) {records.value = resp.records;total_records = resp.records_count;},error(resp) {console.log(resp);}})}pull_page(current_page);return {records,}}
}
</script><style scoped>
img.record-user-photo {width: 4vh;border-radius: 50%;
}
</style>
1.4 录像回放功能
1.4.1 录像回放的流程
首先要明确录像回放需要哪些参数,将这些参数从后端获取后保存在前端。之后要明确前端在哪展示录像,以及如何展示录像。
- 后端传来的参数已在
1.2节中说明,并且前端保存在records数组中,records中的每个record.record包含了录像的具体信息,包括地图、双方玩家的操作信息、败者等。 - 前端需要开一个全局变量
record.js进行保存,并且决定在PlayGround中进行录像回放,因此需要一个变量记录当前是在pk还是在播放record。另外,它们共用的GameMap.js也需要根据是record还是pk进行相应的判断,如果是pk那就是前几节实现的,如果是record则要播放录像。
1.4.2 录像回放的实现
-
首先在前端
record.js记录全局变量,在点击"播放录像"按钮之后,应该将对应录像的信息保存到Game, Record,并且跳转到新的页面播放对应录像,因此需要添加对应的路由(路由中带上对应录像的id):path: '/record/:recordId/', name: 'record_content', component: RecordContentView, meta: {requestAuth: true, }const open_record_content = recordId => {for (const record of records.value) {if (record.record.id === recordId) {store.commit("updateIsRecord", true);store.commit("updateGame", {map: stringTo2D(record.record.map),a_id: record.record.aid,a_sx: record.record.asx,a_sy: record.record.asy,b_id: record.record.bid,b_sx: record.record.bsx,b_sy: record.record.bsy,});store.commit("updateSteps", {a_steps: record.record.asteps,b_steps: record.record.bsteps,});store.commit("updateRecordLoser", record.record.loser);router.push({name: "record_content",params: {recordId}})break;}} } -
在
GameMap.js中实现录像回放:add_listening_events() {if (this.store.state.record.is_record) {let k = 0;const a_steps = this.store.state.record.a_steps;const b_steps = this.store.state.record.b_steps;const loser = this.store.state.record.record_loser;const [snake0, snake1] = this.snakes;const interval_id = setInterval(() => {if (k >= a_steps.length - 1) {if (loser === "all" || loser === "A") {snake0.status = "die";}if (loser === "all" || loser === "B") {snake1.status = "die";}clearInterval(interval_id);} else {snake0.set_direction(parseInt(a_steps[k]));snake1.set_direction(parseInt(b_steps[k]));}k ++ ;}, 300);} else {/* pk页面的操作 */} }
1.5 前端分页展示
分页要满足以下几点:
(1) 当前页高亮,并且返回当前页的对局列表。
(2) 展示前面2页和后面2页的信息,如果页数不存在就不展示。
(3) 点击对应编号之后会跳转到对应的页面。
<template><ContentField><nav aria-label="..."><ul class="pagination" style="float: right;"><li class="page-item" @click="click_page(-2)"><a class="page-link" href="#">前一页</a></li><li :class="'page-item ' + page.is_active" v-for="page in pages" :key="page.number" @click="click_page(page.number)"><a class="page-link" href="#">{{ page.number }}</a></li><li class="page-item" @click="click_page(-1)"><a class="page-link" href="#">后一页</a></li></ul></nav></ContentField>
</template><script>
export default {setup() {let current_page = 1;let total_records = 0;let pages = ref([]); // pages 记录当前要展示的所有页面const click_page = page => {if (page === -2) page = current_page - 1;else if (page === -1) page = current_page + 1;let max_pages = parseInt(Math.ceil(total_records / 8));if (page >= 1 && page <= max_pages) {pull_page(page);}}const udpate_pages = () => {let max_pages = parseInt(Math.ceil(total_records / 8)); // 除的是每页展示多少个录像let new_pages = [];for (let i = current_page - 2; i <= current_page + 2; i ++ ) {if (i >= 1 && i <= max_pages) {new_pages.push({number: i,is_active: i === current_page ? "active" : "",});}}pages.value = new_pages;}/* 每次 pull_page 之后都要记得 update_pages */return {pages,click_page}}
}
</script>
2 排行榜功能
2.1 排行榜的实现
排行榜相对就简单多得多了,和对局列表功能相同,就是查出来用户列表,再在前端展示即可(前端和上面的差不多,不赘述了)。
@Override
public JSONObject getRanklist(Integer page) {IPage<User> userIPage = new Page<>(page, 8);QueryWrapper<User> queryWrapper = new QueryWrapper<>();queryWrapper.orderByDesc("rating");List<User> users = userMapper.selectPage(userIPage, queryWrapper).getRecords();JSONObject resp = new JSONObject();for (User user : users) user.setPassword(""); // 记得传回去之前要把密码清空resp.put("users", users);resp.put("users_count", userMapper.selectCount(null));return resp;
}
相关文章:
P6. 对局列表和排行榜功能
P6. 对局列表和排行榜功能 0 概述1 对局列表功能1.1 分页配置1.2 后端按页获取对局列表接口1.3 前端展示传回来的对局列表1.4 录像回放功能1.4.1 录像回放的流程1.4.2 录像回放的实现 1.5 前端分页展示 2 排行榜功能2.1 排行榜的实现 0 概述 本节主要介绍了如何实现对局列表和…...
uniapp easycom组件冲突
提示信息 easycom组件冲突:[/components/uni-icons/uni-icons.vue,/uni_modules/uni-icons/components/uni-icons/uni-icons.vue] 问题描述 老项目,在uniapp插件商城导入了一个新的uniapp官方开发的组件》uni-data-picker 数据驱动的picker选择器 …...
总结24个Python接单赚钱平台与详细教程,兼职月入5000+
如果说当下什么编程语言最靠谱或者比较适合搞副业? 答案肯定100%是:Python。 python是所有语法中最简单易上手的语言,不需要特别的的英语词汇量,逻辑思维也不需要很差就能上手。而且学会了之后就能编写代码爬取各种数据…...
macOS 的电源适配器设置
在 macOS 的电源适配器设置中,有四个选项,每个选项都有特定的功能: Prevent your Mac from automatically sleeping when the display is off(当显示屏关闭时,防止你的 Mac 自动进入睡眠状态):…...
视觉SLAM与定位之一前端特征点及匹配
视觉SLAM中的特征点及匹配 参考文章或链接特征点性能的评估传统特征点和描述子(仅特征点或者特征点描述子)传统描述子 基于深度学习的特征点基于深度学习的描述子基于深度学习的特征点描述子特征匹配 参考文章或链接 Image Matching from Handcrafted t…...
开源项目的认识理解
目录 开源项目有哪些机遇与挑战? 1.开源项目的发展趋势 2.开源的经验分享(向大佬请教与上网查询) 3.开源项目的挑战 开源项目有哪些机遇与挑战? 1.开源项目的发展趋势 1. 持续增长与普及 - 开源项目将继续增长,…...
37.哀家要长脑子了!--层序遍历
gongmi层序遍历模板 vector<vector<int>> levelOrder(TreeNode *root){queue<TreeNode*> que;vector<vector<int>> res;if(root ! nullptr)que.push(root);while(!que.empty()){int size que.size();vector<int> storey;for(int i 0; i …...
【从零开始AI绘画6】StableDiffusionWebUI拓展的安装方法以及推荐的几个拓展
这里写自定义目录标题 拓展Extention安装方法(以双语对照插件为例)1、WebUI内置的下载方式(推荐)2、git clone安装(更推荐)3、github下载安装包后解压(不推荐) 强力推荐安装的几个插…...
HTML5表单的自动验证、取消验证、自定义错误信息
1、自动验证 通过在元素中使用属性的方法,该属性可以实现在表单提交时执行自动验证的功能。下面是关于对元素内输入内容进行限制的属性的指定。 属性说明required输入内容是否不为空pattern输入的内容是否符合指定格式min、max输入的数值是否在min~max范围step判断…...
SpringMVC系列九: 数据格式化与验证及国际化
SpringMVC 数据格式化基本介绍基本数据类型和字符串自动转换应用实例-页面演示方式Postman完成测试 特殊数据类型和字符串自动转换应用实例-页面演示方式Postman完成测试 验证及国际化概述应用实例代码实现注意事项和使用细节 注解的结合使用先看一个问题解决问题 数据类型转换…...
判断链表中是否有环(力扣141.环形链表)
这道题要用到快慢指针。 先解释一下什么是快慢指针。 快慢指针有两个指针,走得慢的是慢指针,走得快的是快指针。 在这道题,我们规定慢指针一次走一步,快指针一次走2步。 如果该链表有环,快慢指针最终会在环中相遇&a…...
Kubernetes基于helm部署jenkins
Kubernetes基于helm安装jenkins jenkins支持war包、docker镜像、系统安装包、helm安装等。在Kubernetes上使用Helm安装Jenkins可以简化安装和管理Jenkins的过程。同时借助Kubernetes,jenkins可以实现工作节点的动态调用伸缩,更好的提高资源利用率。通过…...
【Linux】vim详解
1.什么是vi/vim? 简单来说,vi是老式的文本编辑器,不过功能已经很齐全了,但是还是有可以进步的地方。vim则可以说是程序开发者的一项很好用的工具,就连 vim的官方网站( http://www.vim.org)自己也说vim是一…...
Android11 mtk 第二次设置壁纸,锁屏壁纸不变的问题
1、情景:近日测试人员发现第一次更换壁纸后,主屏幕壁纸和锁屏壁纸均会改变;但第二次更换壁纸后,主屏幕壁纸会改变而锁屏壁纸不会改变。 2、要求:主屏幕壁纸和锁屏壁纸军改变 3、解决 路径:****\frameworks\base\services\core\java\com\android\server\wallpaper\Wallp…...
Java学习路线
目录 友情提醒第一章、Java基础1.1)第一部分:Java 入门1.2)第二部分:Java数组1.3)第三部分:Java面向对象1.4)第四部分:常用工具类1.5)第五部分:集合体系1.6&a…...
java 实现人脸检测
1. 安装必要的库 确保你已经安装了JPEG库、BLAS和LAPACK库。在Ubuntu或Debian系统上,可以使用以下命令安装: sudo apt-get update sudo apt-get install libjpeg-dev libblas-dev liblapack-dev 在CentOS或Fedora系统上,可以使用以下命令安…...
VSCode神仙插件——Codeium (AI编程助手)
1、安装&登录插件 安装过程中会让你登录Codeium账户,可以通过Google账户登录,或者可以注册一个Codeium账户(如果没有弹出让你登录账户的界面,可以等安装结束后在右下角找到登录的地方) 右下角显示如下图所示&#…...
css文本划线效果(text-decoration相关属性详解)
/* 样式类型*/text-decoration: underline;/* 下划线颜色 */text-decoration-color: #ffcb15;/* 超出基线的字符不会被截断 */text-decoration-skip-ink: none;/*下划线厚度 */text-decoration-thickness: 5px;/* 与其原始位置的偏移距离 */text-underline-offset: 0;1. text-u…...
《Windows API每日一练》8.5 listbox控件
列表框是将一批文本字符串显示在一个具有滚动功能的方框中的控件。通过发送消息到列表框的窗口过程,程序可以添加或删除列表中的字符串。当列表框中的一个项目被选中时,列表框控件便发送 WM_COMMAND消息到其父窗口。然后父窗口确定哪个项目被选中。 本节…...
使用Node.js 框架( Express.js)来创建一个简单的 API 端点
文章目录 使用Node.js 框架( Express.js)来创建一个简单的 API 端点什么是express安装修改代码 express 自动刷新 使用Node.js 框架( Express.js)来创建一个简单的 API 端点 什么是express Express 是一个保持最小规模的灵活的 …...
Spring Boot+Neo4j知识图谱实战:3步搭建智能关系网络!
一、引言 在数据驱动的背景下,知识图谱凭借其高效的信息组织能力,正逐步成为各行业应用的关键技术。本文聚焦 Spring Boot与Neo4j图数据库的技术结合,探讨知识图谱开发的实现细节,帮助读者掌握该技术栈在实际项目中的落地方法。 …...
深度学习习题2
1.如果增加神经网络的宽度,精确度会增加到一个特定阈值后,便开始降低。造成这一现象的可能原因是什么? A、即使增加卷积核的数量,只有少部分的核会被用作预测 B、当卷积核数量增加时,神经网络的预测能力会降低 C、当卷…...
20个超级好用的 CSS 动画库
分享 20 个最佳 CSS 动画库。 它们中的大多数将生成纯 CSS 代码,而不需要任何外部库。 1.Animate.css 一个开箱即用型的跨浏览器动画库,可供你在项目中使用。 2.Magic Animations CSS3 一组简单的动画,可以包含在你的网页或应用项目中。 3.An…...
三分算法与DeepSeek辅助证明是单峰函数
前置 单峰函数有唯一的最大值,最大值左侧的数值严格单调递增,最大值右侧的数值严格单调递减。 单谷函数有唯一的最小值,最小值左侧的数值严格单调递减,最小值右侧的数值严格单调递增。 三分的本质 三分和二分一样都是通过不断缩…...
基于Java+VUE+MariaDB实现(Web)仿小米商城
仿小米商城 环境安装 nodejs maven JDK11 运行 mvn clean install -DskipTestscd adminmvn spring-boot:runcd ../webmvn spring-boot:runcd ../xiaomi-store-admin-vuenpm installnpm run servecd ../xiaomi-store-vuenpm installnpm run serve 注意:运行前…...
【从零开始学习JVM | 第四篇】类加载器和双亲委派机制(高频面试题)
前言: 双亲委派机制对于面试这块来说非常重要,在实际开发中也是经常遇见需要打破双亲委派的需求,今天我们一起来探索一下什么是双亲委派机制,在此之前我们先介绍一下类的加载器。 目录 编辑 前言: 类加载器 1. …...
如何配置一个sql server使得其它用户可以通过excel odbc获取数据
要让其他用户通过 Excel 使用 ODBC 连接到 SQL Server 获取数据,你需要完成以下配置步骤: ✅ 一、在 SQL Server 端配置(服务器设置) 1. 启用 TCP/IP 协议 打开 “SQL Server 配置管理器”。导航到:SQL Server 网络配…...
xmind转换为markdown
文章目录 解锁思维导图新姿势:将XMind转为结构化Markdown 一、认识Xmind结构二、核心转换流程详解1.解压XMind文件(ZIP处理)2.解析JSON数据结构3:递归转换树形结构4:Markdown层级生成逻辑 三、完整代码 解锁思维导图新…...
32单片机——基本定时器
STM32F103有众多的定时器,其中包括2个基本定时器(TIM6和TIM7)、4个通用定时器(TIM2~TIM5)、2个高级控制定时器(TIM1和TIM8),这些定时器彼此完全独立,不共享任何资源 1、定…...
数据结构第5章:树和二叉树完全指南(自整理详细图文笔记)
名人说:莫道桑榆晚,为霞尚满天。——刘禹锡(刘梦得,诗豪) 原创笔记:Code_流苏(CSDN)(一个喜欢古诗词和编程的Coder😊) 上一篇:《数据结构第4章 数组和广义表》…...
