代码编织梦想

前端: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 Transfer

 Source Server         : MyDemo
 Source Server Type    : MySQL
 Source Server Version : 80027
 Source Host           : 192.168.157.134:3306
 Source Schema         : giveALike

 Target Server Type    : MySQL
 Target Server Version : 80027
 File Encoding         : 65001

 Date: 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>

 上述代码如有问题,欢迎提出来,博主看到了会第一时间解决

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/crazy1013/article/details/127974796

MySql+SpringBoot+Vue 搭建一个完整的前后端分离项目-爱代码爱编程

文章目录 完整项目搭建流程数据库1. **连接 admin**2. **新建数据库**3. **为这个数据库,专门建一个用户**4. **为这个用户,授予对应数据库的全部权限**5. **对当前用户,建立连接**后端1. 新建 SpringBoot 项目2. 更改启动类位置3. IDEA 数据库配置4. 配置 MyBatis5. MVC 包建立5.

新增电子书表单及编辑功能-爱代码爱编程

文章目录 新增电子书表单完成电子书编辑功能新增并测试后端接口前端调用接口 新增电子书表单 主要是对admin-book.vue进行修改。 点击编辑按钮,弹出对话框,这里使用Antd的Modal组件<template> <a-layout> <a-layout-content :sty

Reids延时队列使用的思考-爱代码爱编程

我们平时习惯于使用 Rabbitmq 和 Kafka 作为消息队列中间件,来给应用程序之间增加异步消息传递功能。这两个中间件都是专业的消息队列中间件,特性之多超出了大多数人的理解能力。 对于那些只有一组消费者的消息队列,使用 Redis 就可以非常轻松的搞定。Redis 的消息队列不是专业的消息队列,它没有非常多的高级特性,没有 ack 保证,如果

谷粒学院(十一)课程最终发布 | 课程列表 | 阿里云视频点播服务 | 小节实现视频上传-爱代码爱编程

一、课程最终发布信息展示 – 后端 1、实体类—用于封装页面显示的数据 @ApiModel(value = "课程最终发布") @Data public class CoursePublishVo implements Serializable { private static final long serialVersionUID = 1L;

基于springboot+vue3知识库系统开发_m0_51764537的博客-爱代码爱编程

知识库系统开发实战 页面展示 1 首页 2 登录页面 登录成功后首页面: 3 用户管理页面 编辑: 4 电子书管理页面 文档管理: 编辑: 5 分类管理页面 6 关于我页面 退出登录:

springboot+臻绿原客绿色食品商城 毕业设计-附源码161928_weixin_bysj1987的博客-爱代码爱编程

绿色食品商城网站管理系统的设计与实现 摘  要  随着人们生活水平、生活质量的提高和保健意识的不断增强,商品已经越来越受到广大消费者的青睐,绿色消费逐渐成为消费潮流消费的亮点和热点。在国家政策利好、市场需求不断扩大的环境下,我国生态商品发展迅猛,除了在传统的线下市场一片繁荣,生态商品在移动电商也渐有抬头之势。 本系统主要是提供给用户一个购

springboot+mybatis+vue3.0+ts+elementuiplus学生管理系统_无敌代码终结者的博客-爱代码爱编程

一、系统登录页面 二、修改密码页面 三、首页 三、学生信息列表 四、编辑学生信息页面 五、个人信息页面 六、页面丢失页面 七、前端代码目录 八、前端代码部分页面 <template> &l

springboot如何避免sql注入漏洞呢?_qq_25073223的博客-爱代码爱编程

转自: SpringBoot如何避免SQL注入漏洞呢? 下文笔者讲述SpringBoot避免SQL注入漏洞的方法分享,如下所示 SQL盲注,SQL注入简介 SQL注入的风险: 数据库中的数据被任意查看,修改,删除 SQL注入的原因: 未对用户输入进行正确的验证 SQL注入如何避免 对危险字符进行过滤或sql参数化

springboot使用线程池异步化解耦通知_wsasyncservice-爱代码爱编程

SpringBoot使用线程池异步化解耦通知 1、前言 为什么我们需要使用WebSocket通信连接?在一般的HTTP协议中,当前端页面向后端发送一个请求后,会建立一条由客户端发起的通信连接,只能由客户端发起连接请求而服

[java] spring boot auto configure(spring boot自动装配)的原理_java自动装配-爱代码爱编程

文章目录 前言版本信息前置知识Spring框架如何收集BeanDefinition信息? Spring Boot 自动装配的原理Spring框架的Context核心模块提供了这些功能@EnableAuto