简单宿舍管理系统(springboot+vue)

news2024/10/7 14:31:49

简单宿舍管理系统(springboot+vue)

  • 1.创建项目
    • 1.前端
    • 2.数据库
    • 3.后端
  • 2.登陆
    • 1.前端
      • 1.准备工作
      • 2.登陆组件
      • 3.配置
    • 2.后端
      • 1.链接数据库
      • 2.创建用户实体类
      • 3.数据操作持久层
        • 1.配置
        • 2.内容
        • 3.测试
      • 4.中间业务层
        • 1.异常
        • 2.业务实现
        • 3.测试
      • 5.响应前端控制层
    • 3.前后对接
    • 4.效果
  • 3.后台管理

最近看了springboot和vue,为了练一下把前后端打通就自己手动写个简单的系统,测试一下,把代码放在仓库。

1.创建项目

1.前端

我的前端项目名叫Dormitory,然后添加插件element-plus(页面设计)和axios(后端交互)。

npm init vue@latest#这里插件下载我都选no,之后自己会手动下载使用
cd Dormitory
npm install
npm install element-plus
npm install axios
npm run dev

2.数据库

首先创建库,第一个是登陆功能,我就顺便创建一个简单的用户表t_user。

mysql -u root -p
create database dormitory;
use dormitory;
use store
CREATE TABLE t_user (
	uid INT AUTO_INCREMENT COMMENT '用户id',
	username VARCHAR(20) NOT NULL UNIQUE COMMENT '用户名',
	password CHAR(32) NOT NULL COMMENT '密码',
	role INT COMMENT '角色',
	name VARCHAR(20) NOT NULL UNIQUE COMMENT '姓名',
	gender INT COMMENT '性别:0-女,1-男',
	telephone VARCHAR(50) COMMENT '手机号',
	PRIMARY KEY (uid)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

3.后端

创建项目名叫dormitory_b,依赖库我用了三个(spring web,mybatis framework,mysql driver),然后配置一下jdk和maven环境和xml即可。

2.登陆

登陆这里我把uid和role保存到后端session中,username保存到前端cookie中,而且密码啥的我也没加密,就怎么简单怎么来。

1.前端

1.准备工作

这里我用到element-plus和icon,而且我是按需引入,所以首先下载插件:

npm install -D unplugin-vue-components unplugin-auto-import
npm install @element-plus/icons-vue

然后在vite.config.ts按需引入element-plus:

import { fileURLToPath, URL } from 'node:url'
import AutoImport from 'unplugin-auto-import/vite'
import Components from 'unplugin-vue-components/vite'
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'

export default defineConfig({
  plugins: [
    vue(),
    AutoImport({
      resolvers: [ElementPlusResolver()],
    }),
    Components({
      resolvers: [ElementPlusResolver()],
    }),
  ],
  resolve: {
    alias: {
      '@': fileURLToPath(new URL('./src', import.meta.url))
    }
  }
});

在main.ts里将icon全局注册到App上:

import * as ElementPlusIconsVue from '@element-plus/icons-vue'
for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
  app.component(key, component)
}

就可以使用svg方式使用:

 <el-icon><Menu /></el-icon>

然后配置路由用到了router,所以先下载:

npm install vue-router 

然后在src里面建一个router文件夹,里面建一个index.js写路由配置文件,然后在main.js里面挂载一下:

import router from './router';
app.use(router)

2.登陆组件

这里登陆页面我写在了LoginView里面,后面我会配置路由和组件。

<template>
    <div class="login-container">
      <div class="login-form">
        <el-form ref="login-form" :model="loginForm" label-width="80px" :rules="rules">
          <el-form-item label="用户名" prop="username">
            <el-input v-model="loginForm.username"></el-input>
          </el-form-item>
          <el-form-item label="密码" prop="password">
            <el-input type="password" v-model="loginForm.password"></el-input>
          </el-form-item>
          <el-form-item label="角色" prop="role">
        <el-radio-group v-model="loginForm.role">
          <el-radio label="admin">系统管理员</el-radio>
          <el-radio label="dorm">宿舍管理员</el-radio>
        </el-radio-group>
      </el-form-item>
          <el-form-item size="large">
            <el-button type="primary" @click="toLogin">登录</el-button>
          </el-form-item>
        </el-form>
      </div>
    </div>
  </template>
  
  <script>
  import { ref } from 'vue';
  import axios from 'axios';
  
  export default {
    setup() {
      const loginForm = ref({
        username: '',
        password: '',
        role: 'admin',
      });
  
      const rules = {
        username: [{ required: true, message: '请输入用户名', trigger: 'blur' }],
        password: [{ required: true, message: '请输入密码', trigger: 'blur' }],
        role: [{ required: true, message: '请选择角色', trigger: 'change' }],
      };
  
      const performLogin = async () => {
        try {
            const formData = new FormData();//axios默认是json格式发送数据,但我后端接受的是user,所以将数据放到表单
            formData.append('username', loginForm.value.username);
            formData.append('password', loginForm.value.password);
            formData.append('role',loginForm.value.role=='admin'?0:1);

            const response = await axios.post('http://localhost:8080/users/login', formData);
            const data = response.data;

  
          if (data.state === 200) {
            // 登录成功后,保存用户名到cookie
            document.cookie = `username=${loginForm.value.username}; expires=; path=/`;
            alert('登录成功');
          } else if (data.state === 400) {
            alert('用户名错误');
          } else if (data.state === 401) {
            alert('密码错误');
          }else if (data.state === 402) {
            alert('角色错误');
          }
        } catch (error) {
          console.error('An error occurred:', error);
        }
      };
  
      const toLogin = () => {
        performLogin();
      };
  
      return {
        loginForm,
        rules,
        toLogin,
      };
    },
  };
  </script>
  
  <style scoped>
  .login-container {
    display: flex;
    align-items: center;
    justify-content: center;
    height: 100vh;
  }
  
  .login-form {
    padding: 80px;
    border-radius: 10px;
    box-shadow: 0 0 10px rgba(0, 0, 0, 0.2);
  }
  </style>
  

3.配置

首先是在router/index.js里面写路由配置,将这个页面路由配置一下:

import { createRouter, createWebHistory } from 'vue-router'
import LoginView from '@/components/LoginView.vue'
const router = createRouter({
  history: createWebHistory(import.meta.env.BASE_URL),
  routes: [
    {
      path: '/login',
      component: LoginView
    }
  ]
})
export default router

然后在App.vue里面写一下这个路由出口

<template>
  <RouterView></RouterView>
</template>

此时就可以通过http://localhost:5173/login/访问到这个页面。

2.后端

1.链接数据库

在application.properties中配置数据库。

spring.datasource.url=jdbc:mysql://localhost:3306/dormitory?useUnicode=true&characterEncoding=utf-8
spring.datasource.username=root
spring.datasource.password=root

2.创建用户实体类

在entity/User类里面创建用户实体类,和getset,equal,tostring方法(mac的快捷键是command+n)。

public class User {
        private Integer uid;
        private String username;
        private String password;
        private Integer role;
        private String name;
        private Integer gender;
        private String phone;
}

3.数据操作持久层

1.配置

首先是配置一下mapper层,在启动类里面添加项目的mapper路径,让自动扫包。

@MapperScan("com.hckj.dormitory_b.mapper")

在application.properties中配置mapper地址。

mybatis.mapper-locations=classpath:mapper/*.xml
2.内容

在mapper/UserMapper接口里面写SQL语句的抽象方法(类添加@Mapper注解),然后resources/mapper/UserMapper.xml里面写抽象方法的映射文件(这里放在resource是因为xml是静态文件)。

User findByUsername(String username);//接口
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.hckj.dormitory_b.mapper.UserMapper">
    <select id="findByUsername" resultType="com.hckj.dormitory_b.entity.User">
        select * from t_user where username=#{username}
    </select>
</mapper>
3.测试

为了登陆测试,这里先给数据库里面插入一条数据:

INSERT INTO t_user (username, password, name,role, gender, telephone)
VALUES ('zoe', '111', 'dz', 0, 0,'188');

然后测试(测试类加注解:@SpringBootTest和@RunWith(SpringRunner.class))

	@Autowired
    private UserMapper userMapper;
    @Test
    public void findByUsername(){
        System.out.println(userMapper.findByUsername("zoe"));
    }

4.中间业务层

1.异常

在登录这个业务里会出现用户没有查询到和密码不匹配,所以在service的ex包里面创建UsernameNotFoundException和PasswordNotMatchException异常类,还有一个是角色不匹配RoleNotMatchException,并都继承RuntimeException,然后生成抛出异常的5种构造方法。

2.业务实现

然后写业务层的接口(加@Service注解)并写类实现这个接口。

User login(String username, String password,Integer role);//接口
@Service
public class UserServiceImpl implements IUserService{
    @Autowired
    private UserMapper userMapper;
    @Override
    public User login(String username, String password,Integer role) {
        User result = userMapper.findByUsername(username);
        if (result == null) {
            throw new UsernameNotFoundException("用户数据不存在");
        }
        String password_ = result.getPassword();
        if (!password_.equals(password)) {
            throw new PasswordNotMatchException("用户密码错误");
        }
        Integer role_=result.getRole();
        if (!role_.equals(role)) {
            throw new RoleNotMatchException("用户角色错误");
        }
        User user = new User();
        user.setUid(result.getUid());
        user.setUsername(result.getUsername());
        user.setRole(result.getRole());
        return user;
    }
}
3.测试
@SpringBootTest
@RunWith(SpringRunner.class)
public class UserServiceTests {
    @Autowired
    private IUserService userService;
    @Test
    public void login(){
        User user= userService.login("zoe","111",0);
        System.out.println(user);
    }
}

5.响应前端控制层

package com.hckj.dormitory_b.controller;

import com.hckj.dormitory_b.entity.User;
import com.hckj.dormitory_b.service.IUserService;
import com.hckj.dormitory_b.service.ex.PasswordNotMatchException;
import com.hckj.dormitory_b.service.ex.RoleNotMatchException;
import com.hckj.dormitory_b.service.ex.UsernameNotFoundException;
import jakarta.servlet.http.HttpSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.HashMap;
import java.util.Map;

@RestController
@RequestMapping("users")
public class UserController {
    @Autowired
    private IUserService userService;
    @PostMapping("login")
    public Map<String, Object> login(User user, HttpSession session) {
        String username = user.getUsername();
        String password = user.getPassword();
        Integer role=user.getRole();
        Map<String, Object> response = new HashMap<>();
        try {
            User loggedInUser = userService.login(username, password,role);
            session.setAttribute("uid",loggedInUser.getUid());//将用户的uid和role保存到session
            session.setAttribute("role",loggedInUser.getRole());
            response.put("state", 200);
            response.put("message", "登陆成功");
            response.put("data", loggedInUser);
        } catch (UsernameNotFoundException e) {
            response.put("state", 400);
            response.put("message", "用户名未找到");
            response.put("data", null);
        } catch (PasswordNotMatchException e) {
            response.put("state", 401);
            response.put("message", "密码不正确");
            response.put("data", null);
        } catch (RoleNotMatchException e){
            response.put("state",402);
            response.put("message","角色不正确");
            response.put("data",null);
        }
        return response;
    }
}

3.前后对接

对接这里其实就只是一个跨域问题,这个就是在后端工程的config/WebMvcConfig类里面加入设置,这里我前端的地址是http://localhost:5173

package com.hckj.dormitory_b.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
                .allowedOrigins("http://localhost:5173")
                .allowedMethods("GET", "POST", "PUT", "DELETE")
                .allowCredentials(true);
    }
}

4.效果

在这里插入图片描述

3.后台管理

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

散列表:Word文档中的单词拼写检查功能是如何实现的?

文章来源于极客时间前google工程师−王争专栏。 一旦我们在Word里输入一个错误的英文单词&#xff0c;它就会用标红的方式提示“编写错误”。Word的这个单词拼写检查功能&#xff0c;虽然很小但却非常实用。这个功能是如何实现的&#xff1f; 散列别&#xff08;Hash Table&am…

linux复习笔记02(小滴课堂)

linux下输入输出错误重定向&#xff1a; 输入重定向&#xff1a;< 一个大于号是进行了覆盖。 两个大于号是追加。 输出重定向可以用于以后日志打印。 错误重定向&#xff1a; 错误重定向是不把信息打印到屏幕上而是打印到指定文件中去&#xff1a; 输出重定向其实是用的1…

【论文阅读】(2023TPAMI)PCRLv2

目录 AbstractMethodMethodnsU-Net中的特征金字塔多尺度像素恢复多尺度特征比较从多剪切到下剪切训练目标 总结 Abstract 现有方法及其缺点&#xff1a;最近的SSL方法大多是对比学习方法&#xff0c;它的目标是通过比较不同图像视图来保留潜在表示中的不变合判别语义&#xff…

可视化数学分析软件 MATLAB R2021b mac中文版软件介绍

MATLAB R2021b mac作为数学类科技应用软件中首屈一指的商业数学软件&#xff0c;可以帮助您进行矩阵运算、绘制函数和数据、实现算法、创建用户界面、连接其他编程语言的程序等,主要应用于工程计算、控制设计、信号处理与通讯、图像处理、信号检测、金融建模设计与分析等领域。…

算法刷题-链表

算法刷题-链表 203. 移除链表元素 给你一个链表的头节点 head 和一个整数 val &#xff0c;请你删除链表中所有满足 Node.val val 的节点&#xff0c;并返回 新的头节点 。 示例 1&#xff1a; 输入&#xff1a;head [1,2,6,3,4,5,6], val 6 输出&#xff1a;[1,2,3,4,5]…

小成代码路的错误

文章目录 计算长度使用左闭右开的方法getline(解决输入空格问题和给一个输入的界限&#xff09;stoi(字符串转整形&#xff09;stoi&#xff08;整型转字符串型&#xff09;reverse&#xff08;反转函数&#xff09;将字符串立志静成员变量在类外初始化&#xff1b;但是有特例&…

FreeSWITCH 1.10.10 简单图形化界面12 - 注册IMS

FreeSWITCH 1.10.10 简单图形化界面12 - 注册IMS 0、 界面预览1、IMS注册-SIP中继基本设置界面2、IMS注册-SIP中继呼叫设置3、IMS中继-代理设置界面4、IMS注册-SIP中继状态界面5、IMS注册-SIP中继详细状态界面6、IMS注册-SIP中继代拨号码优先界面 FreeSWITCH界面安装参考&#…

Qt planeGame day10

Qt planeGame day10 Game基本框架 qt中没有现成的游戏框架可以用&#xff0c;我们需要自己搭框架首先创建一个QGame类作为框架&#xff0c;这个基本框架里面应该有如下功能&#xff1a;游戏初始化 void init(const QSize& siez,const QString& title);游戏反初始化(…

系统报错“由于找不到vcomp140.dll无法继续执行代码”的解决方案

在我们日常使用电脑的过程中&#xff0c;可能会遇到一些错误提示&#xff0c;其中之一就是“找不到vcomp140.dll”。这个错误可能让许多用户感到困扰&#xff0c;因为它可能影响到我们的电脑使用。那么&#xff0c;vcomp140.dll是什么意思&#xff1f;当我们遇到这个问题时&…

学习笔记2——Nosql

学习笔记系列开头惯例发布一些寻亲消息 链接&#xff1a;https://baobeihuijia.com/bbhj/contents/3/194205.html 跟学链接 跟学视频链接&#xff1a;https://www.bilibili.com/video/BV1S54y1R7SB/?spm_id_from333.999.0.0 &#xff08;建议有java基础的同学学习或者一直…

发挥设计模式单例模式的力量:从技术到社会的转变

文章目录 &#x1f31f; 如何将设计模式单例模式运用到社会当中&#x1f34a; 什么是单例模式&#x1f34a; 单例模式在现实生活中的应用&#x1f389; 数据库连接池&#x1f389; 日志管理器&#x1f389; 系统配置中心 &#x1f34a; 如何将单例模式应用于社会中&#x1f389…

【Unity程序技巧】公共Update管理器

&#x1f468;‍&#x1f4bb;个人主页&#xff1a;元宇宙-秩沅 &#x1f468;‍&#x1f4bb; hallo 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍&#x1f4bb; 本文由 秩沅 原创 &#x1f468;‍&#x1f4bb; 收录于专栏&#xff1a;Uni…

hugo-stack for github

静态博客框架jekyll、hexo和hugo三者之间的区别与差异 博客生成器? 全名为静态网站生成器&#xff0c; 可在任意拥有主机功能的环境下寄存(托管)可直接配合域名进行全球访问 劣势: 每次更新网页必须重新生成整个网站编译速度&#xff08;单位&#xff1a;秒&#xff09; Jek…

Win下Eclipse安装

eclipse官网https://www.eclipse.org/downloads/ 软件介绍&#xff1a; Eclipse 是一个开放源代码的、基于 Java 的可扩展开发平台。Eclipse 是 Java 的集成开发环境&#xff08;IDE&#xff09;&#xff0c;当然 Eclipse 也可以作为其他开发语言的集成开发环境&#xff0c;如…

为什么使用KT6368A蓝牙芯片用app连接,基本都在5分钟左右后断开

为什么我们自己的板子用KT6368A蓝牙芯片&#xff0c;用app连接&#xff0c;基本都是在5分钟左右后 断掉或者断开&#xff0c;什么原因。参考的原理图&#xff0c;是官方的图纸如下 遇到这样的问题&#xff0c;根据我们的经验&#xff0c;大概率是硬件问题&#xff0c;分析方法如…

深度好文:How to get started in C++!

Datawhale干货 作者&#xff1a;zclll&#xff0c;推荐&#xff1a;卢雨畋&#xff0c;Datawhale成员 在大家的不懈催更下&#xff08;hhh)&#xff0c;这篇文章终于和大家见面了。对于程序设计、软件开发而言&#xff0c;我都只是一个入门水平而已&#xff08;也许C略多一点&…

whatsapp的越狱特征检测

一、检测点 1、检测目录 opendir打开bin是否成功 2、检测模块 解析macho的header头获取加载的模块&#xff0c;获取进程的所有模块&#xff0c;判断是否包含如下模块&#xff1a;substrate,watusi,zdumper 3、检测文件 判定文件或是应用是否的路径是否存在 /Applications/Cydia…

单链表的相关操作(精简版..在修改中)

目录 前言&#xff1a; 哨兵位&#xff1a; 链表的概念 链表的相关操作&#xff1a; 链表的创建&#xff1a; 打印链表&#xff1a; 申请新节点&#xff1a; 链表的尾插&#xff1a; &#xff01;&#xff01;&#xff01;对于传参中二级指针的解释&#xff1a; 链表的…

[C国演义] 第十六章

第十六章 等差数列的划分最长递增子序列 等差数列的划分 力扣链接 子数组 ⇒ dp[i]的含义: yinums[i] 为结尾的所有子数组中的 等差数列数组最多的个数子数组⇒ 状态转移方程: 根据最后一个元素的构成 初始化: 涉及到 i-1, i-2 ⇒ 所以要初始化dp[0] 和 dp[1] 都初始化为 0…

一次不成功的抓包过程

想搞Android app抓包&#xff0c;简单的方法&#xff0c;已经不起作用&#xff0c;打开charles代理工具&#xff0c;抓不到我的目标app任何请求&#xff0c;搞了两三天&#xff0c;也没成功。 我的目标APP里&#xff0c;经过apk反编译出来&#xff0c;看到有libflutter.so文件&…