目录

(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)前端工程

index.js

pages.json

addNote.vue

 catNote.vue

 Login.vue

 Main.vue

 mine.vue

Register.vue

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

(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

xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">

4.0.0

org.springframework.boot

spring-boot-starter-parent

2.7.8

com.example

Memo-hehang

0.0.1-SNAPSHOT

hehang

memo

1.8

org.springframework.boot

spring-boot-starter-web

org.mybatis.spring.boot

mybatis-spring-boot-starter

2.3.0

org.mybatis.spring.boot

mybatis-spring-boot-starter

2.3.0

org.springframework.boot

spring-boot-starter-data-jpa

com.mysql

mysql-connector-j

runtime

org.projectlombok

lombok

true

org.springframework.boot

spring-boot-starter-test

test

com.baomidou

mybatis-plus-boot-starter

3.4.2

com.qiniu

qiniu-java-sdk

[7.13.0, 7.13.99]

com.google.code.gson

gson

2.10.1

org.springframework.boot

spring-boot-maven-plugin

org.projectlombok

lombok

org.apache.maven.plugins

maven-compiler-plugin

9

9

然后我们修改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

{

/**

* 添加备忘录

* @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

{

/**

* 获取所有类型

* @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

{

/**

* 登录

* @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 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 wrapper = new QueryWrapper<>();

wrapper.eq("id", noteid);

List 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().orderByAsc("finish","time").eq("rid", userid));

return R.success(pageData);

}

/**

* 查询最近即将截止的未完成的备忘录的时间差

* @param userid

* @return

*/

@Override

public R selectcutDownTime(Integer userid)

{

QueryWrapper wrapper = new QueryWrapper<>();

wrapper.eq("rid", userid).orderByAsc("finish", "time");

List 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 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().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().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 implements TypeService

{

/**

* 获取所有类型

* @return

*/

@Override

public R typeMapping()

{

List types = list();

HashMap 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 implements UserService

{

/**

* 登录

* @param user

* @return

*/

@Override

public R login(User user)

{

// 判断用户账号是否正确

User one = getOne(new QueryWrapper()

.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 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()

.eq("id", userid)

);

if (one != null)

{

return R.success(200,"查询成功", one);

}

else

{

return R.error(405, "查询失败");

}

}

}

至此后端工程全部创建完毕,按照下图检查一下是否有缺少,注意Mapper可写也可以不写,因为我们不需要写SQL语句,不需要调用Mapper,全部完毕后就可以运行项目,利用apipost进行测试,或者前端创建完后直接集成测试

(6)前端工程

我们采用uniapp来写前端代码,按照以下步骤建立项目

输入项目名称,选择vue2

我们需要用到以下uniapp的组件,可以从uniapp组件库下载,链接为:组件使用的入门教程 | uni-app官网

对应的矢量图标可以在阿里巴巴矢量图库下载,链接为iconfont-阿里巴巴矢量图标库

然后我们在根目录下建立store文件夹,在此文件夹下建立index.js,用于存放一些函数

index.js

export function getUserid() {

let userid = uni.getStorageSync("userid");

if (userid == null || userid === '')

return '';

else

return userid;

}

export function getNoteid()

{

let noteid = uni.getStorageSync("noteid");

if (noteid == null || noteid === '')

return '';

else

return noteid;

}

export function getUsername()

{

let username = uni.getStorageSync("username");

if (username == null || username === '')

return '';

else

return username;

}

export function hasLogin() {

let userid = uni.getStorageSync("userid");

if (userid == null || userid === '') {

return false;

} else

return true;

}

export function logout() {

uni.removeStorageSync("userid");

uni.removeStorageSync("noteid");

uni.removeStorageSync("username");

uni.redirectTo({

url: "/pages/mine"

});

}

随后修改pages.json中修改相关页面配置文件,可以先创建相关页面后再进行此步骤,以免编译时报错

pages.json

{

"pages": [ //pages数组中第一项表示应用启动页,参考:https://uniapp.dcloud.io/collocation/pages

{

"path": "pages/Main",

"style": {

"navigationBarTitleText": "个人备忘录"

}

}

,{

"path" : "pages/Login",

"style" :

{

"navigationBarTitleText": "登录",

"enablePullDownRefresh": false

}

}

,{

"path" : "pages/Main",

"style" :

{

"navigationBarTitleText": "所有备忘录",

"enablePullDownRefresh": false

}

},

{

"path" : "pages/mine",

"style" :

{

"navigationBarTitleText": "个人中心",

"enablePullDownRefresh": false

}

}

,{

"path" : "pages/addNote",

"style" :

{

"navigationBarTitleText": "添加/修改备忘录",

"enablePullDownRefresh": false

}

}

,{

"path" : "pages/catNote",

"style" :

{

"navigationBarTitleText": "查询备忘录",

"enablePullDownRefresh": false

}

}

,{

"path" : "pages/Register",

"style" :

{

"navigationBarTitleText": "注册",

"enablePullDownRefresh": false

}

}

],

"globalStyle": {

"navigationBarTextStyle": "black",

"navigationBarTitleText": "个人备忘录",

"navigationBarBackgroundColor": "#F8F8F8",

"backgroundColor": "#F8F8F8"

},

"tabBar": {

"list": [

{

"text": "首页",

"pagePath": "pages/Main",

"iconPath": "static/images/首页.png",

"selectedIconPath": "static/images/首页2.png"

},

{

"text": "记录",

"pagePath": "pages/addNote",

"iconPath": "static/images/记录.png",

"selectedIconPath": "static/images/记录1.png"

},

{

"text": "分类",

"pagePath": "pages/catNote",

"iconPath": "static/images/分类.png",

"selectedIconPath": "static/images/分类2.png"

},

{

"text": "我的",

"pagePath": "pages/mine",

"iconPath": "static/images/我的.png",

"selectedIconPath": "static/images/我的2.png"

}

]

},

"uniIdRouter": {}

}

 然后再pages中建立以下页面文件,我这里没有创建同名目录

addNote.vue

 catNote.vue

 Login.vue

 Main.vue

 mine.vue

Register.vue

到这里前后端代码已经全部完成,下面是运行的截图

到此全部结束啦,如果此文章对你有帮助,希望给一个关注+点赞+收藏

若需要源码可以私信我,免费分享

推荐阅读

评论可见,请评论后查看内容,谢谢!!!评论后请刷新页面。