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 是一个保持最小规模的灵活的 …...
微信小程序之bind和catch
这两个呢,都是绑定事件用的,具体使用有些小区别。 官方文档: 事件冒泡处理不同 bind:绑定的事件会向上冒泡,即触发当前组件的事件后,还会继续触发父组件的相同事件。例如,有一个子视图绑定了b…...
基于FPGA的PID算法学习———实现PID比例控制算法
基于FPGA的PID算法学习 前言一、PID算法分析二、PID仿真分析1. PID代码2.PI代码3.P代码4.顶层5.测试文件6.仿真波形 总结 前言 学习内容:参考网站: PID算法控制 PID即:Proportional(比例)、Integral(积分&…...
DeepSeek 赋能智慧能源:微电网优化调度的智能革新路径
目录 一、智慧能源微电网优化调度概述1.1 智慧能源微电网概念1.2 优化调度的重要性1.3 目前面临的挑战 二、DeepSeek 技术探秘2.1 DeepSeek 技术原理2.2 DeepSeek 独特优势2.3 DeepSeek 在 AI 领域地位 三、DeepSeek 在微电网优化调度中的应用剖析3.1 数据处理与分析3.2 预测与…...
家政维修平台实战20:权限设计
目录 1 获取工人信息2 搭建工人入口3 权限判断总结 目前我们已经搭建好了基础的用户体系,主要是分成几个表,用户表我们是记录用户的基础信息,包括手机、昵称、头像。而工人和员工各有各的表。那么就有一个问题,不同的角色…...
Ascend NPU上适配Step-Audio模型
1 概述 1.1 简述 Step-Audio 是业界首个集语音理解与生成控制一体化的产品级开源实时语音对话系统,支持多语言对话(如 中文,英文,日语),语音情感(如 开心,悲伤)&#x…...
pikachu靶场通关笔记22-1 SQL注入05-1-insert注入(报错法)
目录 一、SQL注入 二、insert注入 三、报错型注入 四、updatexml函数 五、源码审计 六、insert渗透实战 1、渗透准备 2、获取数据库名database 3、获取表名table 4、获取列名column 5、获取字段 本系列为通过《pikachu靶场通关笔记》的SQL注入关卡(共10关࿰…...
Map相关知识
数据结构 二叉树 二叉树,顾名思义,每个节点最多有两个“叉”,也就是两个子节点,分别是左子 节点和右子节点。不过,二叉树并不要求每个节点都有两个子节点,有的节点只 有左子节点,有的节点只有…...
Android 之 kotlin 语言学习笔记三(Kotlin-Java 互操作)
参考官方文档:https://developer.android.google.cn/kotlin/interop?hlzh-cn 一、Java(供 Kotlin 使用) 1、不得使用硬关键字 不要使用 Kotlin 的任何硬关键字作为方法的名称 或字段。允许使用 Kotlin 的软关键字、修饰符关键字和特殊标识…...
ip子接口配置及删除
配置永久生效的子接口,2个IP 都可以登录你这一台服务器。重启不失效。 永久的 [应用] vi /etc/sysconfig/network-scripts/ifcfg-eth0修改文件内内容 TYPE"Ethernet" BOOTPROTO"none" NAME"eth0" DEVICE"eth0" ONBOOT&q…...
微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据
微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据 Power Query 具有大量专门帮助您清理和准备数据以供分析的功能。 您将了解如何简化复杂模型、更改数据类型、重命名对象和透视数据。 您还将了解如何分析列,以便知晓哪些列包含有价值的数据,…...
