前端:vite+vue3+ts+elementplus+less
后端:springboot2.7.5+mybatisplus
后端:
引入pom依赖
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.24</version> </dependency> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.5.2</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies>
运行sql
/*
Navicat Premium Data TransferSource Server : MyDemo
Source Server Type : MySQL
Source Server Version : 80027
Source Host : 192.168.157.134:3306
Source Schema : giveALikeTarget Server Type : MySQL
Target Server Version : 80027
File Encoding : 65001Date: 21/11/2022 23:50:34
*/SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;-- ----------------------------
-- Table structure for article
-- ----------------------------
DROP TABLE IF EXISTS `article`;
CREATE TABLE `article` (
`id` int NOT NULL AUTO_INCREMENT COMMENT '编号',
`content` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL COMMENT '内容',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 5 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;-- ----------------------------
-- Records of article
-- ----------------------------
INSERT INTO `article` VALUES (1, '11');
INSERT INTO `article` VALUES (2, '666');
INSERT INTO `article` VALUES (3, '777');
INSERT INTO `article` VALUES (4, '999');-- ----------------------------
-- Table structure for giveALike
-- ----------------------------
DROP TABLE IF EXISTS `giveALike`;
CREATE TABLE `giveALike` (
`id` int NOT NULL AUTO_INCREMENT COMMENT '编号',
`user_id` int NULL DEFAULT NULL COMMENT '用户编号',
`article_id` int NULL DEFAULT NULL COMMENT '文章编号',
`is_like` int NULL DEFAULT NULL COMMENT '是否点赞(0表示未点赞,1表示点赞)',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 935456769 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;-- ----------------------------
-- Records of giveALike
-- ------------------------------ ----------------------------
-- Table structure for user
-- ----------------------------
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
`id` int NOT NULL AUTO_INCREMENT COMMENT '编号',
`username` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '用户名',
`password` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '密码',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 2 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;-- ----------------------------
-- Records of user
-- ----------------------------
INSERT INTO `user` VALUES (1, '11', '11');SET FOREIGN_KEY_CHECKS = 1;
项目结构
yml配置
server: port: 5000 spring: application: name: service-user datasource: url: jdbc:mysql://192.168.157.134:3306/giveALike?serverTimezone=GMT%2B8&characterEncoding=utf-8&useSSL=false driver-class-name: com.mysql.cj.jdbc.Driver username: root password: root
entity下的三个实体类
Article:
@Data public class Article { @TableId(value = "id", type = IdType.AUTO) private Integer id;//编号 private String content;//内容 }
GiveALike:
@Data @TableName("giveALike") public class GiveALike { @TableId(value = "id", type = IdType.AUTO) private Integer id; private Integer articleId;//文章编号 private Integer userId;//用户编号 private int isLike;//是否点赞(0表示未点赞,1表示点赞) }
User:
@Data public class User { @TableId(value = "id", type = IdType.AUTO) private Integer id;//用户id private String username;//用户名 private String password;//密码 }
mapper
ArticleMapper:
@Mapper public interface ArticleMapper extends BaseMapper<Article> { }
GiveALikeMapper:
@Mapper public interface GiveALikeMapper extends BaseMapper<GiveALike> { }
UserMapper:
@Mapper public interface UserMapper extends BaseMapper<User> { }
controller
@Slf4j @CrossOrigin @RestController @RequestMapping("/giveALike") public class GiveALikeController { @Resource private UserMapper userMapper; @Resource private ArticleMapper articleMapper; @Resource private GiveALikeMapper giveALikeMapper; //登录 @PostMapping("/login") public User login(@RequestBody User user) { QueryWrapper<User> userQueryWrapper = new QueryWrapper<>(); userQueryWrapper.eq("username", user.getUsername()); User vo = userMapper.selectOne(userQueryWrapper); if (vo != null && Objects.equals(vo.getPassword(), user.getPassword())) { return vo; } else { return null; } } //获取所有文章数据 @GetMapping("/getList") public List<Article> getList() { return articleMapper.selectList(null); } //获取当前用户点赞表的数据 @GetMapping("/getUserLike/{id}") public List<GiveALike> getUserLike(@PathVariable int id) { QueryWrapper<GiveALike> wrapper = new QueryWrapper<>(); wrapper.eq("user_id", id); return giveALikeMapper.selectList(wrapper); } //点赞 @PostMapping("/saveUserLike") public GiveALike saveUserLike(@RequestBody GiveALike giveALike) { QueryWrapper<GiveALike> wrapper = new QueryWrapper<>(); wrapper.eq("article_id", giveALike.getArticleId()).eq("user_id", giveALike.getUserId()); GiveALike vo = giveALikeMapper.selectOne(wrapper); if (vo != null) { if (vo.getIsLike() == 0) { vo.setIsLike(1); } else { vo.setIsLike(0); } giveALikeMapper.updateById(vo); return vo; } else { giveALike.setIsLike(1); giveALikeMapper.insert(giveALike); return giveALike; } } }
前端:
相关依赖
目录结构
main.ts页面
import { createApp } from 'vue' import ElementPlus from 'element-plus' import 'element-plus/dist/index.css' import App from './App.vue' import router from "./router"; createApp(App).use(router).use(ElementPlus).mount('#app')
App.vue页面
<template> <div id="app"> <router-view/> </div> </template> <style> </style>
路由router
import { createRouter,createWebHistory } from "vue-router"; const routes = [ { path:"/home", name:'首页', component:()=>import('../page/home.vue') }, { path:"/", name:'登录', component:()=>import('../page/login.vue') }, ] const router = createRouter({ history:createWebHistory(), routes:routes, }) export default router
登录页面login
<template> <div class="main"> <div class="main_username"> <input v-model="user.username" class="username" type="text" placeholder="请输入用户名"> </div> <div class="main_password"> <input v-model="user.password" class="password" type="password" placeholder="请输入密码"> </div> <el-button @click="login" type="primary" class="main_login">登录</el-button> </div> </template> <script setup lang="ts"> import {ElMessage} from 'element-plus' import {reactive} from "vue"; import axios from "axios"; import router from "../router"; interface User { username: string, password: string } //登录所需的信息 const user = reactive<User>({ username: '11', password: '11' }) //登录 const login = () => { axios.post("http://localhost:5000/giveALike/login", user).then((res) => { if (res.data != '') { ElMessage({ message: '登录成功', type: 'success', }) //跳转页面 router.push("/home") //将用户信息存到session window.sessionStorage.setItem("user", JSON.stringify(res.data)) } else { console.log(66) ElMessage.error('登录失败') } }) } </script> <style lang="less" scoped> .main { .main_username { margin-bottom: 10px; input { font-size: 30px; } } .main_password { input { font-size: 30px; } } .main_login { font-size: 30px; margin-top: 10px; } } </style>
home页面
<template> <div v-loading="loading"> <div v-for="item in data.articleList" :key="item.id"> <div class="item"> <div class="item_id">编号:{{ item.id }}</div> <div class="item_content">内容:{{ item.content }}</div> <div>{{ item }}</div> <img v-if="item.isLike===0" @click="handleLike(item.id)" src="../assets/未点赞.png" class="item_img" alt="图片"> <img v-else @click="handleLike(item.id)" src="../assets/点赞.png" class="item_img" alt="图片"> </div> </div> </div> </template> <script setup lang="ts"> import axios from "axios"; import {reactive, ref} from "vue"; import {ElMessage} from "element-plus"; //加载特效 const loading = ref<boolean>(true) const data = reactive({ articleList: [] as Article[],//所有内容列表 userLikeList: [] as any[]//当前用户点赞表的数据 }) interface giveALike { articleId: number, userId: number } interface Article { id: number, content: string, isLike?: number } //点赞所需的参数 const giveALikeParam = reactive<giveALike>({ articleId: 0,//文章编号 userId: 0//用户编号 }) //获取所有内容 const getList = () => { axios.get("http://localhost:5000/giveALike/getList").then((res) => { data.articleList = res.data }) } //点赞 const handleLike = (row: number) => { //从session中获取用户信息 const user = JSON.parse(window.sessionStorage.getItem("user") || '') //设置用户编号 giveALikeParam.userId = user.id //设置文章编号 giveALikeParam.articleId = row axios.post("http://localhost:5000/giveALike/saveUserLike", giveALikeParam).then((res) => { data.articleList[row - 1].isLike = data.articleList[row - 1].isLike === 1 ? 0 : 1; if (res.data.isLike == 1) { ElMessage({ message: '点赞成功', type: 'success', }) } else { ElMessage({ message: '取消点赞', type: 'warning', }) } }) } //获取当前用户点赞表的数据 const getLikeList = () => { //从session中获取用户信息 const user = JSON.parse(window.sessionStorage.getItem("user") || '') axios.get("http://localhost:5000/giveALike/getUserLike/" + user.id).then((res) => { data.userLikeList = res.data //懒加载 setTimeout(()=>{ userIsLike() loading.value = false },1000) }) } //查询用户是否点赞 const userIsLike = () => { if(data.userLikeList.length!=0){ for (let i = 0; i < data.articleList.length; i++) { for (let j = 0; j < data.userLikeList.length; j++) { if (data.articleList[i].id === data.userLikeList[j].articleId) { data.articleList[i].isLike = data.userLikeList[j].isLike break; } else { data.articleList[i].isLike = 0 } } } }else{ for (let i = 0; i < data.articleList.length; i++) { data.articleList[i].isLike = 0 } } } getList() getLikeList() </script> <style lang="less" scoped> .item { display: flex; .item_id { margin-right: 10px; } .item_content { width: 100px; } .item_img { width: 100px; height: 100px; cursor: pointer; } } </style>
上述代码如有问题,欢迎提出来,博主看到了会第一时间解决