健康系统练习

健康系统

项目建构:

前后端分离,前端vue3,后端Java,springboot做跨域处理,前端将在vscode中 的tomcat下部署,后端将在ideal中集成的tomcat中部署

健康系统练习_第1张图片

创建项目工程在ideal中直接选用springi…创建,选中web,sql中的mysdatatbasses

后端页面

在数据源中新建一个数据连接池application.yml:

健康系统练习_第2张图片

健康系统练习_第3张图片

其中的image-20230629163810888加载了数据库连接池的驱动

image-20230629163832606

连接数据对象的地址,使用了jdbc进行连接

  • 上面的 mybatis.mapper-locations 属性指定了 Mapper 接口文件所在的位置,mybatis.type-aliases-package 属性则指定了类型别名所在的包。你可以根据你的实际情况进行调整。
  • 此时,Spring Boot 将使用这个端口号来启动 Web 服务器,为了防止后面前端页面中的tomcat中的端口重复

在浏览器中验证9000端口成功加载

健康系统练习_第4张图片

健康系统练习_第5张图片

在Java类中创建测试案列test来展示项目的结构

健康系统练习_第6张图片

健康系统练习_第7张图片

在浏览器上输入地址后

健康系统练习_第8张图片

前后端分离导致他们的服务器端口通信不一致,需要让他们保持通信

健康系统练习_第9张图片

前端页面:

环境准备:

需要下载node.js才能使用vue框架

安装node.js包管理器

在安装完node.js后需要安装安装Nodejs下的包管理器,打开windows命令窗口,输入“npm install -g cnpm --registry=https://registry.npm.taobao.org

健康系统练习_第10张图片

下载不了就国内镜像下载,可以更新一下版本,

安装vue-cli脚手架

切换到d盘目录安装脚手架:

健康系统练习_第11张图片

npm install -g @vue/cli

查看下版本

image-20230629164143190

启动下可视化界面在对应的目录下:

成功启动:

image-20230629164157125

健康系统练习_第12张图片

初始预设项目的创建:

在D盘下创建此项目

健康系统练习_第13张图片

健康系统练习_第14张图片

image-20230629164300368

image-20230629164307959

image-20230629164313854

在最后创建的前一步

要选择创建的版本选择3.x版本的

健康系统练习_第15张图片

image-20230629164349999

在创建完成后需要给vue添加一些组件在插件库里面添加插件

添加:插件,由于我是vue3所以使用plus版element

健康系统练习_第16张图片

image-20230629164431175

点击完成安装

添加依赖:

image-20230629164448404

健康系统练习_第17张图片

健康系统练习_第18张图片

这几个就是帮助设计样式,和提交的

健康系统练习_第19张图片

启动项目:

健康系统练习_第20张图片

对基础页面进行删减:

健康系统练习_第21张图片

创建登录组件:

健康系统练习_第22张图片

健康系统练习_第23张图片

为了保证能访问到需要进行路由转发(index.js)

image-20230629164907311

健康系统练习_第24张图片

在app主界面修设置了路由转发

健康系统练习_第25张图片

开发login组件:

健康系统练习_第26张图片

创建了全局的css样式global.css

健康系统练习_第27张图片

在导入到全局变量

健康系统练习_第28张图片

登录页面成功显示:

健康系统练习_第29张图片

健康系统练习_第30张图片

设置列表前面的搜索框

健康系统练习_第31张图片

健康系统练习_第32张图片

为了美化页面里面的图标需要下载好图标导入到项目

image-20230908102020972

健康系统练习_第33张图片

打开健康系统练习_第34张图片

这里面有用法

image-20230630112552842

导入到项目在全局设置样式(main.js)

健康系统练习_第35张图片

image-20230630161511754

image-20230630161626155

健康系统练习_第36张图片

image-20230908101956593

注意这里是在里面是有一个点的要去掉

健康系统练习_第37张图片

健康系统练习_第38张图片

样式添加:

在global.css设置了登录容器的大小即为可视化窗口的大小

健康系统练习_第39张图片

在login.vue中设置了容器的高度大小为可视化窗口的100%

健康系统练习_第40张图片

设置了背景颜色和大小

健康系统练习_第41张图片

成功让其填充到页面

设置了login——box登录容器的样式这里可以调整:

image-20230701174534998

设置了form表单样式:

健康系统练习_第42张图片

设置了log区域的div样式:

健康系统练习_第43张图片

设置了图标:

健康系统练习_第44张图片

结果:

健康系统练习_第45张图片

设置了登录按钮的样式边界:

健康系统练习_第46张图片

设置了form表单的样式:

调整后:

健康系统练习_第47张图片

前端登录页面美化样式完成:

添加用户登录表单非空前验证:

添加属性:

健康系统练习_第48张图片

设置了用户名和密码的登录前必须输入验证:

健康系统练习_第49张图片

并且在对应的表单中绑定了对应的事件

健康系统练习_第50张图片

添加登录的提交需要导入axios

(vue2)

image-20230702111350772

由于我使用的是vue3导致使用的挂载方法不一致,且挂载axios有先后顺序,必须在访问app之前挂载

(vue 3)

健康系统练习_第51张图片

在密码框添加了防可见

image-20230702113501245

为了验证按钮点了之后是否生效我加了验证的日志

健康系统练习_第52张图片

浏览器开发者工具下

健康系统练习_第53张图片

在设置登录按钮的过程中由于vue3问题我修改了多次下面展示我修改的代码

image-20230702162817944

健康系统练习_第54张图片

健康系统练习_第55张图片

image-20230702163115502

这里我还将窗口的可视化进行了移动、

健康系统练习_第56张图片

健康系统练习_第57张图片

在点击登录和重置后,有信息输出表示成功了

健康系统练习_第58张图片

登录显示后端数据测试

健康系统练习_第59张图片

点击登录后成功显示

健康系统练习_第60张图片

健康系统练习_第61张图片

添加了点击登录按钮后提示的消息框

image-20230702184035615

image-20230702184046877

健康系统练习_第62张图片

健康系统练习_第63张图片

健康系统练习_第64张图片

添加home首页创建home首页

image-20230704104230878

在home页面写上基本框架

健康系统练习_第65张图片

重定向路由页面让路由进行跳转

image-20230704104419128

image-20230704104431873

健康系统练习_第66张图片

健康系统练习_第67张图片

到此处完整的响应请求,基本完成,且前后端分离

创建user对象进行封装(get,Set):

健康系统练习_第68张图片

健康系统练习_第69张图片

创建了一个登录控制器:

健康系统练习_第70张图片

健康系统练习_第71张图片

改变前端页面要访问的后台地址:

健康系统练习_第72张图片

在点击登录后成功跳转login页面

image-20230705095459535

在后端接收到创建的User 对象

在后台控制台,查看到创建的User对象

image-20230705095726836

到这实体用户User的自动封装,自动创建,已经完成

在dao成进行数据库的访问

健康系统练习_第73张图片

健康系统练习_第74张图片

编写了查询语句

健康系统练习_第75张图片

健康系统练习_第76张图片

返回了controller层,进行登录

健康系统练习_第77张图片

健康系统练习_第78张图片

在主程序入口进行了扫描dao层中的包的操作

image-20230705113706041

点击了登录后跳转到home页面,在后端会查询到数据中的用户信息

image-20230705113950397

image-20230705114004183

导入json特殊字符串,形成json对象

健康系统练习_第79张图片

由于我是用的gradle创建的项目没有pom.xml文件,Gradle使用一个名为"build.gradle"(或者是"build.gradle.kts",如果你使用Kotlin脚本)的文件来定义项目的构建配置。这个文件包含了项目的依赖项、插件、任务和其他构建设置。

image-20230714192350807

在login页面将对象转化为json字符串

image-20230714192523983

在登录页面对跳转页面进行设置,设置了他的默认值是error,使用了json.tojsonstring来将对象和跳转页面进行返回

健康系统练习_第80张图片

将从后端发送过来的数据的flag值和ok对比,进行跳转

健康系统练习_第81张图片

在hom.vue中添加了退出按钮,并成功返回到登录页面

健康系统练习_第82张图片

健康系统练习_第83张图片

在点击了退出按钮后,成功返回到登录页面也就是login页面

在成功点击登录后,在浏览器调试页面查看会话中的存储数据,点击登录之后会在调试页面生成key 和值,在点击退出之后这些数据也不会清除,这样的安全性大大下降

健康系统练习_第84张图片

在home.vue中清除session

健康系统练习_第85张图片

改了之后

image-20230715154100039

在设置完清楚会话session后我添加了一个安全退出的提示框(home.vue)

image-20230715155545262

健康系统练习_第86张图片

健康系统练习_第87张图片

设置了路由守卫(index.js)

这段代码是使用 Vue Router 中的全局前置守卫 beforeEach,它的作用是在路由导航之前进行拦截和处理。

健康系统练习_第88张图片

测试了登录页面正常登录,和退出

设置home页面的布局

在elemenet中找到containerd 容器布置器

Container | Element Plus (element-plus.org)

找到一个有头,有左有右,没有尾巴的布局

健康系统练习_第89张图片

在home首页插入代码:

布局设置:
<template>
    
    <div class="common-layout">
        
        <el-container class="home-container">
                 
                 <el-aside width="200px">Asideel-aside>
            
            <el-container>
                
                <el-header>
                    首页
                    
                    
                el-header>
                
                <el-main>Mainel-main>
            el-container>
        el-container>
    div>
template>
并在style中设置了布局样式
/* 布局器的填充 height: 100vh,可以确保布局容器填充整个视口的高度*/
.home-container{
    height: 100vh;
}
/* home主页样式设置 */
/* 头样式 */
.el-header{
    background-color: #373d41;
}
/* 侧边栏样式 */
.el-aside{
    background-color: #333744;
}
/* 主体样式 */
.el-main{
    background-color: #eaedf1;
}

健康系统练习_第90张图片

在侧边栏里面添加了图标

        <el-aside width="200px">
            <img src="../assets/OIP.png" alt="">
        el-aside>

健康系统练习_第91张图片

添加了文字信息设置了文字信息的样式

/* 头样式 */
.el-header {
    /* 背景颜色 */
    background-color: #373d41;
    /* 使用 Flexbox 布局 */
    display: flex;
    /* 在主轴上居中对齐 */
    justify-content: center;
    /* 在交叉轴上居中对齐 */
    align-items: center;
    /* 左边距设置为0% */
    padding-left: 0%;
    /* 文字颜色 */
    color: #fff;
    /* 字体大小 */
    font-size: 20px;
}

image-20230717194531753

添加导航栏

导航 |元素加 (element-plus.org)

      <el-menu
        active-text-color="#ffd04b"
        background-color="#545c64"
        text-color="#fff"
      >
        <el-sub-menu index="1">
          <template #title>
            <el-icon><location />el-icon>
            <span>Navigator Onespan>
          template>
          <el-menu-item-group title="Group One">
            <el-menu-item index="1-1">item oneel-menu-item>
            <el-menu-item index="1-2">item twoel-menu-item>
          el-menu-item-group>
          <el-menu-item-group title="Group Two">
            <el-menu-item index="1-3">item threeel-menu-item>
          el-menu-item-group>
          <el-sub-menu index="1-4">
            <template #title>item fourtemplate>
            <el-menu-item index="1-4-1">item oneel-menu-item>
          el-sub-menu>
        el-sub-menu>
        <el-menu-item index="2">
          <el-icon><icon-menu />el-icon>
          <span>Navigator Twospan>
        el-menu-item>
        <el-menu-item index="3" disabled>
          <el-icon><document />el-icon>
          <span>Navigator Threespan>
        el-menu-item>
        <el-menu-item index="4">
          <el-icon><setting />el-icon>
          <span>Navigator Fourspan>
        el-menu-item>
      el-menu>

添加了注册按钮:

注册

在set中设置了register注册方法

// 注册按钮点击事件

  const register = () => {

   app.$router.push("/SigIn");

  };

在return中设置了返回函数

register // 返回register函数

在路由中导入了注册的路径

// 导入SignIn主页
import SignIn from '../components/SigIn.vue'	

设置了重定向的组件和路径

 {

  // 重定向到这个路径

  path: "/SigIn",

  // 导入的组件

  component:SignIn





 }

在sigin页面添加了注册表单并设置了样式







由于前面设置了路由守卫,导致了在login页面只能跳转到home页面,注册页面跳转不出来,我修改了路由守卫,让他不用验证用户,就能直接跳转到注册页面

if (to.path==="/sigin")return next();

将前端的注册页面完成,现在将前端收集的数据发送到后端

controller层

package com.healthsystem.portplay.controller;

import com.healthsystem.portplay.bean.User;
import com.healthsystem.portplay.dao.UserDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class RegisterController {
    /**
     * 自动注入 UserDao 对象
     */
    @Autowired
    UserDao userDao;
    /**
     * 处理登录请求的方法
     *
     * @param user 包含登录信息的 User 对象
     * @return 返回包含登录结果和用户信息的 JSON 字符串
     */
    @RequestMapping("/register")
    public String registerUser(@RequestBody User user){
        userDao.save(user); // 假设 userDao 中有一个保存用户的方法 saveUser(User user)

        // 返回一个表示注册成功的 JSON 字符串
        return "{\"success\": true}";
    }
}

dao层来访问数据层


import com.healthsystem.portplay.bean.User;
import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Repository;

//"@Repository" 是一个注解,它用于在 Spring 框架中标识一个类为数据访问对象(DAO)。
@Repository
//定义接口,在login层实现
public interface UserDao {
    // 保存用户信息到数据库
    void save(User user);
    //    "@Param" 是一个注解,它通常用于在使用 MyBatis 进行数据库访问时,标识方法参数与 SQL 语句中的参数的映射关系
    User GetUserByMessage(@Param("username") String username, @Param("password") String password);
}

uesrmapper.xml文件

DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="com.healthsystem.portplay.dao.UserDao">
    <select id="GetUserByMessage" resultType="com.healthsystem.portplay.bean.User">
        select *
        from `user`
        where username = #{username}
          and password = #{password}
          and state = 1;
    select>
    <insert id="save" parameterType="com.healthsystem.portplay.bean.User">
        INSERT INTO `user` (username, password, email) VALUES
            (#{username}, #{password}, #{email})
    insert>
mapper>

添加了注册成功会拉起登录程序,登录成功跳转到home首页

async submitFormData(formData) {
      // 发送表单数据到后端进行处理和存储
      const response = await axios.post('/register', formData);
      const res = response.data;
     
      // 假设后端返回的 JSON 结果中有一个名为 'success' 的字段,表示注册是否成功
      if (res.success) {
        // 注册成功
        ElMessage.success('成功');
        // 在注册成功后调用登录方法,传递注册的用户名和密码
        this.login(formData.username, formData.password);

      } else {
        // 注册失败
        ElMessage.error('失败');
      }
    },

在其中我尝试了几次注册成功跳转失败,我去检查后端,和前端代码,并没有发现,没有发现问题,但是我还是将前端的拉起登录部分检查,以为是数据传送不到登录页面。睡了一会发现,应该不是这个问题,可能是数据库中的账户状态问题

当账户状态是0时,登录不了,我改变了他的状态

image-20230725170724081

健康系统练习_第92张图片

成功登录当首页

设置了一个联系的三个链接

image-20230725203829752

在关于我们页面设置了关于我们,和联系我们的留言






  

  

  

添加了常见问题页面的展示


  

  

  

健康系统练习_第93张图片


文章目录

  • **健康系统**
  • 项目建构:
  • **后端**页面
    • **在数据源中新建一个数据连接池application.yml:**
    • **在Java类中创建测试案列test来展示项目的结构**
    • **前后端分离导致他们的服务器端口通信不一致,需要让他们保持通信**
  • **前端页面:**
    • **环境准备:**
      • **需要下载node.js才能使用vue框架**
      • **安装node.js包管理器**
      • **安装vue-cli脚手架**
      • **启动下可视化界面在对应的目录下:**
      • **初始预设项目的创建:**
      • **要选择创建的版本选择3.x版本的**
      • **在创建完成后需要给vue添加一些组件在插件库里面添加插件**
      • **添加依赖:**
      • **启动项目:**
        • **对基础页面进行删减:**
        • **创建登录组件:**
        • **为了保证能访问到需要进行路由转发(index.js)**
        • **开发login组件:**
        • 创建了全局的css样式global.css
        • 登录页面成功显示:
        • 设置列表前面的搜索框
      • 样式添加:
        • 在global.css设置了登录容器的大小即为可视化窗口的大小
        • 在login.vue中设置了容器的高度大小为可视化窗口的100%
        • 设置了form表单样式:
        • 设置了log区域的div样式:
      • 添加用户登录表单非空前验证:
        • 添加属性:
        • 并且在对应的表单中绑定了对应的事件
        • **由于我使用的是vue3导致使用的挂载方法不一致,且挂载axios有先后顺序,必须在访问app之前挂载**
        • **在密码框添加了防可见**
        • 为了验证按钮点了之后是否生效我加了验证的日志
        • 登录显示后端数据测试
        • 添加了点击登录按钮后提示的消息框
        • 添加home首页创建home首页
        • 在home页面写上基本框架
        • 创建user对象进行封装(get,Set):
        • 创建了一个登录控制器:
        • 到这实体用户User的自动封装,自动创建,已经完成
        • 导入json特殊字符串,形成json对象
        • 在成功点击登录后,在浏览器调试页面查看会话中的存储数据,点击登录之后会在调试页面生成key 和值,在点击退出之后这些数据也不会清除,这样的安全性大大下降
        • 设置了路由守卫(index.js)
      • 设置home页面的布局
        • 在elemenet中找到containerd 容器布置器
          • 布局设置:
          • 并在style中设置了布局样式
          • 在侧边栏里面添加了图标
      • 添加了注册按钮:
        • 在set中设置了register注册方法
        • 在return中设置了返回函数
        • 在路由中导入了注册的路径
        • 设置了重定向的组件和路径
        • controller层
        • dao层来访问数据层
        • uesrmapper.xml文件
      • 重新设置了home主页的布局
        • 设置了分界线在用户量,和用户状态上
        • 直接显示用户名
        • 我准备在我的用户量界面查询数据库信息然后通过图表显示在界面
          • 查询数据的映射文件:
        • 打算在用户状态里面画出用户名,和用户状态显示出他的状态开关和用户等级,并且支持用户状态的修改,在添加一个可以删除用户的按钮
          • 现在需要在用户等级为用户的加上他的会员时间,需要有个起始时间,和截至时间,以天为单位
        • 问题:

重新设置了home主页的布局

 
退出 用户量 用户状态

设置了分界线在用户量,和用户状态上


                    
                        用户量
                        
                        
                        用户状态
                    
                

直接显示用户名

image-20230731212157667

将在点击用户量时,显示图标的功能去掉

项目报错问题解决的思路

在一次打开项目的时候发现有问题由于没有截图保存

在查看前端问题是发现是axios跨域处理有问题

在后端的报错发现是

User user1 = userDao.GetUserByMessage(user.getUsername(), user.getPassword());

这行有问题

我去看了我的dao层发现在GetUserByMessage发现这个方法有问题

我去查看了我的xml映射文件修改了我的dao层位置和user的位置,重新运行的程序发现还是不行

在日志中发现我的数据库链接池可能有问题,我重新写了一次我的数据库驱动,

```xml
**driver-class-name**: com.mysql.cj.jdbc.Driver
```

重新跑了一次程序发现成功运行

我准备在我的用户量界面查询数据库信息然后通过图表显示在界面

我想的是在后端查询到用户量按月份统计

健康系统练习_第94张图片

在数据库查询到的数据,然后通过dao层,通过控制器,返回给前端,在前端绘制图表

查询数据的映射文件:
   <select id="GetUserByMessage" resultType="com.healthsystem.portplay.bean.User">
        select *
        from `user`
        where username = #{username}
          and password = #{password}
          and state = 1;
    select>

dao层将查询到的数据转到一个集合里面,包括,用户量,月份

List<Map<String,Object>>GetUserCountByMonth();

再通过控制器将集合里面的数据返回给前端


    // 获取用户数量的控制器方法
    @GetMapping("/countByMonth")
    public List<Map<String,Object>>GetUserCountByMonth(){
        return userDao.GetUserCountByMonth();
    }

前端绘制图表并在打开页面就直接加载

		
        

          
import axios from "axios"; import { Chart } from "chart.js"; const chartCanvasRef = ref(null); // 使用 ref() 函数声明 chartCanvasRef 变量 // 发送获取用户数量数据请求并绘制图表 async function fetchUserCount() { try { // 向 "/countByMonth" 端点发起 GET 请求以获取用户数量数据 const response = await axios.get("/countByMonth"); // 从响应中提取用户数量数据 const userCount = response.data; // 从用户数量数据中提取月份标签和用户数量 const monthLabels = userCount.map((data) => data.month); const userCounts = userCount.map((data) => data.user_count); // 获取用于绘制图表的 Canvas 上下文 const ctx = chartCanvasRef.value.getContext("2d"); // 使用 Chart.js 库创建一个新的条形图 new Chart(ctx, { type: "bar", // 使用 "bar" 类型绘制条形图 data: { labels: monthLabels, // 使用月份标签作为 X 轴 datasets: [ { label: "用户数量", // 数据集的标签 data: userCounts, // 用户数量数据作为 Y 轴 backgroundColor: "rgba(75, 192, 192, 0.2)", // 条形图的背景颜色 borderColor: "rgba(75, 192, 192, 5)", // 条形图的边框颜色 borderWidth: 1, // 条形图的边框宽度 }, ], }, options: { scales: { x: { type: "category", // 使用 "category" 类型作为 X 轴的标尺 labels: monthLabels, // 使用月份标签作为 X 轴标尺上的刻度 }, y: { beginAtZero: true, // Y 轴从零开始 }, }, }, }); } catch (error) { console.error("Error fetching user count:", error); } } // 页面加载时就自动显示用户量统计图表 onMounted(fetchUserCount);

健康系统练习_第95张图片

打算在用户状态里面画出用户名,和用户状态显示出他的状态开关和用户等级,并且支持用户状态的修改,在添加一个可以删除用户的按钮

在vue3的官网,找到对应的开关的样式在测试页面做好测试

image-20230808124724482

这个就是我需要的状态按钮的开关

 

需要的是在点击了开关之后需要对value的值进行更新,我在测试页面对他进行了他操作







image-20230808125218954

image-20230808125231080

在这里我实现了开关打开的状态和关闭的切换

现在需要在用户等级为用户的加上他的会员时间,需要有个起始时间,和截至时间,以天为单位

已经在数据库里面添加了对应的会员的时间跨度

image-20230808170059212

只需要按照用户名来区分,并且每个用户都要包括用户名、角色、状态、起始时间和结束时间,

SELECT
    username,
    role,
    state,
    startTime,
    endTime
FROM
    user
ORDER BY
    username;

image-20230808170205794

我在测试页面已经加上了状态转换的

问题:

将用户信息检索出来放入表中,设置了开关按钮,但是发现开关或者只能打开状态,关闭,不能关闭或者打开。经过几次排查,发现在点击了开关,让其关闭时候,我后端的update信息携带的state:1,不是我想要的0

image-20230810211653238

我点击关闭了

image-20230810211720358

等到轮询,发现状态为改变

image-20230810211751043

在浏览器开发环境发现我的后端的updatestate

健康系统练习_第96张图片

关闭是0

出问题代码

image-20230810211930911

修改后

image-20230810212123101

代码更新了,点击关闭

image-20230810212207310

我的update也正常了

健康系统练习_第97张图片

功能成功了后,加入主页面

表单界面|


          
用户名 等级 开始时间 截止时间 状态
{{ user.username }} {{ user.role }} {{ user.startTime }} {{ user.endTime }}
import { ref, onMounted, onBeforeUnmount } from "vue";
//菜单2
const userStatechartCanvasRef = ref(null);
const users = ref([]);
// 在组件挂载前调用异步函数,获取用户名信息
// 定时器,每隔一段时间获取用户信息
let pollingInterval;
onMounted(async () => {
  try {
    // 页面加载时就自动显示用户量统计图表1
    fetchUserCount();
    // 在组件挂载前调用异步函数,获取用户名信息1
    getUserInfo();
    // 初始化时立即获取一次用户信息2
    await fetchUserInfo();
    // 设置定时器,每隔 5毫秒秒获取一次用户信息2
    pollingInterval = setInterval(fetchUserInfo, 5000); // 每 5毫 秒轮询一次
    drawChart();
  } catch (error) {
    console.error("Error fetching user information:", error);
  }
});
// onMounted(getUserInfo);
// 获取用户信息,在菜单2中的
async function fetchUserInfo() {
  try {
    const response = await axios.get("/UserInfo");
    users.value = response.data;
  } catch (error) {
    console.error("Error fetching user information:", error);
  }
}
// 使用 Chart.js 或其他绘图库绘制图表,
// 根据数据进行绘制菜单2中
function drawChart(canvasRef) {
  if (canvasRef) {
    const ctx = canvasRef.getContext("2d");
  }
}
// 用户状态的切换,菜单2中
function handleSwitchChange(user) {
  const newState = user.state ? 1 : 0;
  updateDatabaseState(user.username, newState)
    .then(() => {
      // Update the user's state locally
      user.state = newState;
    })
    .catch((error) => {
      console.error("Error updating state:", error);
    });
}
// 将状态信息推送到后端,菜单2中
async function updateDatabaseState(username, newState) {
  try {
    const response = await axios.put("/updateState", {
      username: username,
      state: newState,
    });
    return response.data;
  } catch (error) {
    throw error;
  }
}

// 在组件被销毁前清除定时器,菜单2中
onBeforeUnmount(() => {
  clearInterval(pollingInterval);
});

其中有菜单1的,有12 标注
// 菜单2样式
table {
  border-collapse: collapse;
  width: 100%;
}

th,
td {
  border: 1px solid #55d515;
  padding: 8px;
  text-align: left;
}

th {
  background-color: #35e51e;
}

健康系统练习_第98张图片

添加分页功能,他的数据展示在下页展示

健康系统练习_第99张图片

添加了一个修改时间,时间是以天为单位来计算的

image-20230811222846081

   
            
          
          
            
          
// 更新用户时间信息2
function updateTime(user) {
  const NewstartTime = user.startTime;
  const NewendTime = user.endTime;
  updateDatabaseTime(user.username, NewstartTime, NewendTime)
    .then(() => {
      // Time updated successfully
      user.startTime = NewstartTime;
      user.endTime = NewendTime;
    })
    .catch((error) => {
      console.error("Error updating time:", error);
    });
}
// 将时间信息推送到后端
async function updateDatabaseTime(username, NewstartTime, NewendTime) {
  try {
    const response = await axios.put("/updateTime", {
      username: username,
      startTime: NewstartTime,
      endTime: NewendTime,
    });
    return response.data;
  } catch (error) {
    throw error;
  }
}

为了判断用户是否过期,想使用springboot中的定时任务来检查数据库中的用户时间信息是否过期,当你在Spring中创建一个 @Component 类时,它会被自动识别为一个Spring管理的组件。在你的情况下,你可以创建一个带有定时任务的组件,用来检查和更新用户状态。

@Component
public class CheckUserTimeSchedule {
    private final UserDao userDao;

    @Autowired
    public CheckUserTimeSchedule(UserDao userDao) {
        this.userDao = userDao;
    }

    @Scheduled(fixedRate = 30000)
    public void checkAndUpdateUserStatus() {
        List<Map<String, Object>> usersMapList = userDao.GetUserInfo(); // 获取所有用户信息

        LocalDate currentDate = LocalDate.now();

        for (Map<String, Object> userMap : usersMapList) {
            String username = (String) userMap.get("username");
            LocalDate endTime = (LocalDate) userMap.get("endTime");

            if (endTime != null && endTime.isBefore(currentDate)) {
                // 用户的截止时间已过期,将状态更新为 false(已过期)
                userDao.updateUserState(username, false);
            }
        }
        System.out.println("检查并更新用户状态");
    }
}

创建一个员工表用来统计员工打卡情况

-- 创建员工表
CREATE TABLE employee (
    id INT NOT NULL,
    username VARCHAR(255) NOT NULL,
    sign_in DATETIME,
    PRIMARY KEY (id, username),
    FOREIGN KEY (id) REFERENCES user(id)
);

给表中插入用户等级为管理员的

insert into employee(id, username, sign_in) select id, username, null from user where role = '普通管理员';

健康系统练习_第100张图片

员工 签到记录
{{ Employee.username }} {{ Employee.sign_in }}
// 菜单3
const chartCanvasRefe = ref(null);
const Employees = ref([]);
pollingInterval = setInterval(pollEmployeeInfo, 60 * 1000); //每 1分钟 秒轮询一次
// 使用 Chart.js 或其他绘图库绘制图表,
// 根据数据进行绘制菜单2中
function drawChart(canvasRef, canvasRefe) {
  if (activeMenu === "1" && canvasRef) {
    const ctx = canvasRef.getContext("2d");
  }
  if (activeMenu === "3" && canvasRefe) {
    const ctx1 = canvasRefe.getContext("2d");
  }
}
// 获取员工信息,3
async function fetchEmployeeInfo() {
  try {
    const response = await axios.get("/employeeInfo");
    Employees.value = response.data;
  } catch (error) {
    console.error("Error fetching Employee information:", error);
  }
}
<select id="GetEmployeeInfo" parameterType="com.healthsystem.portplay.bean.Employee">
        select username, sign_in
        from employee
        order by username;
    select>
 List<Map<String, Object>> GetEmployeeInfo();
package com.healthsystem.portplay.controller;

import com.healthsystem.portplay.dao.UserDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;
import java.util.Map;

@RestController
public class EmployeeInfo {
private final UserDao userDao;
@Autowired
    public EmployeeInfo(UserDao userDao){this.userDao=userDao;}
    @GetMapping("/employeeInfo")
    public List<Map<String,Object>>GetEmployeeInfo(){
    return userDao.GetEmployeeInfo();
    }
}

为了区分普通管理员,和超级管理员,我添加了一个新的页面只用来显示,等级为用户的页面






他的功能是和超级用户差不多的

在菜单4中查询了数据库信息中的分店信息

设置了分页处理和菜单2一样,就不展示了

到这简单的前后端分离项目已经完成,只是记录自己的学习,欢迎大佬指正
t(“/updateState”, {
username: username,
state: newState,
});
return response.data;
} catch (error) {
throw error;
}
}
// 计算当前页显示的用户列表,2
const displayedUsers = computed(() => {
const startIndex = (currentPage.value - 1) * pageSize.value;
const endIndex = startIndex + pageSize.value;
return users.value.slice(startIndex, endIndex);
});

// 处理分页改变事件,2
function handlePageChange(newPage) {
currentPage.value = newPage;
}
// 更新用户时间信息2
function updateTime(user) {
const NewstartTime = user.startTime;
const NewendTime = user.endTime;
updateDatabaseTime(user.username, NewstartTime, NewendTime)
.then(() => {
// Time updated successfully
user.startTime = NewstartTime;
user.endTime = NewendTime;
})
.catch((error) => {
console.error(“Error updating time:”, error);
});
}
// 将时间信息推送到后端,2
async function updateDatabaseTime(username, NewstartTime, NewendTime) {
try {
const response = await axios.put(“/updateTime”, {
username: username,
startTime: NewstartTime,
endTime: NewendTime,
});
return response.data;
} catch (error) {
throw error;
}
}
// 在组件被销毁前清除定时器,菜单2中
onBeforeUnmount(() => {
clearInterval(pollingInterval);
});


他的功能是和超级用户差不多的

在菜单4中查询了数据库信息中的分店信息

设置了分页处理和菜单2一样,就不展示了

到这简单的前后端分离项目已经完成,只是记录自己的学习,欢迎大佬指正

你可能感兴趣的:(java,javaweb,java,tomcat,spring,boot,vue)