springboot3+react18+ts实现一个点赞功能

前端:vite+react18+ts+antd

后端:springboot3.0.6+mybatisplus

最终效果大致如下:

springboot3+react18+ts实现一个点赞功能_第1张图片

后端:

引入pom依赖


        
            org.springframework.boot
            spring-boot-starter-web
        

        
            mysql
            mysql-connector-java
            8.0.31
        

        
            com.baomidou
            mybatis-plus-boot-starter
            3.5.3.1
        

        
            org.projectlombok
            lombok
            true
        

        
            org.springframework.boot
            spring-boot-starter-test
            test
        

运行sql

/*
 Navicat Premium Data Transfer

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

 Target Server Type    : MySQL
 Target Server Version : 80027 (8.0.27)
 File Encoding         : 65001

 Date: 01/05/2023 20:20:15
*/

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 = 2 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;

项目结构

springboot3+react18+ts实现一个点赞功能_第2张图片

yml配置,数据库改成你自己的数据库

server:
  port: 5000

spring:
  application:
    name: give-a-like

  datasource:
    url: jdbc:mysql://192.168.157.134:3306/giveALike?serverTimezone=GMT%2B8&characterEncoding=utf-8
    driver-class-name: com.mysql.cj.jdbc.Driver
    username: root
    password: root

mybatis-plus:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

entity下的三个实体类

Article:

@Data
public class Article {
    @TableId(value = "id", type = IdType.AUTO)
    private Integer id;//编号
    private String content;//内容
    @TableField(exist = false)
    private Integer isLike;
}

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
{ }

GiveALikeMapper:

@Mapper
public interface GiveALikeMapper extends BaseMapper {
}

UserMapper: 

@Mapper
public interface UserMapper extends BaseMapper {
}

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 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;
        }
    }

    //获取所有文章数据
    //TODO 优化建议:使用分页,减少并发
    @GetMapping("/getList")
    public List
getList() { List
articles = articleMapper.selectList(null); List
list = new ArrayList<>(); for (Article item : articles) { QueryWrapper wrapper = new QueryWrapper<>(); wrapper.eq("article_id", item.getId()); GiveALike giveALike = giveALikeMapper.selectOne(wrapper); if (giveALike == null || giveALike.getIsLike() == 0) { item.setIsLike(0); } else { item.setIsLike(1); } list.add(item); } return list; } //点赞 @PostMapping("/saveUserLike") @Transactional public GiveALike saveUserLike(@RequestBody GiveALike giveALike) { QueryWrapper 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; } } }

前端:

相关依赖

springboot3+react18+ts实现一个点赞功能_第3张图片

目录结构

springboot3+react18+ts实现一个点赞功能_第4张图片

 main.tsx页面

import React, {Suspense} from 'react'
import ReactDOM from 'react-dom/client'
import {RouterProvider} from 'react-router-dom'
import router from './router'

ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render(
    
        
            
        
    
)

App.tsx页面本次没有使用到,无影响

路由router.ts

import React, {lazy} from "react";
import {createBrowserRouter} from "react-router-dom";
import type {RouteObject} from "react-router-dom";

const Home = lazy(() => import('../view/home.tsx'))
const Login = lazy(() => import('../view/login.tsx'))


declare module 'react-router' {
    interface IndexRouteObject {
        meta?: {
            menu?: boolean
            title?: string
            auth?: boolean
        }
    }

    interface NonIndexRouteObject {
        meta?: {
            menu?: boolean
            title?: string
            auth?: boolean
        }
    }
}

export const routes: RouteObject[] = [
    {
        path: '/home',
        element: React.createElement(Home),
        meta: {
            menu: true,
            title: '首页',
            auth: true
        }
    },
    {
        path: '/',
        element: React.createElement(Login),
        meta: {
            menu: true,
            title: '登录',
            auth: false
        }
    }
];

const router = createBrowserRouter(routes)

export default router;

 登录页面login.tsx

import React, {useState} from "react";
import {useNavigate} from 'react-router-dom'
import axios from "axios";

const Login = () => {
    const navigate = useNavigate()

    const [username, setUsername] = useState("");
    const [password, setPassword] = useState("");

    //登录
    const handleSubmit = async (event: React.FormEvent) => {
        event.preventDefault();
        try {
            const response = await axios.post("http://localhost:5000/giveALike/login", {
                username,
                password,
            });
            if (response.status == 200) {
                //登录成功,跳转首页
                navigate('/home');
                //将用户信息存到session
                window.sessionStorage.setItem("user", JSON.stringify(response.data))
            } else {
                alert(response.data.message)
            }
        } catch (error) { /* empty */
        }
    };

    return (
        
setUsername(event.target.value)} />
setPassword(event.target.value)} />
); }; export default Login;

home.tsx页面

import axios from "axios";
import {useEffect, useState} from "react";
import {message} from "antd";

interface GiveALike {
    articleId: number,
    userId: number
}

interface Article {
    id: number,
    content: string,
    isLike?: number
}

const Home = () => {
    const [articleList, setArticleList] = useState([]);
    //点赞所需的参数
    const [giveALike] = useState({
        articleId: 0,//文章编号
        userId: 0//用户编号
    });

    //获取所有内容
    const getList = async () => {
        const response = await axios.get("http://localhost:5000/giveALike/getList")
        setArticleList(response.data)
    }

    //点赞
    const handleLike = (row: number) => {
        //从session中获取用户信息
        const user = JSON.parse(window.sessionStorage.getItem("user") || '')
        //设置用户编号
        giveALike.userId = user.id
        //设置文章编号
        giveALike.articleId = row
        axios.post("http://localhost:5000/giveALike/saveUserLike", giveALike).then((res) => {
            getList()
            if (res.data.isLike == 1) {
                message.success('点赞成功');
            } else {
                message.warning('取消点赞');
            }
        })
    }

    //vite方式获取图片
    const getImageUrl = (name: string) => {
        return new URL(`../assets/${name}`, import.meta.url).href
    }

    useEffect(() => {
        getList()
    }, []);

    return (
        <>
            
{articleList.map((item: Article) => (
编号:{item.id}
内容:{item.content}
{ item.isLike == 0 ? { handleLike(item.id) }} src={getImageUrl("未点赞.png")} style={{width: "50px", height: "50px", cursor: "pointer"}} alt="图片"/> : { handleLike(item.id) }} src={getImageUrl("点赞.png")} style={{width: "50px", height: "50px", cursor: "pointer"}} alt="图片"/> }
))}
); } export default Home;

 Gitee仓库地址:Gitee

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

springboot+vue3+ts版

你可能感兴趣的:(springboot3,ts,react18)