【后端已完成,前端更新ing】uniapp+springboot实现个人备忘录系统【前后端分离】

目录

(1)项目可行性分析

(一)技术可行性:

(二)经济可行性:

(三)社会可行性:

(2)需求描述

功能模块图

用例图:

(3)界面原型

1.登录:

2.注册:

3.我的: 

4.分类: 

5.记录: 

6.主页: 

(4)数据库设计

(1)User表:

(2)Notes表:

(3)Type表:

E-r图如下:

数据库的sql文件:

(5)后端工程

common包: 

R.java

config包: 

CorsConfig.java

domain包:

Notes.java

Type.java

User.java

utils包:

PathUtils.java

controller包:

NotesController.java

TypeController.java

UploadController.java

 UserController.java

 service包:

NotesService

OssUploadService

TypeService

UserService

Impl包:

NotesServiceImpl.java

OssUploadServiceImpl.java

TypeServiceImpl.java

UserServiceImpl.java

(6)前端工程


接下来我们使用uniapp+springboot实现一个简单的前后端分离的小项目----个人备忘录系统,适合初学者学习,以下是详细步骤:

(1)项目可行性分析

(一)技术可行性:

1.uniapp是一个基于Vue.js框架的跨平台开发工具,可以在多个平台上实现一次开发多端运行。它提供了丰富的组件和插件,使得开发变得更加高效。

2.uniapp支持多个主流的移动端平台,如iOS和Android,以及微信小程序、H5等。这意味着你可以通过uniapp开发一个备忘录系统,并在多个平台上发布和使用。

3.Vue.js作为uniapp的底层框架,拥有活跃的开发社区和丰富的生态系统,可以提供大量的资源和支持。

(二)经济可行性:

1.uniapp的开发成本相对较低,因为它使用了一套代码可以覆盖多个平台的开发方式,减少了重复的工作量和开发时间。

2.由于uniapp支持多个主流平台,你可以在不同的平台上发布你的备忘录系统,扩大用户群体,增加潜在的收入来源。

3.uniapp的跨平台特性可以降低维护成本,因为你只需要维护一套代码,而不是针对每个平台都进行独立的开发和维护。

(三)社会可行性:

1.备忘录系统是一个常见且实用的应用,它可以帮助个人记录重要事项、提醒任务等。这种类型的应用在社会中有广泛的需求。

2.通过使用uniapp开发备忘录系统,你可以满足不同用户使用不同平台的需求,提高用户体验和满意度。

3.在移动互联网时代,人们越来越依赖手机和移动应用程序进行工作和生活管理。开发备忘录系统可以满足人们随时随地记录和查看备忘录的需求,符合社会的发展趋势。

(2)需求描述

个人备忘录系统主要有登录、注册、查看所有备忘录、创建新的备忘录、删除备忘录、修改备忘录、根据分类查询已完成或未完成的备忘录。

功能模块图

用例图:

(3)界面原型

主要界面如下:

1.登录:

2.注册:

3.我的: 

4.分类: 

5.记录: 

6.主页: 

(4)数据库设计

数据库主要有三个表:

(1)User表:

表名

类型

长度

注释

id

int

255

id

username

varchar

255

用户名

password

varchar

255

密码

avatar

varchar

255

头像

(2)Notes表:

表名

类型

长度

注释

id

int

255

id

rid

int

255

用户id

detail

varchar

255

内容

time

datetime

255

截止时间

type

int

255

类型

finish

int

255

任务是否完成

(3)Type表:

表名

类型

长度

注释

typeid

int

255

主键

type

varchar

255

是什么类型

E-r图如下:

数据库的sql文件:
/*
 Navicat Premium Data Transfer

 Source Server         : mySQL
 Source Server Type    : MySQL
 Source Server Version : 80019
 Source Host           : localhost:3305
 Source Schema         : memo

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

 Date: 25/12/2023 11:06:46
*/

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
-- Table structure for notes
-- ----------------------------
DROP TABLE IF EXISTS `notes`;
CREATE TABLE `notes`  (
  `id` int(0) NOT NULL AUTO_INCREMENT COMMENT 'note表的id',
  `rid` int(0) NOT NULL COMMENT '这个笔记是哪个人的',
  `detail` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL COMMENT '笔记的内容',
  `photo` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '用户上传的图片,null或者0表示无',
  `time` datetime(0) NOT NULL COMMENT '笔记的创建时间',
  `type` int(0) NOT NULL COMMENT '笔记的类型',
  `finish` int(0) NOT NULL COMMENT '任务是否完成',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 57 CHARACTER SET = utf8 COLLATE = utf8_bin ROW_FORMAT = Dynamic;

-- ----------------------------
-- Records of notes
-- ----------------------------
INSERT INTO `notes` VALUES (31, 13, '软件设计师考试', 'http://s6422okdy.hn-bkt.clouddn.com/2023/12/23/e7bbeaecf4984a72af03d6d623a4f96c.jpg', '2023-11-04 00:04:28', 2, 1);
INSERT INTO `notes` VALUES (32, 13, '国奖答辩', NULL, '2023-10-16 20:26:27', 2, 1);
INSERT INTO `notes` VALUES (33, 13, 'hehang-blog数据库项目', NULL, '2024-01-07 20:26:56', 2, 1);
INSERT INTO `notes` VALUES (34, 13, '数据库详细设计报告', NULL, '2023-11-08 20:27:24', 2, 1);
INSERT INTO `notes` VALUES (35, 13, '数据库课设验收', NULL, '2023-11-22 20:28:02', 2, 1);
INSERT INTO `notes` VALUES (36, 13, '计算机组成原理期中考试', NULL, '2023-11-24 20:28:44', 2, 1);
INSERT INTO `notes` VALUES (37, 13, '计算机能力挑战赛C语言', NULL, '2023-11-25 08:00:00', 2, 1);
INSERT INTO `notes` VALUES (38, 13, '学生代表大会', '0', '2023-12-07 13:15:00', 3, 1);
INSERT INTO `notes` VALUES (39, 13, '闪聚支付springclound项目', NULL, '2023-12-19 18:30:21', 2, 1);
INSERT INTO `notes` VALUES (40, 13, '英语四级考试', NULL, '2023-12-16 09:00:00', 2, 1);
INSERT INTO `notes` VALUES (41, 13, '数据库课设详细设计文档', '0', '2024-01-07 23:59:59', 2, 0);
INSERT INTO `notes` VALUES (43, 13, '完成代码细节的修改', NULL, '2023-12-18 12:00:00', 2, 1);
INSERT INTO `notes` VALUES (44, 14, '记得吃药', '0', '2023-12-24 14:57:57', 8, 0);
INSERT INTO `notes` VALUES (45, 14, '写完uniapp期末课设的报告', '', '2023-12-24 14:08:58', 2, 1);
INSERT INTO `notes` VALUES (47, 13, '计算机能力挑战赛决赛\n地点:武汉纺织大学阳光校区', 'http://s6422okdy.hn-bkt.clouddn.com/2023/12/23/daa53bce645146d08531649be4308db4.jpg', '2023-12-09 09:00:00', 2, 1);

-- ----------------------------
-- Table structure for type
-- ----------------------------
DROP TABLE IF EXISTS `type`;
CREATE TABLE `type`  (
  `typeid` int(0) NOT NULL COMMENT '主键',
  `type` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL COMMENT '是什么类型',
  PRIMARY KEY (`typeid`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_bin ROW_FORMAT = Dynamic;

-- ----------------------------
-- Records of type
-- ----------------------------
INSERT INTO `type` VALUES (1, '日常');
INSERT INTO `type` VALUES (2, '学习');
INSERT INTO `type` VALUES (3, '工作');
INSERT INTO `type` VALUES (4, '娱乐');
INSERT INTO `type` VALUES (5, '社交');
INSERT INTO `type` VALUES (6, '家庭');
INSERT INTO `type` VALUES (7, '个人');
INSERT INTO `type` VALUES (8, '健康');
INSERT INTO `type` VALUES (9, '财务');

-- ----------------------------
-- Table structure for user
-- ----------------------------
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user`  (
  `id` int(0) NOT NULL AUTO_INCREMENT COMMENT '用户的id',
  `username` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL COMMENT '用户名字',
  `password` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL COMMENT '用户密码',
  `avatar` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL COMMENT '用户的头像',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 16 CHARACTER SET = utf8 COLLATE = utf8_bin ROW_FORMAT = Dynamic;

-- ----------------------------
-- Records of user
-- ----------------------------
INSERT INTO `user` VALUES (13, 'hehang', '123456', 'https://img2.baidu.com/it/u=3841326637,2519425910&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=501');
INSERT INTO `user` VALUES (14, 'abcd', '123456', 'https://pic2.zhimg.com/v2-fc348d5e926116782149d2151dc09834.jpg');
INSERT INTO `user` VALUES (15, 'mynote', '123456', 'https://img2.baidu.com/it/u=3841326637,2519425910&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=501');
INSERT INTO `user` VALUES (16, '1234', '123456', 'https://img2.baidu.com/it/u=3841326637,2519425910&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=501');

SET FOREIGN_KEY_CHECKS = 1;

(5)后端工程

首先打开IDEA,选择创建Spring Initializr,按照以下配置,jdk版本无法选择jdk1.8,先不管,进去以后可以改,具体操作可以看我的另一篇相关的博客

配置spring版本,先选择3.2.0,进入项目后再通过pom文件修改

进入项目后修改pom.xml文件为如下配置,我们在pom中手动修改了jdk版本为1.8,spring为2.7.8,这样兼容性比较好,修改后记得刷新maven

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.8</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>Memo-hehang</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>hehang</name>
    <description>memo</description>
    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.3.0</version>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.3.0</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>com.mysql</groupId>
            <artifactId>mysql-connector-j</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.4.2</version>
        </dependency>

        <!--七牛云OOS-->
        <dependency>
            <groupId>com.qiniu</groupId>
            <artifactId>qiniu-java-sdk</artifactId>
            <version>[7.13.0, 7.13.99]</version>
        </dependency>
        <dependency>
            <groupId>com.google.code.gson</groupId>
            <artifactId>gson</artifactId>
            <version>2.10.1</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>9</source>
                    <target>9</target>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>


然后我们修改resources文件夹下的application.yml,数据库连接修改成你自己的,七牛云的使用可以看我上一篇博客

server:
  port: 2023

spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3305/memo?characterEncoding=utf-8&serverTimezone=Asia/Shanghai
    username: root
    password: 123456

mybatis-plus:
  global-config:
    db-config:
      id-type: auto
#  configuration:
#    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
# 打开七牛云,找到密钥管理,把相关信息填写到下面3行
myoss:
  accessKey: yourAK
  secretKey: yourSK
  bucket: yourbucket



接下来在项目下创建如下几个包:

common包: 
R.java

在common文件下创建 R.java 类,主要用于封装返回给前端的数据:

package com.example.memohehang.common;

import lombok.Data;

import java.io.Serializable;

/**
 * 统一返回类型
 */
@Data
public class R implements Serializable
{

    private int code; // 200是正常,非200表示异常
    private String msg;
    private Object data;

    public static R success(Object data)
    {
        return success(200, "操作成功", data);
    }

    public static R success(int code, String msg, Object data)
    {
        R r = new R();
        r.setCode(code);
        r.setMsg(msg);
        r.setData(data);
        return r;
    }

    public static R error(int i, String msg)
    {
        return error(400, msg, null);
    }

    public static R error(String msg, Object data)
    {
        return error(400, msg, data);
    }

    public static R error(int code, String msg, Object data)
    {
        R r = new R();
        r.setCode(code);
        r.setMsg(msg);
        r.setData(data);
        return r;
    }

}
config包: 
CorsConfig.java

在config包下创建 CorsConfig.java 类,用于解决前端跨域问题,在config.AllowedOrigin中填写你自己的前端端口,一般为8080,或者填 * ,允许所有

package com.example.memohehang.config;


import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.filter.CorsFilter;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.cors.CorsConfiguration;

//解决前端跨域问题
@Configuration
public class CorsConfig {
    @Bean
    public CorsFilter corsFilter()
    {
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        CorsConfiguration config = new CorsConfiguration();
        config.addAllowedOrigin("http://localhost:8080");
        config.addAllowedHeader("*");
        config.addAllowedMethod("*");
        config.setAllowCredentials(true);
        source.registerCorsConfiguration("/**", config);
        return new CorsFilter(source);
    }
}
domain包:

对应数据库的实体类

Notes.java

这里我们利用jsonformat注解进行时间格式化

package com.example.memohehang.domain;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.Date;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Notes {
    @TableId(value = "id", type = IdType.AUTO)
    private Integer id;
    private Integer rid;
    // 内容
    private String detail;
    // 截止时间
    @JsonFormat(locale = "zh", timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
    private Date time;
    // 类型
    private Integer type;

    //图片
    private String photo;
    // 是否完成 0表示还没有 1表示完成了
    private Integer finish;


}
Type.java
package com.example.memohehang.domain;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Type
{
    private Integer typeid;
    private String type;
}
User.java
package com.example.memohehang.domain;

import lombok.AllArgsConstructor;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User
{
    //主键自增
    @TableId(value = "id", type = IdType.AUTO)
    private Integer id;
    private String username;
    private String password;
    // 头像
    private String avatar;
}
utils包:
PathUtils.java

这是对上传的文件进行重命名,在后面的七牛云相关的service中会用到

package com.example.memohehang.utils;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.UUID;


//对原始文件名进行修改文件名,并修改存放目录
public class PathUtils
{

    public static String generateFilePath(String fileName)
    {
        //根据日期生成路径
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd/");
        String datePath = sdf.format(new Date());
        //uuid作为文件名
        String uuid = UUID.randomUUID().toString().replaceAll("-", "");
        //后缀和文件后缀一致
        int index = fileName.lastIndexOf(".");
        // test.jpg -> .jpg
        String fileType = fileName.substring(index);
        return new StringBuilder().append(datePath).append(uuid).append(fileType).toString();
    }
}

 我一般写代码的顺序为:Controller----service----serviceImpl----mapper,在方法学一般先写调用体,根据调用写对应的实现,下面我们按照这个顺序来写:

controller包:
NotesController.java
package com.example.memohehang.controller;

import com.example.memohehang.common.R;
import com.example.memohehang.domain.Notes;
import com.example.memohehang.service.NotesService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;


@Controller
@RequestMapping("/note")
public class NotesController {
    @Autowired
    private NotesService notesService;


    // 添加
    @RequestMapping("/save")
    @ResponseBody
    public R save(@RequestBody Notes notes)
    {
        System.out.println("添加备忘录:" + notes);
        return notesService.addNote(notes);
    }


    // 根据noteid查询对应的note
    @RequestMapping ("/selectByNote/{noteid}")
    @ResponseBody
    public R selectByNote(@PathVariable("noteid") Integer noteid)
    {

        return notesService.selectByNote(noteid);
    }

    // 查询 只显示用户自己的
    @RequestMapping ("/selectAllByUserID/{userid}")
    @ResponseBody
    public R selectAllById(@PathVariable("userid") Integer userid,@RequestParam(defaultValue = "1") Integer currentPage)
    {
        return notesService.selectAllById(userid,currentPage);
    }

    // 查询最近即将截止的未完成的备忘录的时间差
    @RequestMapping ("/selectTime/{userid}")
    @ResponseBody
    public R selectcutDownTime(@PathVariable("userid") Integer userid)
    {
        return notesService.selectcutDownTime(userid);
    }



    // 分类查询
    @RequestMapping ("/selectByType/{userid}/{type}/{isFinish}")
    @ResponseBody
    public R selectByType(@PathVariable("userid") Integer userid, @PathVariable("type") Integer type,@PathVariable("isFinish") Integer isFinish,@RequestParam(defaultValue = "1") Integer currentPage)
    {

        return notesService.selectByType(userid,type,isFinish,currentPage);

    }


    // 修改
    @RequestMapping("/update")
    @ResponseBody
    public R update(@RequestBody Notes notes)
    {
        return notesService.update(notes);
    }

    // 删除
    @DeleteMapping("/delete/{id}")
    @ResponseBody
    public R delete(@PathVariable("id") Integer id)
    {
        return notesService.delete(id);
    }



}


TypeController.java
package com.example.memohehang.controller;

import com.example.memohehang.common.R;
import com.example.memohehang.service.TypeService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;


@Controller
@RequestMapping("/type")
public class TypeController
{
    @Autowired
    private TypeService typeService;

    // 获取编号与类型的映射表
    @ResponseBody
    @GetMapping("/getMapping")
    public R typeMapping()
    {
        return typeService.typeMapping();
    }

}


UploadController.java
package com.example.memohehang.controller;


import com.example.memohehang.common.R;
import com.example.memohehang.service.OssUploadService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

@RestController
public class UploadController
{
    @Autowired
    private OssUploadService ossUploadService;

    @PostMapping("/upload")
    public R uploadImg(MultipartFile img)
    {

        return ossUploadService.uploadImg(img);
    }
}
 UserController.java
package com.example.memohehang.controller;

import com.example.memohehang.common.R;
import com.example.memohehang.domain.User;
import com.example.memohehang.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;


@RestController
@RequestMapping("/user")
public class UserController {


    @Autowired
    private UserService userService;

    // 登录功能
    @RequestMapping(value = "/login", method = RequestMethod.POST)
    public R login(@RequestBody User user)
    {
        return userService.login(user);

    }

    // 注册功能
    @RequestMapping(value = "/register", method = RequestMethod.POST)
    public R register(@RequestBody User user)
    {
        return userService.register(user);
    }

    // 根据用户id查询
    @RequestMapping ("/selectUserById/{userid}")
    @ResponseBody
    public R selectUserById(@PathVariable("userid") Integer userid)
    {
        return userService.selectUserById(userid);
    }

}



我们用mybatisplus自带的查询函数即可完成所有的CRUD,因此我们不需要写SQL语句

 service包:
NotesService
package com.example.memohehang.service;



import com.baomidou.mybatisplus.extension.service.IService;
import com.example.memohehang.common.R;
import com.example.memohehang.domain.Notes;
import com.example.memohehang.domain.User;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;

public interface NotesService extends IService<Notes>
{
    /**
     * 添加备忘录
     * @param notes
     * @return
     */
    public R addNote(Notes notes);

    /**
     * 根据noteid查询note
     * @param noteid
     * @return
     */
    public R selectByNote(Integer noteid);

    /**
     * 查询 只显示用户自己的
     * @param userid
     * @param currentPage
     * @return
     */
    public R selectAllById(Integer userid,Integer currentPage);

    /**
     * 查询最近即将截止的未完成的备忘录的时间差
     * @param userid
     * @return
     */
    public R selectcutDownTime(Integer userid);

    /**
     * 分类查询
     * @param userid
     * @param type
     * @param isFinish
     * @param currentPage
     * @return
     */
    public R selectByType(Integer userid, Integer type,Integer isFinish,Integer currentPage);

    /**
     * 修改
     * @param notes
     * @return
     */
    public R update(Notes notes);

    /**
     * 删除
     * @param id
     * @return
     */
    public R delete(Integer id);
}


OssUploadService
package com.example.memohehang.service;

import com.example.memohehang.common.R;
import org.springframework.web.multipart.MultipartFile;

public interface OssUploadService {
    //图片上传到七牛云
    R uploadImg(MultipartFile img);
}
TypeService
package com.example.memohehang.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.example.memohehang.common.R;
import com.example.memohehang.domain.Type;


public interface TypeService extends IService<Type>
{
    /**
     * 获取所有类型
     * @return
     */
    public R typeMapping();
}


UserService
package com.example.memohehang.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.example.memohehang.common.R;
import com.example.memohehang.domain.User;



public interface UserService extends IService<User>
{
    /**
     * 登录
     * @param user
     * @return
     */
    public R login(User user);

    /**
     * 注册
     * @param user
     * @return
     */
    public R register(User user);

    /**
     * 根据id查询用户
     * @param userid
     * @return
     */
    public R selectUserById(Integer userid);
}


接下来在service包中创建Impl,注意第一个 “ I ” 是大写的 “ i ”,第二个是小写的 “ L ”

Impl包:
NotesServiceImpl.java
package com.example.memohehang.service.Impl;



import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.memohehang.common.R;
import com.example.memohehang.domain.Notes;
import com.example.memohehang.mapper.NotesMapper;
import com.example.memohehang.service.NotesService;
import org.springframework.stereotype.Service;

import java.time.Duration;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class NotesServiceImpl extends ServiceImpl<NotesMapper, Notes> implements NotesService
{
    private NotesMapper notesMapper;
    /**
     * 添加备忘录
     * @param notes
     * @return
     */
    @Override
    public R addNote(Notes notes)
    {
        boolean b = save(notes);//调用mybatis-plus
        if (b)
        {
            return R.success(200, "添加成功", null);
        }
        else
        {
            return R.error(405, "添加失败");
        }

    }

    /**
     * 根据noteid查询note
     * @param noteid
     * @return
     */
    @Override
    public R selectByNote(Integer noteid)
    {
        QueryWrapper<Notes> wrapper = new QueryWrapper<>();

        wrapper.eq("id", noteid);
        List<Notes> note =  list(wrapper);

        if (note == null)
        {
            return R.error(400,"查询失败");
        }
        else
        {
            return R.success(note.get(0));
        }
    }

    /**
     * 查询 只显示用户自己的
     * @param userid
     * @param currentPage
     * @return
     */
    @Override
    public R selectAllById(Integer userid, Integer currentPage)
    {
        Page page = new Page(currentPage, 20);
        // 查询条件 分页的基础上 再按照创建时间排序
        IPage pageData = page(page, new QueryWrapper<Notes>().orderByAsc("finish","time").eq("rid", userid));

        return R.success(pageData);
    }

    /**
     * 查询最近即将截止的未完成的备忘录的时间差
     * @param userid
     * @return
     */
    @Override
    public R selectcutDownTime(Integer userid)
    {
        QueryWrapper<Notes> wrapper = new QueryWrapper<>();
        wrapper.eq("rid", userid).orderByAsc("finish", "time");
        List<Notes> note = list(wrapper);

        // 处理查询结果
        if (note != null && !note.isEmpty())
        {
            Notes firstUnfinishedNote = null;
            for (Notes n : note)
            {
                if (n.getFinish() == 0)
                {
                    firstUnfinishedNote = n;
                    break;
                }
            }

            if (firstUnfinishedNote != null)
            {
                LocalDateTime currentTime = LocalDateTime.now();
                Date noteTime = firstUnfinishedNote.getTime();

                Instant instant = noteTime.toInstant();
                LocalDateTime noteLocalDateTime = instant.atZone(ZoneId.systemDefault()).toLocalDateTime();

                Duration duration = Duration.between(currentTime, noteLocalDateTime);
                long days = duration.toDays();
                long hours = duration.toHoursPart();
                long minutes = duration.toMinutesPart();
                long seconds = duration.toSecondsPart();

                // 构造返回结果
                Map<String, Object> resultMap = new HashMap<>();
                resultMap.put("days", days);
                resultMap.put("hours", hours);
                resultMap.put("minutes", minutes);
                resultMap.put("seconds", seconds);

                System.out.println(resultMap);
                // 返回结果
                return R.success(200, "duration", resultMap);
            }
            else
            {
                return R.error(405, "没有找到未完成的备忘录");
            }
        }
        else
        {
            return R.error(405, "没有找到备忘录");
        }
    }

    /**
     * 分类查询
     * @param userid
     * @param type
     * @param isFinish
     * @param currentPage
     * @return
     */
    @Override
    public R selectByType(Integer userid, Integer type, Integer isFinish, Integer currentPage)
    {
        Page page = new Page(currentPage, 20);

        IPage pageData = page(page, new QueryWrapper<Notes>().orderByAsc("time").eq("rid", userid).eq("finish", isFinish).eq("type", type));

        return R.success(pageData);
    }

    /**
     * 修改
     * @param notes
     * @return
     */
    @Override
    public R update(Notes notes)
    {
        System.out.println("开始更新");
        System.out.println(notes);
        boolean b = update(notes, new QueryWrapper<Notes>().eq("id", notes.getId()));
        if (b)
        {
            System.out.println("更新成功");
            return R.success(200, "更新成功", null);
        }
        System.out.println("更新失败");
        return R.error(405, "更新失败");
    }

    /**
     * 删除
     * @param id
     * @return
     */
    @Override
    public R delete(Integer id)
    {
        System.out.println("user delete..." + id);
        boolean b = removeById(id);
        if (b)
        {
            return R.success(200, "删除成功", null);
        }
        return R.error(405, "删除失败");
    }
}


OssUploadServiceImpl.java

注意这里需要修改外链回显链接

package com.example.memohehang.service.Impl;

import com.example.memohehang.common.R;
import com.example.memohehang.service.OssUploadService;
import com.example.memohehang.utils.PathUtils;
import com.google.gson.Gson;
import com.qiniu.common.QiniuException;
import com.qiniu.http.Response;

import com.qiniu.storage.Configuration;
import com.qiniu.storage.Region;
import com.qiniu.storage.UploadManager;
import com.qiniu.storage.model.DefaultPutRet;
import com.qiniu.util.Auth;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.InputStream;


@Service
@Data//为成员变量生成get和set方法
@ConfigurationProperties(prefix = "myoss")
//把文件上传到七牛云
public class OssUploadServiceImpl implements OssUploadService {

    @Override
    //MultipartFile是spring提供的接口
    public R uploadImg(MultipartFile img) {

        //获取原始文件名
        String originalFilename = img.getOriginalFilename();

        // 获取文件大小
        long fileSize = img.getSize();

        //PathUtils.generateFilePath(originalFilename)表示把原始文件名转换成指定文件名

        String filePath = PathUtils.generateFilePath(originalFilename);

        //下面用于调用的uploadOss方法返回的必须是String类型
        String url = uploadOss(img,filePath);
        System.out.println("外链地址:"+url);
        //把得到的外链地址返回给前端
        return R.success(200,"操作成功",url);
    }

    //----------------------------------上传文件到七牛云----------------------------------------

    //注意要从application.yml读取属性数据,下面的3个成员变量的名字必须对应application.yml的myoss属性的三个子属性名字
    private String accessKey;
    private String secretKey;
    private String bucket;

    //上传文件的具体代码。MultipartFile是spring提供的接口,作用是实现文件上传
    private String uploadOss(MultipartFile imgFile, String filePath){
        //构造一个带指定 Region 对象的配置类。你的七牛云OSS创建的是哪个区域的,那么就调用Region的什么方法即可
        Configuration cfg = new Configuration(Region.huanan());
        cfg.resumableUploadAPIVersion = Configuration.ResumableUploadAPIVersion.V2;// 指定分片上传版本
        UploadManager uploadManager = new UploadManager(cfg);

        //打开七牛云,把鼠标悬浮在右上角的个人头像,然后就会看到'密钥管理',点击进入就有你的密钥,把其中的AK和SK复制到下面两行
        //String accessKey = "_ibGP9wytjLCAZPqcFaWQNxbw7fMUvofSOvOFFR3";
        //String secretKey = "QSOAU-cv3sSDGNfVNPF6iXz-PsP5X9QTrjFI9zYw";
        //String bucket = "hehang-blog";
        //为避免上面3行暴露信息,我们会把信息写到application.yml里面,然后添加ConfigurationProperties注解、3个成员变量即可读取

        //文件名,如果写成null的话,就以文件内容的hash值作为文件名
        String key = filePath;

        try {

            //byte[] uploadBytes = "hello qiniu cloud".getBytes("utf-8");
            //ByteArrayInputStream byteInputStream=new ByteArrayInputStream(uploadBytes);

            //上面两行是官方写的(注释掉),下面那几行是我们写的
            //把前端传过来的文件转换成InputStream对象
            InputStream xxinputStream = imgFile.getInputStream();

            Auth auth = Auth.create(accessKey, secretKey);
            String upToken = auth.uploadToken(bucket);

            try {
                //把前端传过来的xxinputStream图片上传到七牛云
                Response response = uploadManager.put(xxinputStream,key,upToken,null, null);
                //解析上传成功的结果
                DefaultPutRet putRet = new Gson().fromJson(response.bodyString(), DefaultPutRet.class);
                System.out.println("上传成功! 生成的key是: "+putRet.key);
                System.out.println("上传成功! 生成的hash是: "+putRet.hash);
                return "http://s6422okdy.hn-bkt.clouddn.com/"+key;//注意这个地方替换成自己的域名,http://不能掉

            } catch (QiniuException ex) {
                Response r = ex.response;
                System.err.println(r.toString());
                try {
                    System.err.println(r.bodyString());
                } catch (QiniuException ex2) {
                    //ignore
                }
            }
        }catch (Exception e) {
            //ignore
        }
        return "上传失败";
    }
}


TypeServiceImpl.java
package com.example.memohehang.service.Impl;



import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import com.example.memohehang.common.R;
import com.example.memohehang.domain.Type;
import com.example.memohehang.mapper.TypeMapper;
import com.example.memohehang.service.TypeService;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.List;

@Service
public class TypeServiceImpl extends ServiceImpl<TypeMapper, Type> implements TypeService
{
    /**
     * 获取所有类型
     * @return
     */
    @Override
    public R typeMapping()
    {
        List<Type> types = list();
        HashMap<Integer, String> hashMap = new HashMap<>();
        for (Type type : types)
        {
            hashMap.put(type.getTypeid(), type.getType());
        }
        return R.success(hashMap);
    }
}


UserServiceImpl.java
package com.example.memohehang.service.Impl;



import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import com.example.memohehang.common.R;
import com.example.memohehang.domain.User;
import com.example.memohehang.mapper.UserMapper;
import com.example.memohehang.service.UserService;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService
{

    /**
     * 登录
     * @param user
     * @return
     */
    @Override
    public R login(User user)
    {
        // 判断用户账号是否正确
        User one = getOne(new QueryWrapper<User>()
                .eq("username", user.getUsername())
                .eq("password", user.getPassword())
        );

        if (one != null)
        {
            return R.success(200,"登录成功", one);
        }
        else
        {
            return R.error(405, "账号或密码错误");
        }
    }

    @Override
    public R register(User user)
    {
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getUsername, user.getUsername());
        System.out.println(user);
        User tempUsername = getOne(queryWrapper);
        // 先判断一下用户是否存在 存在就返回false
        if (tempUsername != null)
        {
            return R.error(405,"账户已存在");
        }
        else
        {
            //网上随机找的一个图片
            user.setAvatar("https://img2.baidu.com/it/u=3841326637,2519425910&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=501");
            // 反之加入
            save(user);
            return R.success(user);
        }
    }

    /**
     * 根据id查询用户
     * @param userid
     * @return
     */
    @Override
    public R selectUserById(Integer userid)
    {
        // 判断用户账号是否正确
        User one = getOne(new QueryWrapper<User>()
                .eq("id", userid)
        );

        if (one != null)
        {
            return R.success(200,"查询成功", one);
        }
        else
        {
            return R.error(405, "查询失败");
        }
    }
}


至此后端工程全部创建完毕,按照下图检查一下是否有缺少,全部完毕后就可以运行项目,利用apipost进行测试,或者前端创建完后直接集成测试

(6)前端工程

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/285599.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

航芯ACM32G103开发板评测 03 RT-Thread Nano移植 线程管理测试

航芯ACM32G103开发板评测 07 RT-Thread Nano移植 线程管理测试 1. 软硬件平台 ACM32G103 Board开发板MDK-ARM KeilRT-Thread Nano 源码 2. 物联网RTOS—RT-Thread ​ RT-Thread诞生于2006年&#xff0c;是一款以开源、中立、社区化发展起来的物联网操作系统。 RT-Thread主…

我的2023年度总结:从大学生到程序员的转变

在过去的一年里&#xff0c;我从一名大学生转变为一名计算机专业人士&#xff0c;经历了许多实战经历&#xff0c;其中最让我印象深刻的是我参与的一个校园App项目。在这个项目中&#xff0c;我负责后端开发和数据库设计&#xff0c;成功地将App上线并得到了师生的好评。 在技术…

小企业是否应该采用SD-WAN组网?

在当今数字化时代&#xff0c;企业成功的关键之一是建立稳定高效的网络连接。无论企业规模大小如何&#xff0c;网络都是实现高效运营和达成业务目标的重要组成部分。对于小企业而言&#xff0c;考虑成本效益和资源管理显得尤为重要。那么&#xff0c;对于小企业来说&#xff0…

电子书推荐|VMware 替代与升级攻略:技术路线、产品对比与用户实践

在进行 VMware 国产化替代时&#xff0c;您是否会遇到以下问题&#xff1a; 如何实现 VMware 整体架构/部分组件替换&#xff1f;是否可以不仅“为替换而替换”&#xff0c;而是同时实现架构的升级&#xff0c;带来更多业务价值&#xff1f;哪些国产方案具备 VMware 同等能力&…

自动化测试报告生成【Allure】

之前尝试使用过testNG自带的测试报告、优化过reportNG的测试报告&#xff0c;对这两个报告都不能满意。后经查找资料&#xff0c;发现有个神器&#xff1a; Allure&#xff08;已经有allure2了&#xff0c;笔者使用的就是allure2&#xff09;&#xff0c;生成的测试报告与上述…

便捷开发技巧——在Vscode中使用Git-翻译自Vscode官网

介绍 Want to easily manage your source code and collaborate with others? Git and GitHub are the tools you need! And with Visual Studio Code, you can set up and use them in a snap. Even if you’re a beginner, VS Code’s user-friendly interface guides you …

一些想法:关于行人检测与重识别

本文主要是介绍我们录用于 ECCV18 的一个工作&#xff1a;Person Search via A Mask-guided Two-stream CNN Model. 这篇文章着眼于 Person Search 这个任务&#xff0c;即同时考虑行人检测&#xff08;Pedestrian Detection&#xff09;与行人重识别&#xff08;Person Re-ide…

【ArcGIS微课1000例】0083:地震灾害图件制作之土壤类型分布图

本文基于1:400万矢量土壤图,制作甘肃积石山6.2级地震100km范围内土壤类型分布图。 文章目录 一、土壤分布图预览二、数据集来源及简介三、土壤分布图制作一、土壤分布图预览 二、数据集来源及简介 1. 数据来源 数据集为1:400万中国土壤图,1:400万中国土壤图(2000)由中国科…

骨传导蓝牙耳机什么牌子好用?为你揭晓不踩雷的骨传导耳机排行

喜欢运动的朋友们&#xff0c;你们一定不能错过骨传导耳机&#xff01;它真的是我们运动时的好帮手。为什么这么说呢&#xff1f;因为它不会像普通耳机那样塞住我们的耳朵&#xff0c;让我们在运动时感觉不舒服&#xff0c;甚至伤害耳朵。而且&#xff0c;它还可以帮助我们听到…

详解动态顺序表

&#x1d649;&#x1d65e;&#x1d658;&#x1d65a;!!&#x1f44f;&#x1f3fb;‧✧̣̥̇‧✦&#x1f44f;&#x1f3fb;‧✧̣̥̇‧✦ &#x1f44f;&#x1f3fb;‧✧̣̥̇:Solitary-walk ⸝⋆ ━━━┓ - 个性标签 - &#xff1a;来于“云”的“羽球人”。…

ES6之Promise的链式调用

✨ 专栏介绍 在现代Web开发中&#xff0c;JavaScript已经成为了不可或缺的一部分。它不仅可以为网页增加交互性和动态性&#xff0c;还可以在后端开发中使用Node.js构建高效的服务器端应用程序。作为一种灵活且易学的脚本语言&#xff0c;JavaScript具有广泛的应用场景&#x…

老品牌新玩法?经济内循环下逆势开出100多家门店,他被央视青睐!

2023年12月26日&#xff0c;CCTV-2整点财经栏目以“抢抓复苏机遇&#xff0c;连锁品牌主打新活力”为主题&#xff0c;播报我国老品牌发展现状&#xff0c;新消费时代以来&#xff0c;消费者的选择多样化、分众化、小众化、个性化&#xff0c;给“老品牌”发展带来前所未有的挑…

Android Context在四大组件及Application中的表现

文章目录 Android Context在四大组件及Application中的表现Context是什么Context源码Activity流程分析Service流程分析BroadcastReceiver流程分析ContentProvider流程分析Application流程分析 Android Context在四大组件及Application中的表现 Context是什么 Context可以理解…

【代码随想录】刷题笔记Day43

前言 刚过完非常愉快的元旦假期&#xff0c;唔想反工啊啊啊&#xff0c;先刷刷题找回学习的状态吧 416. 分割等和子集 - 力扣&#xff08;LeetCode&#xff09; dp[target] target为目标&#xff0c;weight和value相同的01背包问题&#xff0c;用一维遍历dp[j]为容量为j的背…

为什么德国如此重视可持续性有机葡萄酒种植?

可持续性在德国葡萄栽培中越来越重要&#xff0c;它包括对葡萄酒行业的生态、经济和社会问题给予同等的考虑。在过去的几年里&#xff0c;世界范围内出现了许多不同的可持续葡萄酒生产项目。 以可持续发展为导向的酒庄是如何运营的&#xff1f;作为可持续发展整体方法的一部分&…

酒店预订订房小程序源码系统+多商户入驻 完全开源可二开 附带完整的搭建教程

在传统的酒店预订流程中&#xff0c;用户往往需要通过电话、第三方平台或者酒店官网进行预订&#xff0c;这些方式或多或少存在操作繁琐、信息不同步、服务不及时等问题。而小程序的出现&#xff0c;为酒店预订提供了一个全新的解决方案。它无需下载安装&#xff0c;即用即走&a…

租房数据分析可视化大屏+58同城 Django框架 大数据毕业设计(附源码)✅

毕业设计&#xff1a;2023-2024年计算机专业毕业设计选题汇总&#xff08;建议收藏&#xff09; 毕业设计&#xff1a;2023-2024年最新最全计算机专业毕设选题推荐汇总 &#x1f345;感兴趣的可以先收藏起来&#xff0c;点赞、关注不迷路&#xff0c;大家在毕设选题&#xff…

STM32CubeMX教程11 RTC 实时时钟 - 入侵检测和时间戳

目录 1、准备材料 2、实验目标 3、实验流程 3.0、前提知识 3.1、CubeMX相关配置 3.1.1、时钟树配置 3.1.2、外设参数配置 3.1.3、外设中断配置 3.2、生成代码 3.2.1、外设初始化调用流程 3.2.2、外设中断调用流程 3.2.3、添加其他必要代码 4、常用函数 5、烧录验…

php ext-sodium 拓展安装 linux+windows

php编译安装(linux)&#xff0c;可以参考&#xff1a;php编译安装 一、windows soduim源码包自带&#xff0c;直接修改php.ini&#xff0c;取消extensionsodium注释即可 二、linux 1.安装依赖 apt-get install libsodium-dev2.进入源码目录 这里写自己的源码目录 cd /us…

【CASS精品教程】CASS11坐标换带方法(单点计算、批量计算)

参考阅读:【Pix4d精品教程】Pix4d中央子午线细化设置(测区跨两个分带) 文章目录 一、坐标换带概述二、CASS坐标换带1. 单点转换2. 批量转换三、应用场景一、坐标换带概述 坐标换带是将一个投影带的平面直角坐标系换算成另外一个投影带的平面直角坐标系的过程。这一过程主要…