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 是一个保持最小规模的灵活的 …...
(LeetCode 每日一题) 3442. 奇偶频次间的最大差值 I (哈希、字符串)
题目:3442. 奇偶频次间的最大差值 I 思路 :哈希,时间复杂度0(n)。 用哈希表来记录每个字符串中字符的分布情况,哈希表这里用数组即可实现。 C版本: class Solution { public:int maxDifference(string s) {int a[26]…...
【kafka】Golang实现分布式Masscan任务调度系统
要求: 输出两个程序,一个命令行程序(命令行参数用flag)和一个服务端程序。 命令行程序支持通过命令行参数配置下发IP或IP段、端口、扫描带宽,然后将消息推送到kafka里面。 服务端程序: 从kafka消费者接收…...
日语学习-日语知识点小记-构建基础-JLPT-N4阶段(33):にする
日语学习-日语知识点小记-构建基础-JLPT-N4阶段(33):にする 1、前言(1)情况说明(2)工程师的信仰2、知识点(1) にする1,接续:名词+にする2,接续:疑问词+にする3,(A)は(B)にする。(2)復習:(1)复习句子(2)ために & ように(3)そう(4)にする3、…...
PPT|230页| 制造集团企业供应链端到端的数字化解决方案:从需求到结算的全链路业务闭环构建
制造业采购供应链管理是企业运营的核心环节,供应链协同管理在供应链上下游企业之间建立紧密的合作关系,通过信息共享、资源整合、业务协同等方式,实现供应链的全面管理和优化,提高供应链的效率和透明度,降低供应链的成…...
大语言模型如何处理长文本?常用文本分割技术详解
为什么需要文本分割? 引言:为什么需要文本分割?一、基础文本分割方法1. 按段落分割(Paragraph Splitting)2. 按句子分割(Sentence Splitting)二、高级文本分割策略3. 重叠分割(Sliding Window)4. 递归分割(Recursive Splitting)三、生产级工具推荐5. 使用LangChain的…...
selenium学习实战【Python爬虫】
selenium学习实战【Python爬虫】 文章目录 selenium学习实战【Python爬虫】一、声明二、学习目标三、安装依赖3.1 安装selenium库3.2 安装浏览器驱动3.2.1 查看Edge版本3.2.2 驱动安装 四、代码讲解4.1 配置浏览器4.2 加载更多4.3 寻找内容4.4 完整代码 五、报告文件爬取5.1 提…...
如何理解 IP 数据报中的 TTL?
目录 前言理解 前言 面试灵魂一问:说说对 IP 数据报中 TTL 的理解?我们都知道,IP 数据报由首部和数据两部分组成,首部又分为两部分:固定部分和可变部分,共占 20 字节,而即将讨论的 TTL 就位于首…...
sipsak:SIP瑞士军刀!全参数详细教程!Kali Linux教程!
简介 sipsak 是一个面向会话初始协议 (SIP) 应用程序开发人员和管理员的小型命令行工具。它可以用于对 SIP 应用程序和设备进行一些简单的测试。 sipsak 是一款 SIP 压力和诊断实用程序。它通过 sip-uri 向服务器发送 SIP 请求,并检查收到的响应。它以以下模式之一…...
SiFli 52把Imagie图片,Font字体资源放在指定位置,编译成指定img.bin和font.bin的问题
分区配置 (ptab.json) img 属性介绍: img 属性指定分区存放的 image 名称,指定的 image 名称必须是当前工程生成的 binary 。 如果 binary 有多个文件,则以 proj_name:binary_name 格式指定文件名, proj_name 为工程 名&…...
AGain DB和倍数增益的关系
我在设置一款索尼CMOS芯片时,Again增益0db变化为6DB,画面的变化只有2倍DN的增益,比如10变为20。 这与dB和线性增益的关系以及传感器处理流程有关。以下是具体原因分析: 1. dB与线性增益的换算关系 6dB对应的理论线性增益应为&…...
