柚见十三期(优化)

前端优化

加载匹配功能与加载骨架特效

骨架屏 : vant-skeleton

index.vue中

/**  * 加载数据  */  
const loadData = async () => {  let userListData;  loading.value = true;  //心动模式  if (isMatchMode.value){  const  num = 10;//推荐人数  userListData = await myAxios.get('user/match',{  params: {  num,  },  })  .then(function (response) {  console.log('/user/match succeed',response);  return response?.data;  })  .catch(function (error) {  console.log('/user/match error',error);  showFailToast('请求失败');  });  }  else {  //不开启推荐模式,默认全部查询  //普通用户使用分页查询todo 并没有实现  userListData = await  myAxios.get('/user/recommend',{  params: {  pageSize: 8,  pageNum: 1,  },  })  .then(function (response) {  console.log('/user/recommend succeed', response);  return response?.data?.records;  })  .catch(function (error) {  console.log('/user/recommends error',error);  showFailToast('请求失败');  });  }  if (userListData){  userListData.forEach((user: userType) =>{  if (user.tags){  user.tags = JSON.parse(user.tags);  }  })  userList.value = userListData;  }  loading.value = false;  
}  //`watchEffect`函数用于在响应式数据发生变化时执行副作用(side effect)操作。在这个例子中,当数据发生变化时,会调用`loadData()`函数来加载数据。watchEffect(() =>{  loadData();  
})

在这里插入图片描述

前端导航标题

router :控制路由跳转
route: 获取路由信息

解决:使用 router.beforeEach,根据要跳转页面的 url 路径 匹配 config/routes 配置的 title 字段

在这里插入图片描述

在这里插入图片描述

//标题  
const DEFAULT_TITLE='柚见'  
const title=ref(DEFAULT_TITLE);  
/**  * 根据路由切换标题  */  
router.beforeEach((to,from)=>{  const toPath=to.path;  const route=routes.find((r)=>{  return toPath==r.path;  })  title.value=route.title ?? DEFAULT_TITLE;  })

重定向到登录页

根据后端返回的未登录的错误码,重定向

全局响应拦截器中修改
在这里插入图片描述

发现页面一直不能正常跳转
切换hash模式
不同的历史模式 | Vue Router (vuejs.org)
在这里插入图片描述

登录成功后自动跳转回之前页面

在这里插入图片描述

添加创建队伍按钮

添加样式

在这里插入图片描述

引入样式

在这里插入图片描述

在这里插入图片描述

换成vant库中的+
在这里插入图片描述

<!--  创建队伍按钮-->  <van-button type="primary" @click="doJoinTeam" class="add-button" icon="plus">  </van-button>

队伍操作按钮权限控制

更新队伍:仅创建人可见

 v-if="team.userId === currentUser?.id"

解散队伍:仅创建人可见

 v-if="team.userId === currentUser?.id"

加入队伍: 仅非队伍创建人、且未加入队伍的人可见
退出队伍:创建人不可见,仅已加入队伍的人可见

后端修改

仅加入队伍和创建队伍的人能看到队伍操作按钮(listTeam 接口要能获取我加入的队伍状态) ✔

方案 1:前端查询我加入了哪些队伍列表,然后判断每个队伍 id 是否在列表中(前端要多发一次请求)

方案 2:在后端去做上述事情(推荐)

加密队伍与公开队伍的展示

前端修改

Tab 标签页 - Vant 4 (gitee.io)

<van-tabs v-model:active="activeName">  <van-tab title="公开队伍" name="public"></van-tab>  <van-tab title="加密队伍" name="secret"></van-tab>  
</van-tabs>

在这里插入图片描述

const onTabChange=(name)=>{  if(name==='public')  {  //查询公开队伍  listTeam()  }else if(name === 'secret'){  //查询加密队伍  listTeam(' ',2);  }  console.log(name)  }
//只有管理员和本人才能查看非私有的房间  
if (!isManager && !statusEnum.equals(TeamStatusEnum.PUBLIC) && !statusEnum.equals(TeamStatusEnum.SECRET)) {  
throw new BusinessException(ErrorCode.NO_AUTH);  
}

点击加入加密队伍后,弹窗密码跳出

在这里插入图片描述

<script setup lang="ts">  
import {TeamType} from "../models/team";  
import {teamStatusEnum} from "../constants/team.ts";  
import myAxios from "../plungins/myAxios.js";  
import {showFailToast, showSuccessToast} from "vant";  
import {onMounted, ref} from "vue";  
import {getCurrentUser} from "../services/user.ts";  
import {useRouter} from "vue-router";  const  router=useRouter();  
const password=ref('');  
//加入该队伍的id  
const joinId=ref(0)  
const showPwd=ref(false)  
interface TeamCardListProps{  teamList: TeamType[];  
}  const props= withDefaults(defineProps<TeamCardListProps>(),{  //@ts-ignore  teamList: [] as TeamType[]  
});  //获得当前用户  
const currentUser=ref()  
onMounted(async ()=>{  const res=await getCurrentUser()  currentUser.value=res  
})  //加入队伍之前---------------------------------------------------------------------  
const preJoinTeam=(team : TeamType)=>{  joinId.value=team.id;  if(team.status === 2)  {  //打开加密弹窗  showPwd.value=true;  }  else if(team.status === 0)  {  doJoinTeam();  }  
}  
const doJoinCancel = () => {  joinId.value = 0;  password.value = '';  
}  
//点击公开队伍,加入队伍------------------------------------------------------------  
const doJoinTeam=async()=>{  if(!joinId.value)  {  return ;  }  const res=await myAxios.post('/team/join',{  teamId:joinId.value,  password:password.value  })  if(res?.code===0){  showSuccessToast("加入成功")  doJoinCancel();  }else{  showFailToast("加入失败\n"+(res.description ? `${res.description}`: ''))  }  
}  
//跳转到更新页---------------------------------------------------------------------  
const doUpdateTeam=({id}: { id: any })=>{  router.push({  path:'/team/update',  query:{  id  }  })  
}  
//点击退出队伍-------------------------------------------------------------------  
const doQuitTeam=async (id)=>{  const res=await myAxios.post('/team/quit',{  teamId:id  })  if(res?.code===0){  showSuccessToast("操作成功")  }else{  showFailToast("操作失败\n"+(res.description ? `${res.description}`: ''))  }  }  
//点击解散队伍-------------------------------------------------------------------------  
const doDeleteTeam=async ({id}: { id: any })=>{  const res=await myAxios.post('/team/delete',{  id  })  if(res?.code===0){  showSuccessToast("操作成功")  }else{  showFailToast("操作失败\n"+(res.description ? `${res.description}`: ''))  }  
}  </script>

已加入队伍人数

<div>  {{ `已加入人数 : ${team.hasJoinNum} / ` + team.maxNum }}  
</div>

后端优化

队伍按钮权限控制

在这里插入图片描述

在这里插入图片描述

@GetMapping("/list")  
public BaseResponse<List<TeamUserVO>> listTeams(TeamQuery teamQuery,HttpServletRequest request) {  if (teamQuery == null) {  
throw new BusinessException(ErrorCode.PARAMS_ERROR);  
}  
boolean isManager = userService.isManager(request);  
User loginUser = userService.getLoginUser(request);  // 1、查询队伍列表  
List<TeamUserVO> teamList = teamService.listTeams(teamQuery, isManager);  
final List<Integer> teamIdList = teamList.stream().map(TeamUserVO::getId).collect(Collectors.toList());  
// 2、判断当前用户是否已加入队伍  
QueryWrapper<UserTeam> userTeamQueryWrapper = new QueryWrapper<>();  
try {  
userTeamQueryWrapper.eq("userId", loginUser.getId());  
userTeamQueryWrapper.in("teamId", teamIdList);  
List<UserTeam> userTeamList = userTeamService.list(userTeamQueryWrapper);  
// 已加入的队伍 id 集合  
Set<Integer> hasJoinTeamIdSet = userTeamList.stream().map(UserTeam::getTeamId).collect(Collectors.toSet());  
teamList.forEach(team -> {  
boolean hasJoin = hasJoinTeamIdSet.contains(team.getId());  
team.setHasJoin(hasJoin);  
});  
} catch (Exception e) {}  return ResultUtils.success(teamList);  
}

查询已加入队伍的人数

//3.查询已加入队伍数  
QueryWrapper<UserTeam> userTeamQueryWrapper2 = new QueryWrapper<>();  
userTeamQueryWrapper.in("teamId", teamIdList);  
List<UserTeam> userTeamList2 = userTeamService.list(userTeamQueryWrapper2);  //队伍id => userId集合  
Map<Integer, List<UserTeam>> teamIdUserTeamList = userTeamList2.stream().collect(Collectors.groupingBy(UserTeam::getTeamId));  
teamList.forEach(team ->  
team.setHasJoinNum(teamIdUserTeamList.getOrDefault(team.getId(), new ArrayList<>()).size())  
);

多次快速点击加入队伍,重复加入队伍

只要我们点的足够快,就可以在同一时间内往数据库插入多条同样的数据,所以这里我们使用分布式锁(推荐)使用两把锁,一把锁锁队伍,一把锁锁用户(实现较难,不推荐)

之前的代码

//该用户已加入的队伍数量不能超过5个  
int userId = loginUser.getId();  
// 只有一个线程能获取到锁  
RLock lock = redissonClient.getLock("youjian:join_team");  QueryWrapper<UserTeam> userTeamQueryWrapper = new QueryWrapper<>();  
userTeamQueryWrapper.eq("userId",userId);  
int hasJoinNum = (int) userTeamService.count(userTeamQueryWrapper);  
if (hasJoinNum >= 5){  
throw new BusinessException(ErrorCode.PARAMS_ERROR,"最多创建和加入5个队伍");  
}  //不能重复加入已加入的队伍  
userTeamQueryWrapper = new QueryWrapper<>();  
userTeamQueryWrapper.eq("userId",userId);  
userTeamQueryWrapper.eq("teamId",teamId);  
int hasUserJoinTeam = (int) userTeamService.count(userTeamQueryWrapper);  
if (hasUserJoinTeam > 0){  
throw new BusinessException(ErrorCode.PARAMS_ERROR,"用户已加入该队伍");  
}  
//不能加入已满队伍  
userTeamQueryWrapper = new QueryWrapper<>();  
userTeamQueryWrapper.eq("teamId",teamId);  
int teamHasJoinNum = (int) userTeamService.count(userTeamQueryWrapper);  
if (teamHasJoinNum >= team.getMaxNum()){  
throw new BusinessException(ErrorCode.PARAMS_ERROR,"队伍已满");  
}  //3.加入,修改队伍信息  
UserTeam userTeam = new UserTeam();  
userTeam.setUserId(userId);  
userTeam.setTeamId(teamId);  
userTeam.setJoinTime(new Date());  
return userTeamService.save(userTeam);

修改后

@Resource  
private RedissonClient redissonClient;

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/750154.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于SpringBoot框架实现的B2B平台的医疗病历交互系统

采用技术 基于SpringBoot框架实现的B2B平台的医疗病历交互系统的设计与实现~ 开发语言&#xff1a;Java 数据库&#xff1a;MySQL 技术&#xff1a;SpringBootMyBatis 工具&#xff1a;IDEA/Ecilpse、Navicat、Maven 页面展示效果 管理员角色 医院管理 医院注册 医院文…

音频的录制及播放

在终端安装好pip install pyaudio&#xff0c;在pycharm中敲入录音的代码&#xff0c;然后点击运行可以在10s内进行录音&#xff0c;录音后的音频会保存在与录音代码同一路径项目中&#xff0c;然后再新建项目敲入播放的代码&#xff0c;点击运行&#xff0c;会把录入的录音进行…

C语言-strerror(打印错误信息)和perror(获得错误信息)

strerror&#xff08;打印错误信息&#xff09;和perror&#xff08;获得错误信息&#xff09; strerror 语法格式 返回类型是char* 都需要头文件 errno.h 这里是错误码 每一个错误码代表一个错误信息 错误码 对照的错误信息 每一种编译器在写的时候已经规定好了 错误码对…

四连杆机构运动学仿真 | 【Matlab源码+理论公式文本】

【程序简介】&#x1f4bb;&#x1f50d; 本程序通过matlab实现了四连杆机构的运动学仿真编程&#xff0c;动态展现了四连杆机构的运动动画&#xff0c;同时给出了角位移、角速度和角加速度的时程曲线&#xff0c;除了程序本身&#xff0c;还提供了机构运动学公式推导文档&…

【Hadoop大数据技术】——MapReduce分布式计算框架(学习笔记)

&#x1f4d6; 前言&#xff1a;MapReduce是Hadoop系统核心组件之一&#xff0c;它是一种可用于大数据并行处理的计算模型、框架和平台&#xff0c;主要解决海量数据的计算问题&#xff0c;是目前分布式计算模型中应用较为广泛的一种。 目录 &#x1f552; 1. MapReduce概述&am…

Ubuntu 虚拟机安装

最小化安装后常用工具 sudo apt-get install vim# ifconfig apt install net-tools # nload apt install nload # 很多都要用到 apt install build-essential # 开发相关 apt install gcc gapt install iproute2 ntpdate tcpdump telnet traceroute \ nfs-kernel-server nfs…

Ubuntu 14.04:安装 PaddleOCR 2.3

目录 一、说明 1.1 如何选择版本 1.2 查看 github 中的 PaddleOCR 版本 二、安装 2.1 安装前环境准备 2.2 下载包 2.3 解压 2.4 安装依赖库 异常处理&#xff1a;Read timed out. 2.5 下载推理模型&#xff1a;inference 2.5.1 模型存放位置 2.5.2 模型下载链接 2.5.…

JVM学习-底层字节码的执行过程

目录 1.一个简单的程序分析 2. a&#xff0c;a&#xff0c;a--在JVM中的执行过程 3. 一个好玩的xx 4.方法调用的字节码分析、多态的实现、对象头 5. try-catch-finally的字节码分析 5.1 try-catch 5.2 try-catch-finally 5.3特殊情况 5.3.1 try和finally块中都出现了re…

【Miniconda】基于conda避免运行多个PyTorch项目时发生版本冲突

【Miniconda】基于conda避免运行多个PyTorch项目时发生版本冲突 &#x1f308; 个人主页&#xff1a;高斯小哥 &#x1f525; 高质量专栏&#xff1a;Matplotlib之旅&#xff1a;零基础精通数据可视化、Python基础【高质量合集】、PyTorch零基础入门教程&#x1f448; 希望得到…

SQL的执行与优化

文章目录 MySQL查询原理与优化一、select语句的执行顺序二、join 的执行与优化1、驱动表 & 被驱动表2、Simple Nested Loop Join3、Index Nested Loop Join4、Block Nested Loop Join5、Hash Join6、join 优化小结 三、on 与 where 对比四、group by 的执行与优化1、group …

刚刚离乳的幼猫该如何选择猫粮品牌?

亲爱的猫友们&#xff0c;当你家的幼猫刚刚离乳&#xff0c;准备踏入猫粮的世界时&#xff0c;如何选择一款合适的猫粮品牌确实是个让人头疼的问题。&#x1f43e; 别担心&#xff0c;今天我就来为大家推荐一款值得信赖的幼猫粮——福派斯幼猫粮。 1️⃣ 考虑幼猫的营养需求 幼…

macOS系统中通过brew安装MongoDB

Macos 修改目录权限&#xff1a; sudo chmod -R 777 你的文件夹 本文使用homebrew进行安装简单&#xff0c;因为从官网下载安装包并手动安装需要移动安装包到合适的目录下并配置环境变量等一大堆操作后才能使用数据库&#xff08;若没有安装过brew请自行百度进行安装brew&am…

ArkTs的资源Resource类型怎么转为string

使用ResourceManager同步转换 请参看&#xff1a;ResourceManager.getStringSync9 例子&#xff1a; try { let testStr: string this.context.resourceManager.getStringSync($r(app.string.test).id); } catch (error) { console.error(getStringSync failed, error code…

【四 (5)数据可视化之 Pyecharts常用图表及代码实现 】

目录 文章导航一、介绍[✨ 特性]二、安装Pyecharts三、主题风格四、占比类图表1、饼图2、环形图3、玫瑰图4、玫瑰图-多图5、堆叠条形图6、百分比堆叠条形图 五、比较排序类1、条形图2、雷达图3、词云图4、漏斗图 六、趋势类图表1、折线图2、堆叠折线图3、面积图4、堆叠面积图 七…

【AI】Ubuntu系统深度学习框架的神经网络图绘制

一、Graphviz 在Ubuntu上安装Graphviz&#xff0c;可以使用命令行工具apt进行安装。 安装Graphviz的步骤相对简单。打开终端&#xff0c;输入以下命令更新软件包列表&#xff1a;sudo apt update。之后&#xff0c;使用命令sudo apt install graphviz来安装Graphviz软件包。为…

MySQL语法分类 DQL(1)基础查询

//语法 select 字段列表 from 表名列表 where条件列表 group by分组字段 having 分组后的条件 order by排序 limit 分页限定为了更好的学习这里给出基本表数据用于查询操作 create table student (id int, name varchar(20), age int, sex varchar(5),address varchar(100),ma…

将 OpenCV 与 Eclipse 结合使用(插件 CDT)

返回&#xff1a;OpenCV系列文章目录&#xff08;持续更新中......&#xff09; 上一篇&#xff1a;将OpenCV与gcc和CMake结合使用 下一篇&#xff1a;OpenCV4.9.0在windows系统下的安装 警告&#xff1a; 本教程可以包含过时的信息。 先决条件 两种方式&#xff0c;一种…

CODESYS开发教程13-长字符串处理

摘要&#xff1a;这是一篇写给新手的关于CODESYS开发环境的小白教程&#xff0c;一看就懂...... 在以前的《CODESYS开发教程7-字符串及其基本操作》教程中&#xff0c;介绍了字符串及其基本操作&#xff0c;有朋友看了以后觉得不过瘾&#xff0c;希望有一些关于字符串的更加深入…

javaweb员工健康管理监护系统

项目演示视频 &#xff08;链接&#xff1a;https://pan.baidu.com/s/1WliYEUH4c0HVB7s0-1WDUA 提取码&#xff1a;1234 --来自百度网盘超级会员V5的分享&#xff09; 该项目所用到技术 java ssh框架 3&#xff1a;该项目的用到的开发工具&#xff1f; eclipse和idea都可以、m…

Echo框架:高性能的Golang Web框架

Echo框架&#xff1a;高性能的Golang Web框架 在Golang的Web开发领域&#xff0c;选择一个适合的框架是构建高性能和可扩展应用程序的关键。Echo是一个备受推崇的Golang Web框架&#xff0c;以其简洁高效和强大功能而广受欢迎。本文将介绍Echo框架的基本特点、使用方式及其优势…