如何在项目中实现类似于微信的置顶与取消置顶的功能?
- 借鉴微信的置顶与取消置顶的实现思路:
会看到这个微信的聊天记录的排序规则是以时间降序来进行排序的,如果要实现置顶与取消置顶? 一下子是想不到的,需要思路
由此可以确信的是,我们平时使用微信时,最新的聊天记录总是在前面的,多久不聊的聊天是在最后面的。
在项目中需要实现置顶与取消置顶的功能,刚开始没有思路,苦思冥想了半天,以前也没有做过类似的需求。
于是我一直在使用微信的置顶与取消置顶的功能,玩着玩着还挺好玩,我只要最后点击某条聊天记录置顶,那么这条记录就一定会在第一条显示,并且在它前面置顶的聊天记录会依次在它的下面显示。如果我取消了某条 (置顶过) 的聊天记录,那么它的位置就是在它(聊天记录)的 创建的时间点上。当时就特别好奇,这到底要怎么实现?
一直写SQL语句反复尝试还没有思路,整个人都快傻了,这应该是个很简单的功能,为什么就是写不出来,又想不对啊,怎么可能在一个字段中就 实现置顶与取消置顶,并且还要排序? 终于,我在测试表中仅有的字段又加了一个标记字段 is_top(是否置顶), 神奇的现象发生了, 我想要的结果出来了 ,哈哈哈
(这是类似于微信的,先以是否置顶降序排,再以排序字段降序排(盲猜我这个对应微信的聊天记录的创建时间,哈哈哈))SELECT * FROM tb_test ORDER BY is_top DESC,sort_num DESC
(这是我,应该更容易理解,嗯)
SELECT * FROM `tb_test` ORDER BY is_top DESC,sort_num ASC
从结果可以看出来,这句SQL语句再执行的时候,先排第一个字段,再排第二个字段,所有从这个思路,思路逐渐清晰:
当前文稿置顶:
@Overridepublic Map<Integer, String> stick(Long publishId) {// 1: 获取 is_top字段 的最大值Integer isTopMax = publishInfoMapper.getIsTopMax();// 2: 查询当前文稿PublishInfo publishInfoUpdate = new PublishInfo();publishInfoUpdate.setPublishId(publishId);// 创建查询对象QueryWrapper<PublishInfo> queryWrapper = Wrappers.query(publishInfoUpdate);PublishInfo publishInfo = null;try {publishInfo = publishInfoMapper.selectOne(queryWrapper);} catch (Exception e) {throw new RuntimeException(e);}Map<Integer, String> resultMap = new HashMap<>();if (ObjectUtils.isEmpty(publishInfo)) {throw new OperationException(OperationExEnum.ABSENT, "无法找到对应id的文稿,无法进行置顶显示,请确认id是否正确 !");} else {Integer isTop = publishInfo.getIsTop();if (isTop.equals(isTopMax)) {resultMap.put(OperationExEnum.MODIFICATION_FAILURE.getStatusCode(), "当前文稿已经置顶,请重新选择 !");} else if (isTop < 0) {// 说明数据发生了人为改变!throw new OperationException(OperationExEnum.ERROR.getStatusCode(), "数据错误,请联系工作人员 !");}if (!isTop.equals(isTopMax) && isTop >= 0) {// 更新UpdateWrapper<PublishInfo> updateWrapper = Wrappers.update();// 更新的字段 is_top字段值加一,当前的文档置顶!updateWrapper.set(OperationConst.IS_TOP, isTopMax + 1);// 指定条件updateWrapper.eq(OperationConst.PUBLISH_ID, publishInfo.getPublishId());int update = publishInfoMapper.update(publishInfoUpdate, updateWrapper);if (update != 1) {throw new OperationException(OperationExEnum.MODIFICATION_FAILURE, "置顶文稿失败 ! 请稍后操作 !");} else {resultMap.put(OperationExEnum.MODIFICATION_ACCESS.getStatusCode(), "置顶文稿成功 ! ~~~");}}}return resultMap;}
is_top 从前端传过来只是0或1的值, (0代表取消置顶按钮的点击事件,1代表当前置顶按钮的点击事件) 而数据库中is_top 是在业务层自己处理逻辑的,经过反复测试没有什么问题
取消文稿置顶:
@Overridepublic Map<Integer, String> cancelStick(Long publishId) {// 1: 根据文稿id查询当前这个文稿是否置顶PublishInfo publishInfoUpdate = new PublishInfo();publishInfoUpdate.setPublishId(publishId);// 创建查询对象QueryWrapper<PublishInfo> queryWrapper = Wrappers.query(publishInfoUpdate);PublishInfo publishInfo = null;try {publishInfo = publishInfoMapper.selectOne(queryWrapper);} catch (Exception e) {e.printStackTrace();}Map<Integer, String> resultMap = new HashMap<>();if (ObjectUtils.isEmpty(publishInfo)) {throw new OperationException(OperationExEnum.ABSENT, "无法找到对应id的文稿,请确认再操作 !");} else {Integer isTop = publishInfo.getIsTop();if (isTop > 0) {// 更新UpdateWrapper<PublishInfo> updateWrapper = Wrappers.update();// 更新的字段updateWrapper.set(OperationConst.IS_TOP, 0);// 指定条件updateWrapper.eq(OperationConst.PUBLISH_ID, publishInfo.getPublishId());int update = publishInfoMapper.update(publishInfoUpdate, updateWrapper);if (update != 1) {throw new OperationException(OperationExEnum.MODIFICATION_FAILURE, "取消置顶失败 ! 请稍后操作 !");} else {resultMap.put(OperationExEnum.MODIFICATION_ACCESS.getStatusCode(), "取消置顶成功 ! ~~~");}}//如果就是0,说明该文稿本身就没有置顶!else if (isTop.equals(0)) {resultMap.put(OperationExEnum.ABSENT.getStatusCode(), "该文稿不是置顶显示,请重新选择 !");} else {// 说明数据发生了人为改变!throw new OperationException(OperationExEnum.ERROR.getStatusCode(), "数据错误,请联系工作人员 !");}}return resultMap;}
取消置顶的思路完全就是取决于置顶的思路, 只是把is_top的值改为不可再排序的默认值,
使用MybatisPlus 的API 拼接的分页排序语句:
// 1: 创建分页前的数据IPage<PublishInfo> pageNoAndPageSize = new Page<>(pageNo, pageSize);// 2: 封装查询条件 ,(如果该文稿置顶,就按照)is_top字段降序排序 然后再按照 指定sort_num字段 升序排序// (如果文稿不置顶就按照 它指定的sort_num 的值排序 ) 按照 指定sort_num字段 升序排序QueryWrapper<PublishInfo> query = Wrappers.query();query.orderByDesc(OperationConst.IS_TOP).orderByAsc(OperationConst.SORT_NUM);// 3: 查询IPage<PublishInfo> publishInfoPage = publishInfoMapper.selectPage(pageNoAndPageSize, query);// ....................省略................................
如果在添加某个文稿的时候就需要 (置顶) 代码:
if (isTop.equals(1)) {// 拿到当前isTop的最大值Integer isTopMax = publishInfoMapper.getIsTopMax();// 如果当前isTop的最大值是0 , 说明还没有文稿置顶if (isTopMax.equals(0)) {// 当前文稿的isTop值为 1publishInfo.setIsTop(1);} else {// 否则当前文稿的isTop值就是最大值加1publishInfo.setIsTop(isTopMax + 1);}}
// ..............................省略..............................
(如果想让每个文稿sort_num的值不与数据库中的sort_num字段的重复代码):
// 3: 判断当前添加的文稿对象的sort_num 值 在数据库中是否存在Integer sortNum = publishInfo.getSortNum();// 拿到所有的sort_num的值 , 并升序排序ArrayList<Integer> sortNumList = publishInfoMapper.getSortNums();Collections.sort(sortNumList);Map<Integer, String> resultMap = new HashMap<>();// 4: 如果文稿的排序字段不为空, 则判断当前的数据库的sort_num中有没有 新加的文稿的排序字段,// 如果包含了, 就是 sort_num字段 最大值 + 1, 并返回友好提示信息, 如果没有就是添加的排序字段if (sortNum != null) {for (int i = 0; i < sortNumList.size(); i++) {if (sortNum.equals(sortNumList.get(i))) {publishInfo.setSortNum(sortNumList.get(sortNumList.size() - 1) + 1);if (isTop.equals(1)) {resultMap.put(OperationExEnum.ALREADY_EXISTS.getStatusCode(), "您添加的排序字段已经存在,您的排序字段默认为末序,当前是置顶显示 ! ");break;} else {resultMap.put(OperationExEnum.ALREADY_EXISTS.getStatusCode(), "您添加的排序字段已经存在,您的排序字段默认为末序 ! ");break;}}}} else {publishInfo.setSortNum(sortNumList.get(sortNumList.size() - 1) + 1);if (isTop.equals(1)) {resultMap.put(OperationExEnum.ABSENT.getStatusCode(), "您添加的排序字段为空(您未添加排序字段), 默认为末序, 当前是置顶显示 ! ");} else {resultMap.put(OperationExEnum.ABSENT.getStatusCode(), "您添加的排序字段为空(您未添加排序字段), 默认为末序 ! ");}}
Sum up:
1: 没有置顶的数据的is_top字段的值都是一样的(比如默认都是0,或者默认是一样的值)
2: 如果默认的是0,初始置顶值是1 , 或者是2 …
3: 如果默认的是1,初始置顶值是2 , 或者是3 …
4: 当前置顶的数据is_top字段的值永远是所有数据is_top字段中的最大值
5: 当前置顶的数据的is_top字段的值一定是比上一个置顶的数据 大1…, 或者大 2 …
6: 取消置顶那么就是设置为默认值就好了,使它不能再以is_top排序
7: order by is_top ASC|DESC , (sort_num ASC|DESC 或者create_time ASC|DESC ),以你的需求来定
8: is_top的值是随时都会变化的 , 建议使用 bigint 数据类型,对应Java的 Long | long类型
MybatisPlus生成的 SQL语句日志
==> Preparing: SELECT publish_id,publisher,status,sort_num,title_detail,title,title_image_url,service_dir_ids,mountings_dir_ids,belong_category_name,is_top,belong_category_id,create_time,after_update_time FROM tb_publish_info ORDER BY is_top DESC , sort_num ASC LIMIT ?,? ==> Parameters: 0(Long), 8(Long)<== Total: 8
这篇文章对你有帮助吗?作为一名程序工程师,在评论区留下你的困惑或你的见解,大家一起来交流吧! ~~~~~~~~~
如何在项目中实现类似于微信的置顶与取消置顶的功能?相关推荐
- Vue 项目中实现的微信、微博、QQ空间分享功能(亲测有效)
需求:文章添加分享功能(包括微信.微博.QQ空间) 如下图所示: 点击图标分别跳转到如下界面:(实现效果如下) 话不多说直接代码(可以封装成组件) <template><div cl ...
- vue项目中,使用微信js-sdk打开微信内置导航,唤醒第三方导航,
vue项目中,使用微信js-sdk打开微信内置导航,唤醒第三方导航 一.准备工作 二.开发须知 三.开始安装sdk 四.通过微信的config接口注入权限验证配置 附上代码 最近在搞vue项目需要在手 ...
- 从原理到实践:装饰器模式如何在项目中落地详解(给原对象增加新的行为和功能)
装饰器模式---- 不修改原始对象,给原对象增加新的行为和功能. 2.1.概念 装饰器模式(Decorator Pattern)是一种结构型设计模式,它允许动态地向对象添加额外的功能,而无需修改其原始 ...
- 项目中如何整合微信支付
- 在vue-cli项目中使用微信sdk的解决方案
在vue-cli 创建的项目中,引入微信分享的sdk的方法. 说明: 仅将官方 js-sdk 发布到 npm,便于 browserify 使用 js源码: https://res.wx.qq.com/ ...
- 【转】Web API项目中使用Area对业务进行分类管理
在之前开发的很多Web API项目中,为了方便以及快速开发,往往把整个Web API的控制器放在基目录的Controllers目录中,但随着业务越来越复杂,这样Controllers目录中的文件就增加 ...
- vue 项目中 自动生成 二维码
vue 项目中 自动生成 二维码 最近在写一个vue项目,要求根据卡号可以自动生成一个二维码,并渲染在指定位置,因为第一次做类似业务,小编在网上找了找,发现了很多,具体起来主要用的就两种: QRc ...
- h5支付不能打开支付宝 ios_iOS支付宝支付(Alipay)详细接入流程以及项目中遇到的问题分析...
最近在项目中接入了微信支付和支付宝支付,总的来说没有那么坑,很多人都说文档不全什么的,确实没有面面 俱到,但是认真一步一步测试下还是妥妥的,再配合懂得后台,效率也是很高的,看了这篇文章,你也只要几分钟 ...
- iOS支付宝支付(Alipay)详细接入流程以及项目中遇到的问题分析
最近在项目中接入了微信支付和支付宝支付,总的来说没有那么坑,很多人都说文档不全什么的,确实没有面面俱到,但是认真一步一步测试下还是妥妥的,再配合懂得后台,效率也是很高的,看了这篇文章,你也只要几分钟, ...
最新文章
- java多线程w3c_Java创建多线程的三种方式
- ceph-deploy rpm包的制作
- 云脑人力资源管理软件EHR选型手记(即时连载)
- android7.1增加一个开机自启动的bin应用遇到的权限问题
- matlab显示的图片,手动保存时四周有白边
- graph 关系图 设置
- html写个用户协议,五分钟学会HTML5的WebSocket协议
- 材料成形计算机辅助设计,材料成型及计算机辅助设计(综述)
- java dubbo swagger_Dubbo 的 Swagger 服务文档 swagger-dubbo
- JSP 高校后勤报修管理系统myeclipse开发mysql数据库bs框架java编程serlvet(MVC)结构详细设计
- 软件选择,iDreamPiano、freepiano、EveryonePiano
- 小白用C语言编写贪吃蛇
- Java封装、继承、多态、super杂糅在一起的小练习,公司雇员员工工资问题(Employee),练习扩展:创建一个Employee数组,分别创建不同的Employee对象,并打印某个月的工资
- matlab与测绘数据处理,MATLAB与测绘数据处理
- 我们应不应该继续学习python
- WebAssembly:系统编程语言的逆袭
- 学习Python人工智能前景如何
- 计算机设备选型的基本原则,设备选型的概念和选型依据
- 强制打印方法,输出重定向解决
- 青少年护眼灯哪个牌子好?儿童护眼灯品牌推荐