微服务的编程测评系统19-我的消息功能-竞赛排名功能

发布于:2025-09-03 ⋅ 阅读:(20) ⋅ 点赞:(0)

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

1. 我的消息功能

1.1 业务分析

在这里插入图片描述
这个是站内通信

我的消息功能

站内信:网站内部的一种通信方式。
1.用户和用户之间的通信。(点对点)
2.管理员/系统 和 某个用户之间的通信。(点对点) ===》竞赛结果的通信消息
3. 管理员/系统 和 某个用户群(指的是满足某一条件的用户的群体)之间的通信。(点对面)

而且每个用户的消息都不一样
这个是给用户群发消息,福利信息每个用户的消息都一样—》点对面
因为每个用户消息不一样—》点对点

消息的话我们还要设计数据库

因为如果是消息群的话,那么就会把相同的消息发给多个人,所以我们可以设计两个表,一个消息内容表,一个是消息和用户的对应表,这样就不会相同消息发给多个人了

消息内容表
create table tb_message_text(
text_id  bigint unsigned NOT NULL COMMENT '消息内容id(主键)',
message_title varchar(10)  NOT NULL COMMENT '消息标题',
message_content varchar(200)  NOT NULL COMMENT '消息内容',
create_by    bigint unsigned not null  comment '创建人',
create_time  datetime not null comment '创建时间',
update_by    bigint unsigned  comment '更新人',
update_time  datetime comment '更新时间',
primary key (text_id)
)
# 消息表
create table tb_message(
message_id  bigint unsigned NOT NULL COMMENT '消息id(主键)',
text_id  bigint unsigned NOT NULL COMMENT '消息内容id(主键)',
send_id  bigint unsigned NOT NULL COMMENT '消息发送人id',
rec_id  bigint unsigned NOT NULL COMMENT '消息接收人id',
create_by    bigint unsigned not null  comment '创建人',
create_time  datetime not null comment '创建时间',
update_by    bigint unsigned  comment '更新人',
update_time  datetime comment '更新时间',
primary key (message_id)
);

消息如何产生—》竞赛结果通知消息–》凌晨统计排名,对当天结束的竞赛进行排名的统计—》产生消息—》竞赛结束时间不能超过晚上十点—>把消息存在数据库中,然后查询就可以了
然后消息也要存在redis中,不然还是太慢了
在这里插入图片描述
一个是user:message:list:userId,存储list,每个元素是消息id
还有一个是message:detail:textId,存储的是JSON,消息详情

1.2 消息发送

通过定时任务生成消息–.>存储到数据库和缓存中,获取消息列表的时候就可以从缓存中获取了,注意生成消息的时候只存在缓存中
缓存没有修改和删除

@Data
public class UserScore {
    private Long examId;
    private Long userId;
    private Integer score;
}

这个是新增加的类

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ck.job.mapper.user.UserSubmitMapper">

    <select id="selectUserScoreList" resultType="com.ck.job.domain.user.UserScore">
        SELECT
        user_id,
        exam_id,
        sum(score) as score
        FROM
        tb_user_submit
        <where>
            <foreach collection="examIdSet" open="exam_id in (" close=")" item="examId" separator="," > 
                #{examId}
            </foreach>
        </where>
        GROUP BY 
            user_id , exam_id
        ORDER BY
            score DESC
    </select>
</mapper>

这个是使用的xml

@Service
public class MessageServiceImpl extends ServiceImpl<MessageMapper, Message> implements IMessageService{
    @Override
    public boolean batchInsert(List<Message> messageList){
        return saveBatch(messageList);
    }
}
@Service
public class MessageTextServiceImpl extends ServiceImpl<MessageTextMapper, MessageText> implements IMessageTextService {
    @Override
    public boolean batchInsert(List<MessageText> messageTextList){
        return saveBatch(messageTextList);
    }
}

这个是批量插入的service方法

    public static final Long SYSTEM_USER_ID = 1L;

因为createBy无法获取用户Id,所以我们提前要设置好

    public static final String USER_MESSAGE_LIST_USERID = "user:message:list:";
    public static final String MESSAGE_DETAIL_MESSAGEID = "message:detail:";

这个是存入缓存的结构

@Data
public class MessageCacheVO {
    private String messageTitle;

    private String messageContent;
}

这个是存入信息详细数据的类

最后展示定时器的代码

    @XxlJob("examResultHandler")
    public void examResultHandler(){
        log.info("*****examResultHandler:凌晨统计排名*****");
        //先从数据库中获取所有已经结束的竞赛列表
        LocalDateTime now = LocalDateTime.now();
        LocalDateTime minusDays = now.minusDays(1);//获取小于一天的时间
        List<Exam> examList = examMapper.selectList(new LambdaQueryWrapper<Exam>()
                .select(Exam::getExamId,Exam::getTitle)
                .ge(Exam::getEndTime, minusDays)
                .le(Exam::getEndTime, now)//小于等于当前时间
                .eq(Exam::getStatus, Constants.TRUE));//已经发布)
        if(CollectionUtil.isEmpty(examList)){
            return;
        }
        Set<Long> examIdSet = examList.stream().map(Exam::getExamId).collect(Collectors.toSet());
        //然后根据examIdSet获取所有用户的分数
        List<UserScore> userScoreList = userSubmitMapper.selectUserScoreList(examIdSet);
        Map<Long, List<UserScore>> examIdUserScoreMap = userScoreList.stream().collect(Collectors.groupingBy(UserScore::getExamId));
        //按照examId分组,那么分数排名就已经OK了
        saveMessage(examList,examIdUserScoreMap);
    }

    private void saveMessage(List<Exam> examList, Map<Long, List<UserScore>> examIdUserScoreMap ) {
        List<Message> messageList = new ArrayList<>();//插入msg与用户对应信息数据库
        List<MessageText> messageTextList = new ArrayList<>();//插入数据库,msg详细信息
        for(Exam exam: examList){
            Long examId = exam.getExamId();
            List<UserScore> userScoreList = examIdUserScoreMap.get(examId);
            int userTotal = userScoreList.size();
            int rank  = 1;
            for (UserScore userScore : userScoreList){
                String msgTitle = exam.getTitle()+"——排名情况";
                String msgContent = "你参加的竞赛:"+ exam.getTitle()+",你的分数为:"
                        +userScore.getScore()+",总人数:+"+userTotal +",你的排名为:"+rank;
                rank++;
                MessageText messageText = new MessageText();
                messageText.setMessageTitle(msgTitle);
                messageText.setMessageContent(msgContent);
                messageText.setCreateBy(Constants.SYSTEM_USER_ID);
                messageTextList.add(messageText);
                Message message = new Message();
                message.setSendId(Constants.SYSTEM_USER_ID);
                message.setRecId(userScore.getUserId());
                message.setCreateBy(Constants.SYSTEM_USER_ID);
                messageList.add(message);
            }
        }
        messageTextService.batchInsert(messageTextList);
        //给messageList添加messageId
        Map<String, MessageCacheVO> messageCacheVOMap = new HashMap<>();//存入redis,信息详细数据
        for(int i=0;i<messageTextList.size();i++){
            MessageText messageText = messageTextList.get(i);
            Message message = messageList.get(i);
            message.setTextId(messageText.getTextId());

            MessageCacheVO messageCacheVO = new MessageCacheVO();
            messageCacheVO.setMessageContent(messageText.getMessageContent());
            messageCacheVO.setMessageTitle(messageText.getMessageTitle());
            String messageDetailKey = getMessageDetailKey(messageText.getTextId());
            messageCacheVOMap.put(messageDetailKey,messageCacheVO);
        }
        redisService.multiSet(messageCacheVOMap);
        messageService.batchInsert(messageList);
        //存入缓存,用户的信息列表---》那么就要把信息按照userId进行分组了
        Map<Long, List<Message>> userMsgMap = messageList.stream().collect(Collectors.groupingBy(Message::getRecId));
        Iterator<Map.Entry<Long, List<Message>>> iterator = userMsgMap.entrySet().iterator();
        while(iterator.hasNext()){
            Map.Entry<Long, List<Message>> entry = iterator.next();
            Long userId = entry.getKey();
            String userMessageListKey = getUserMessageListKey(userId);
            List<Message> userMessageList = entry.getValue();
            List<Long> userMsgIdList = userMessageList.stream().map(Message::getTextId).toList();
            redisService.rightPushAll(userMessageListKey,userMsgIdList);
        }
//        for (Map.Entry<Long, List<Message>> entry : userMsgMap.entrySet()) {
//            Long userId = entry.getKey();
//            String userMessageListKey = getUserMessageListKey(userId);
//            List<Message> userMessageList = entry.getValue();
//            List<Long> userMsgIdList = userMessageList.stream().map(Message::getTextId).toList();
//            redisService.rightPushAll(userMessageListKey, userMsgIdList);
//        }
    }
    private String getUserMessageListKey(Long userId) {
        return CacheConstants.USER_MESSAGE_LIST_USERID + userId;
    }

    private String getMessageDetailKey(Long messageTextId) {
        return CacheConstants.MESSAGE_DETAIL_MESSAGEID + messageTextId;
    }

我们使用的都是批量插入
在 Java 中,Iterator(迭代器)初始化后,其初始状态是指向集合中第一个元素的「前面」

1.3 消息列表展示

创建一个新的controller,UserMessageController

@RestController
@RequestMapping("/user/message")
@Tag(name = "C端用户信息接口")
@Slf4j
public class UserMessageController {
    @Autowired
    private IUserMessageService userMessageService;
    @GetMapping("/list")
    @Operation(description = "获取用户接收到的信息")
    public TableDataInfo list(PageQueryDTO dto){
        log.info("获取用户接收到的信息,PageQueryDTO:{}", dto);
        return userMessageService.list(dto);
    }
}

直接拷贝以前获取竞赛列表的代码,然后改吧改吧

@Data
public class MessageCacheVO {
    private Long textId;
    private String messageTitle;

    private String messageContent;
}

这个类要完善一下,因为从数据库中可以查询出这个类,然后刷新缓存就要用到messageTextId,记得定时器存入缓存的时候,这个字段也要完善

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ck.friend.mapper.message.MessageTextMapper">
    <select id="selectUserMsgList" resultType="com.ck.friend.domain.message.vo.MessageCacheVO">
        SELECT
        text_id,
        message_title,
        message_content,
        FROM
        tb_message m
        JOIN
        tb_message_text tm
        ON
        m.text_id = tm.text_id
        <where>
            m.rec_id = #{userId}
        </where>
        ORDER BY
        t.create_time DESC
    </select>
</mapper>

这个是根据userId查询它的所有的信息的xml

    @Override
    public TableDataInfo list(PageQueryDTO dto) {
        Long userId= ThreadLocalUtil.get(Constants.USER_ID,Long.class);
        Long listSize = userMessageCacheManager.getListSize(userId);
        List<MessageCacheVO> list ;
        if(listSize==null||listSize==0){
            //说明缓存中没有数据,所以要先从数据库中获取数据,然后存入redis
            PageHelper.startPage(dto.getPageNum(), dto.getPageSize());
            list = messageTextMapper.selectUserMsgList(userId);
            userMessageCacheManager.refreshCache(userId);
            long total = new PageInfo<>(list).getTotal();
            return TableDataInfo.success(list, total);
        }else{
            //直接从redis中获取数据
            list = userMessageCacheManager.getUserMsgList(dto,userId);
            listSize = userMessageCacheManager.getListSize(userId);
            return TableDataInfo.success(list, listSize);
        }
    }

这是service代码
然后是userMessageCacheManager的代码

@Component
public class UserMessageCacheManager {
    @Autowired
    private RedisService redisService;
    @Autowired
    private MessageTextMapper messageTextMapper;
    public Long getListSize(Long userId) {
        String userMessageListKey = getUserMessageListKey(userId);
        return redisService.getListSize(userMessageListKey);
    }

    public void refreshCache(Long userId) {
        List<MessageCacheVO> messageCacheVOList = new ArrayList<>();
        messageCacheVOList = messageTextMapper.selectUserMsgList(userId);//没有分页
        List<Long> userMsgIdList = messageCacheVOList.stream().map(MessageCacheVO::getTextId).toList();
        if (CollectionUtil.isEmpty(messageCacheVOList)) {
            return;
        }
        redisService.rightPushAll(getUserMessageListKey(userId), userMsgIdList);      //刷新列表缓存
        //刷新信息详情缓存
        Map<String, MessageCacheVO> messageCacheVOMap = new HashMap<>();
        for (MessageCacheVO messageCacheVO : messageCacheVOList) {
            messageCacheVOMap.put(getMessageDetailKey(messageCacheVO.getTextId()),messageCacheVO);
        }
        redisService.multiSet(messageCacheVOMap);  //刷新详情缓存
    }

    public List<MessageCacheVO> getUserMsgList(PageQueryDTO dto, Long userId) {
        int start = (dto.getPageNum() - 1) * dto.getPageSize();
        int end = start + dto.getPageSize() - 1; //下标需要 -1
        String userMessageListKey = getUserMessageListKey(userId);
        List<Long> messageIdList = redisService.getCacheListByRange(userMessageListKey, start, end, Long.class);
        List<MessageCacheVO> messageCacheVOList = assembleExamVOList(messageIdList);//从缓存中加载详情
        if (CollectionUtil.isEmpty(messageCacheVOList)) {
            //说明redis中数据可能有问题 从数据库中查数据并且重新刷新缓存
            messageCacheVOList = getMessageVOListByDB(dto,userId); //从数据库中获取数据
            refreshCache(userId);
        }
        return messageCacheVOList;
    }

    private List<MessageCacheVO> getMessageVOListByDB(PageQueryDTO dto, Long userId) {
        PageHelper.startPage(dto.getPageNum(), dto.getPageSize());
        return messageTextMapper.selectUserMsgList(userId);
    }

    private List<MessageCacheVO> assembleExamVOList(List<Long> messageIdList) {
        if (CollectionUtil.isEmpty(messageIdList)) {
            //说明redis当中没数据 从数据库中查数据并且重新刷新缓存
            return null;
        }
        //拼接redis当中key的方法 并且将拼接好的key存储到一个list中
        List<String> detailKeyList = new ArrayList<>();
        for (Long messageTextId : messageIdList) {
            detailKeyList.add(getMessageDetailKey(messageTextId));
        }
        List<MessageCacheVO> messageCacheVOList = redisService.multiGet(detailKeyList, MessageCacheVO.class);
        CollUtil.removeNull(messageCacheVOList);
        if (CollectionUtil.isEmpty(messageCacheVOList) || messageCacheVOList.size() != messageIdList.size()) {
            //说明redis中数据有问题 从数据库中查数据并且重新刷新缓存
            return null;
        }
        return messageCacheVOList;
    }

    private String getUserMessageListKey(Long userId) {
        return CacheConstants.USER_MESSAGE_LIST_USERID + userId;
    }

    private String getMessageDetailKey(Long messageTextId) {
        return CacheConstants.MESSAGE_DETAIL_MESSAGEID + messageTextId;
    }
}

1.4 前端开发

创建文件UserMessage.vue

<template>
    <div class="message-list">
        <div class="message-list-block">
            <div class="message-list-header">
                <span class="ms-title">我的消息</span>
                <span class="message-list-back" @click="goBack()">返回</span>
            </div>
            <div class="mesage-list-content" v-for="(item, index) in messageList" :key="index">
                <img src="@/assets/message/notice.png" width="50px" class="image" />
                <div class="message-content">
                    <div class="title-box">
                        <div class="title">
                            {{ item.messageTitle }}
                        </div>
                    </div>
                    <div class="content">{{ item.messageContent }}</div>
                </div>
                <el-button class="mesage-button" type="text" @click.stop="handlerDelete(item)">删除</el-button>
            </div>
            <div class="message-pagination">
                <!-- 增加分页展示器 -->
                <el-pagination background layout="total, sizes, prev, pager, next, jumper" :total="total"
                    v-model:current-page="params.pageNum" v-model:page-size="params.pageSize"
                    :page-sizes="[5, 10, 15, 20]" @size-change="handleSizeChange"
                    @current-change="handleCurrentChange" />
            </div>
        </div>
    </div>
</template>

<script setup>
import { getMessageListService } from "@/apis/message"
import router from "@/router"
import { reactive, ref } from "vue"

const messageList = ref([]) //消息列表

const total = ref(0)
const params = reactive({
    pageNum: 1,
    pageSize: 10,
})

//消息列表
async function getMessageList() {
    const ref = await getMessageListService(params)
    messageList.value = ref.rows
    total.value = ref.total
}
getMessageList()

const goBack = () => {
    router.go(-1)
}
// 分页
function handleSizeChange(newSize) {
    params.pageNum = 1
    getMessageList()
}

function handleCurrentChange(newPage) {
    getMessageList()
}
</script>
import service from "@/utils/request";

export function getMessageListService(params) {
  return service({
    url: "/user/message/list",
    method: "get",
    params,
  });
}

然后就可以测试了
在这里插入图片描述
我们创建三个用户来测试一下

在这里插入图片描述

    <select id="selectUserMsgList" resultType="com.ck.friend.domain.message.vo.MessageCacheVO">
        SELECT
        tm.text_id,
        tm.message_title,
        tm.message_content
        FROM
        tb_message m
        JOIN
        tb_message_text tm
        ON
        m.text_id = tm.text_id
        WHERE
            m.rec_id = #{userId}
        ORDER BY
        m.create_time DESC
    </select>

然后发现xml文件有问题

修改一下

在这里插入图片描述
成功了

2. 竞赛排名功能

在这里插入图片描述
就是历史竞赛那里的排名功能
未完赛没有查看排名功能
在这里插入图片描述

排名和得分和用户id都有了

但是得分和排名还没有存储—》tb_user_exam有排名的得分字段
----》不用重新统计了–》直接获取—》存入数据库,在定时器的时候

然后还要存入缓存–》key为exam:rank:list:examId
value为userId?不是,第一我们是为了防止一个数据存储多份,所以才存id,但是这里的排名是不会存储多份的,因为不同竞赛的排名和分数是不一样的,而且排名和分数是不能修改的
所以value就是需要什么存什么–》json–>examRank,nickName,score,其中examRank和score在不同竞赛中一般是不同的
但是nickName是会重复的,而且用户修改nickname还要改redis—》所以可以存userId,然后由userId获取redis中的nickname

我们现在定时器那里,修改tb_user_exam表,完善score和exam_rank字段
然后往redis中存入排名数据

@Data
public class UserScore {
    private Long examId;
    private Long userId;
    private Integer score;
    private Integer examRank;
}

完善一下这个类,这个是可以直接存入数据库中,什么都有了

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ck.job.mapper.user.UserExamMapper">

    <update id="updateScoreAndExamRank">
        <foreach collection="userScoreList" item="item" separator=";">
            UPDATE
            tb_user_exam
            SET
            score = #{item.score}, exam_rank = #{item.examRank}
            WHERE
            exam_id = #{item.examId} AND user_id = #{item.userId}
        </foreach>
    </update>
</mapper>

这个是修改数据库tb_user_exam的xml语句

    public static final String EXAM_RANK_LIST_EXAMID = "exam:rank:list:";
    private String getExamRankListKey(Long examId) {
        return CacheConstants.EXAM_RANK_LIST_EXAMID + examId;
    }

这个是redis的key
在savemessage方法中

        for(Exam exam: examList){
            Long examId = exam.getExamId();
            List<UserScore> userScoreList = examIdUserScoreMap.get(examId);
            int userTotal = userScoreList.size();
            int rank  = 1;
            for (UserScore userScore : userScoreList){
                String msgTitle = exam.getTitle()+"——排名情况";
                String msgContent = "你参加的竞赛:"+ exam.getTitle()+",你的分数为:"
                        +userScore.getScore()+",总人数:"+userTotal +",你的排名为:"+rank;
                userScore.setExamRank(rank);
                rank++;
                MessageText messageText = new MessageText();
                messageText.setMessageTitle(msgTitle);
                messageText.setMessageContent(msgContent);
                messageText.setCreateBy(Constants.SYSTEM_USER_ID);
                messageTextList.add(messageText);
                Message message = new Message();
                message.setSendId(Constants.SYSTEM_USER_ID);
                message.setRecId(userScore.getUserId());
                message.setCreateBy(Constants.SYSTEM_USER_ID);
                messageList.add(message);
            }
            userExamMapper.updateScoreAndExamRank(userScoreList);
            redisService.rightPushAll(getExamRankListKey(examId),userScoreList);
        }

然后是创建查询的controller

    @GetMapping("/rank/list")
    public TableDataInfo rankList(RankQueryDTO rankQueryDTO){
        log.info("获取竞赛排名列表信息,rankQueryDTO:{}", rankQueryDTO);
        return examService.rankList(rankQueryDTO);
    }
@Data
public class RankQueryDTO extends PageQueryDTO {
    private Long examId;
}

然后service

@Data
public class ExamRankCacheVO {
    private String nickName;
    private Long userId;
    private Integer score;
    private Integer examRank;
}

这个类是从缓存中要获取的数据,其中只用获取后面三个字段,第一个字段是再次获取的,再次从redis中获取

    <select id="selectExamRankCacheVOList" resultType="com.ck.friend.domain.exam.vo.ExamRankCacheVO">
        SELECT
            user_id,
            score,
            exam_rank
        FROM
            tb_user_exam
        WHERE
            exam_id = #{examId}
        ORDER BY
            exam_rank 
    </select>

这个是从数据库中获取排名信息的xml语句,根据examId

    @Override
    public TableDataInfo rankList(RankQueryDTO rankQueryDTO) {
        Long listSize = examCacheManager.getExamRankListSize(rankQueryDTO.getExamId());
        List<ExamRankCacheVO> list;
        if(listSize==null||listSize==0){
            //说明缓存中没有数据,所以要先从数据库中获取数据,然后存入redis
            PageHelper.startPage(rankQueryDTO.getPageNum(), rankQueryDTO.getPageSize());
            list = examMapper.selectExamRankCacheVOList(rankQueryDTO.getExamId());
            examCacheManager.refreshExamRankListCache(rankQueryDTO.getExamId());
            listSize  = new PageInfo<>(list).getTotal();
        }else{
            //直接从redis中获取数据
            list = examCacheManager.getExamRankList(rankQueryDTO);
        }
        assembleExamRankList(list);
        return TableDataInfo.success(list, listSize);
    }

    private void assembleExamRankList(List<ExamRankCacheVO> list) {
        if(CollectionUtil.isEmpty(list)){
            return;
        }
        for (ExamRankCacheVO examRankCacheVO : list) {
            UserVO user = userCacheManager.getUserById(examRankCacheVO.getUserId());
            examRankCacheVO.setNickName(user.getNickName());
        }
    }

然后是examCacheManager中的方法


    //竞赛排名
    public Long getExamRankListSize(Long examId) {
        return redisService.getListSize(getExamRankListKey(examId));
    }

    private String getExamRankListKey(Long examId) {
        return CacheConstants.EXAM_RANK_LIST_EXAMID + examId;
    }

    public void refreshExamRankListCache(Long examId) {
        //没有分页查询
        List<ExamRankCacheVO> examRankCacheVOList = examMapper.selectExamRankCacheVOList(examId);
        redisService.rightPushAll(getExamRankListKey(examId),examRankCacheVOList);
    }


    public List<ExamRankCacheVO> getExamRankList(RankQueryDTO rankQueryDTO) {
        int start = (rankQueryDTO.getPageNum() - 1) * rankQueryDTO.getPageSize();
        int end = start + rankQueryDTO.getPageSize() - 1; //下标需要 -1
        return redisService.getCacheListByRange(getExamRankListKey(rankQueryDTO.getExamId()),start,end,ExamRankCacheVO.class);
    }

这样就OK了

然后拷贝前端代码到exam.vue

  <el-dialog v-model="dialogVisible" width="600px" top="30vh" :show-close="true" :close-on-click-modal="false"
    :close-on-press-escape="false" class="oj-login-dialog-centor" center>
    <el-table :data="examRankList">
      <el-table-column label="排名" prop="examRank" />
      <el-table-column label="用户昵称" prop="nickName" />
      <el-table-column label="用户得分" prop="score" />
    </el-table>
    <el-pagination class="range_page" background layout="total, sizes, prev, pager, next, jumper" :total="rankTotal"
      v-model:current-page="rankParams.pageNum" v-model:page-size="rankParams.pageSize" :page-sizes="[5, 10, 15, 20]"
      @size-change="handleRankSizeChange" @current-change="handleRankCurrentChange" />
  </el-dialog>

//竞赛排名

const rankParams = reactive({
  examId:'',
  pageNum: 1,
  pageSize: 9,
})
const examRankList = ref([])
const rankTotal = ref(0)

// 分页
function handleRankSizeChange(newSize) {
  rankParams.pageNum = 1
  getExamRankList()
}

function handleRankCurrentChange(newPage) {
  getExamRankList()
}

const dialogVisible = ref(false)

async function getExamRankList() {
  const result = await getExamRankListService(rankParams)
  examRankList.value = result.rows
  rankTotal.value = result.total
}

function togglePopover(examId) {
  dialogVisible.value = true
  rankParams.examId = examId
  getExamRankList()
}

export function getExamRankListService(params) {
  return service({
    url: "/exam/rank/list",
    method: "get",
    params,
  });
}

然后就可以进行测试了
但是有一个要注意的点就是
我们的sql是不支持批量update的
要加上allowMultiQueries=true才可以
在这里插入图片描述

在这里插入图片描述

这样就成功了

总结8


网站公告

今日签到

点亮在社区的每一天
去签到