前端: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>
上述代码如有问题,欢迎提出来,博主看到了会第一时间解决



















