这部分的代码实现均在 backend 端。
天梯积分更新
随着对战的结束,要相应的更新用户的天梯积分

更新代码如下:

对局列表
后端 API
首先实现一个 API,从后端返回一个对局列表的 List。实现 API,需要依次编写 service, service.impl, controller。
由于对局列表可能很长,需要添加分页功能。
在config.MybatisConfig
中添加分页配置:
1 2 3 4 5 6 7 8 9
| @Configuration public class MybatisConfig { @Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL)); return interceptor; } }
|
在service.record
中创建GetRecordListService
不需要将所有页面的信息均返回出来,用户需要展示第几页,就对应的返回第几页。
1 2 3
| public interface GetRecordListService { JSONObject getList (Integer page); }
|
在service.impl.record
中创建GetRecordListServiceImpl
假定每页展示 10 条信息,所以如果 page = 1,返回 09 条;page = 2,返回 1019 条
直接借助 mabatisplus 中的工具 IPage 实现即可。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| @Service public class GetRecordListServiceImpl implements GetRecordListService { @Autowired private RecordMapper recordMapper; @Autowired private UserMapper userMapper; @Override public JSONObject getList(Integer page) { IPage<Record> recordIPage = new Page<>(page, 10); QueryWrapper<Record> queryWrapper = new QueryWrapper<>(); queryWrapper.orderByDesc("id"); List<Record> records = recordMapper.selectPage(recordIPage, queryWrapper).getRecords(); JSONObject resp = new JSONObject(); List<JSONObject> items = new LinkedList<>(); for(Record record : records){ User userA = userMapper.selectById(record.getAId()); User userB = userMapper.selectById(record.getBId()); JSONObject item = new JSONObject(); item.put("a_photo", userA.getPhoto()); item.put("a_username", userA.getUsername()); item.put("b_photo", userB.getPhoto()); item.put("b_username", userB.getUsername()); String result = "平局"; if("A".equals(record.getLoser())) result = "B胜"; else if("B".equals(record.getLoser())) result = "A胜"; item.put("result", result); item.put("record", record); items.add(item); } resp.put("records", items); resp.put("records_count", recordMapper.selectCount(null));
return resp; } }
|
在controller.record
中创建GetRecordListController
1 2 3 4 5 6 7 8 9 10 11
| @RestController public class GetRecordListController { @Autowired private GetRecordListService getRecordListService;
@GetMapping("/record/getlist/") private JSONObject getList (@RequestParam Map<String, String> data){ Integer page = Integer.parseInt(data.get("page")); return getRecordListService.getList(page); } }
|
前端展示
获取列表
在RecordIndexView.vue
中,请求获取对局记录。

测试如下:
与后端返回的格式一致,结果分两大部分 records 和 records_count

其中 records.records 又包括

接下来要将列表显示出来。
需要建立一个 tabel,遍历 records 将内容展示出来

效果如下:
查看录像
为了方便展示录像,需要存储一些全局信息,包括是否展示录像,以及 a 和 b 的 steps
record.js

同时,点击查看录像,需要进入一个新的页面,建立一个新的 vue 页面src\views\record\RecordContentView.vue
由于录像页面,和 PK 页面实际上大部分内容相同,因此,直接将 PK 页面的内容复制过来加以修改。‘
这里只需要用到PlayGround
这一个组件,初始化为。

并将这样一个页面,加入路由
注意,路由中,path
可以加入参数,这里recordId
就是传入的参数
1 2 3 4 5 6 7 8 9 10
| import RecordContentView from '../views/record/RecordContentView.vue' const routes = [ { path:"/record/:recordId", name:"record_content", component:RecordContentView, meta:{ requestAuth:true, } ]
|
回到src\views\record\RecordIndexView.vue
点击查看录像按钮时,触发open_record_content
,并且传入记录的 ID

在open_record_content
函数中,需要通过updateIsrecord
来标记为录像页面;
同时注意,在对战页面的 vue 页面中,取消标记

在open_record_content
函数中同时调用updateGame
,对游戏进行更新,调用updateSteps
,更新a_step
和b_step
,调用updateRecordLoser
,更新record_loser

同时需要在 Gamemap.js 中添加一些逻辑判断。
因为不管是对战页面,还是录像页面,都共用了PlayGround
组件
对于PlayGround
组件,由GameMap
组件构成

在 GameMap 中要创建 GameMap 类的实例

因此,不管是对战页面还是录像页面,都需要GameMap.js
中执行相应的逻辑
这里需要在GameMap.js
中判断是录像是否被标记,如果没有标记,就依然是之前对战的逻辑。
操作回放
如果录像被标记,也就是this.store.state.record.is_record
为 true。
录像本质上是操作的回放,只需要根据两名玩家的 steps,重新将蛇移动一遍。

这样,就实现了对局录像的展示。
分页展示
借助 Bootstrap 的 Pagination 组件

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| <nav aria-label="..."> <ul class="pagination"> <li class="page-item disabled"> <span class="page-link">Previous</span> </li> <li class="page-item"><a class="page-link" href="#">1</a></li> <li class="page-item active" aria-current="page"> <span class="page-link">2</span> </li> <li class="page-item"><a class="page-link" href="#">3</a></li> <li class="page-item"> <a class="page-link" href="#">Next</a> </li> </ul> </nav>
|
加入到 vue 页面中去,效果如下:


被active
标记的数字变蓝
我们的需求是,展示当前页,并且在分页栏中留出前后两页。



此时结果符合预期

并且,还需要点击哪个按钮,就要跳转到对应的页面。



分页功能成功实现!
排行榜
后端 API



前端展示
在对局页面src\views\record\RecordIndexView.vue
逻辑一致,因此,代码复用率很高
主要就是将 records 和 total_records 改为 users 和 total_users,修改非常少量的代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110
| <template> <ContentFieldVue> <table class="table table-striped table-hover" style="text-align:center"> <thead> <tr> <th>玩家</th> <th>天梯积分</th> </tr> </thead> <tbody> <tr v-for="user in users" :key="user.id"> <td> <img :src="user.photo" alt="" class="ranklist-user-photo"> <span class="ranklist-user-username"> </span> </td> <td> </td> </tr> </tbody> </table> <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.pageId" @click="click_page(page.pageId)"> <a class="page-link" href="#"></a> </li> <li class="page-item" @click="click_page(-1)"> <a class="page-link" href="#">后一页</a> </li> </ul> </nav> </ContentFieldVue> </template> <script> import ContentFieldVue from '../../components/ContentField.vue' import { useStore } from 'vuex'; import $ from 'jquery' import { ref } from 'vue'; export default { components: { ContentFieldVue }, setup() { const store = useStore(); let current_page = 1; let users = ref([]); let total_users = 0; let pages = ref([]); const click_page = page => { if(page === -2) page = current_page - 1; if(page === -1) page = current_page + 1; let max_pages = parseInt(Math.ceil(total_users / 3)); if(page >= 1 && page <= max_pages){ pull_page(page);//加载一个新的分页 } } const update_pages = () =>{ let max_pages = parseInt(Math.ceil(total_users / 3));//最大页数 let new_pages = []; for(let i = current_page - 2; i <= current_page + 2; i++){ if(i >= 1 && i <= max_pages){ new_pages.push({ pageId:i, is_active:i === current_page ? "active" : "" }); } } pages.value = new_pages; }
const pull_page = page => { current_page = page; $.ajax({ url: "http://127.0.0.1:3000/ranklist/getlist/", data: { page, }, type: "get", headers: { Authorization: "Bearer " + store.state.user.token, }, success(resp) { console.log(resp); users.value = resp.users; total_users = resp.user_count; update_pages(); }, error(resp) { console.log(resp); } }) } pull_page(current_page);
return { users, total_users, pages, click_page } } } </script>
|
此时就可以实现
