[免费]微信小程序医院预约挂号管理系统(uni-app+SpringBoot后端+Vue管理端)【论文+源码+SQL脚本】

news2025/7/16 10:31:25

大家好,我是java1234_小锋老师,看到一个不错的微信小程序医院预约挂号管理系统(uni-app+SpringBoot后端+Vue管理端),分享下哈。

项目视频演示

【免费】微信小程序医院预约挂号管理系统(uni-app+SpringBoot后端+Vue管理端) Java毕业设计_哔哩哔哩_bilibili

项目介绍

本毕业设计的内容是设计并且实现一个基于java技术的医院预约挂号管理系统。它是在Windows下,以MYSQL为数据库开发平台,java技术和Tomcat网络信息服务作为应用服务器。医院预约挂号管理系统的功能已基本实现,主要实现首页、个人中心、用户管理、专家管理、科室类型管理、科室信息管理、预约信息管理、取消信息管理、系统管理等功能的操作系统。

论文主要从系统的分析与设计、数据库设计和系统的详细设计等几个方面来进行论述,系统分析与设计部分主要论述了系统的功能分析、系统的设计思路,数据库设计主要论述了数据库的设计,系统的详细设计部分主要论述了几个主要模块的详细设计过程。

系统展示

部分代码

package cn.test.hospital.service.impl;

import cn.test.hospital.common.security.AccountDetails;
import cn.test.hospital.common.security.JwtTokenUtil;
import cn.test.hospital.dto.param.PowerAccountRegisterParam;
import cn.test.hospital.dto.param.PowerAccountStatusParam;
import cn.test.hospital.dto.param.UserRegisterParam;
import cn.test.hospital.entity.*;
//import cn.test.hospital.hospital.entity.*;
import cn.test.hospital.mapper.PowerAccountMapper;
import cn.test.hospital.mapper.PowerAccountRoleRelationMapper;
import cn.test.hospital.mapper.dao.PowerAccountRoleRelationDao;
import cn.test.hospital.service.ILogAccountLoginService;
import cn.test.hospital.service.IPowerAccountService;
import cn.test.hospital.service.IUserBasicInfoService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Optional;

/**
 * @author  admin
 */

@Service
public class PowerAccountServiceImpl implements IPowerAccountService {

    private static final Logger LOGGER = LoggerFactory.getLogger(PowerAccountServiceImpl.class);

    /**
     * 一个空格字符
     */
    private static final String BLANK_SPACE = " ";

    @Resource
    private JwtTokenUtil jwtTokenUtil;

    @Resource
    private PasswordEncoder passwordEncoder;

    @Value("${jwt.tokenHead}")
    private String tokenHead;

    @Resource
    private UserDetailsService userDetailsService;

    @Resource
    private PowerAccountMapper accountMapper;

    @Resource
    private PowerAccountRoleRelationDao accountRoleRelationDao;

    @Resource
    private PowerAccountRoleRelationMapper accountRoleRelationMapper;

    @Resource
    private ILogAccountLoginService logAccountLoginService;

    @Resource
    private IUserBasicInfoService userBasicInfoService;

    /**
     * 获取帐号信息
     *
     * @param name 帐号名
     * @return 帐号信息
     */
    @Override
    public Optional<PowerAccount> getByName(String name) {

        PowerAccountExample example = new PowerAccountExample();

        example.createCriteria()
                .andNameEqualTo(name);

        return Optional.ofNullable(accountMapper.selectByExample(example).get(0));
    }

    /**
     * 刷新token
     *
     * @param oldToken 原来的token
     * @return 新token
     */
    @Override
    public String refreshToken(String oldToken) {
        return jwtTokenUtil.refreshHeadToken(oldToken);
    }

    /**
     * 判断用户名是否已使用
     *
     * @param name 用户名
     * @return 是否存在
     */
    @Override
    public boolean count(String name) {
        PowerAccountExample example = new PowerAccountExample();

        example.createCriteria()
                .andNameEqualTo(name);

        return accountMapper.countByExample(example) > 0;
    }

    /**
     * 判断用户是否存在
     *
     * @param id 用户编号
     * @return 是否存在
     */
    @Override
    public boolean count(Long id) {
        PowerAccountExample example = new PowerAccountExample();

        example.createCriteria()
                .andIdEqualTo(id);

        return accountMapper.countByExample(example) > 0;
    }

    /**
     * 注册普通用户账号
     *
     * @param param 用户账号注册参数(账号,密码)
     * @return 是否成功
     */
    @Override
    public boolean registerUser(UserRegisterParam param) {
        PowerAccount account = new PowerAccount();

        account.setName(param.getPhone());
        account.setPassword(passwordEncoder.encode(param.getPassword()));
        account.setStatus(1);

        account.setGmtCreate(new Date());
        account.setGmtModified(new Date());

        if (accountMapper.insertSelective(account) > 0) {

            if (userBasicInfoService.insert(param)) {
                return true;
            } else {
                // 注册失败删除账号信息
                delete(param.getPhone());
                return false;
            }
        }

        return false;
    }

    /**
     * 管理账号注册功能
     *
     * @param param 账号注册参数(账号,密码)
     * @return 是否成功
     */
    @Override
    public boolean registerAdmin(PowerAccountRegisterParam param) {
        PowerAccount account = new PowerAccount();

        account.setName(param.getName());
        account.setPassword(passwordEncoder.encode(param.getPassword()));
        account.setStatus(1);

        account.setGmtCreate(new Date());
        account.setGmtModified(new Date());

        return accountMapper.insertSelective(account) > 0;
    }

    /**
     * 登录后返回 jwt 字符串
     *
     * @param name     帐号名
     * @param password 密码
     * @return 生成的JWT的token
     */
    @Override
    public Optional<String> login(String name, String password) {

        String jwt = null;

        // 客户端加密后传递账号密码
        try {
            UserDetails userDetails = userDetailsService.loadUserByUsername(name);

            // 密码不正确
            if (!passwordEncoder.matches(password, userDetails.getPassword())) {

                LOGGER.info("user :{} login fail , wrong password .", name);
                throw new BadCredentialsException("密码不正确");
            }

            UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails,
                    null, userDetails.getAuthorities());

            SecurityContextHolder.getContext().setAuthentication(authentication);

            String token = jwtTokenUtil.generateToken(userDetails);

            // 这里需要记录登录时间
            updateLoginTime(name);
            logAccountLoginService.insert(name);

            // 注意中间用空格隔开
            jwt = tokenHead + BLANK_SPACE + token;

        } catch (AuthenticationException e) {
            LOGGER.warn("user :{} , login fail :{}", name, e.getMessage());
        }


        return Optional.ofNullable(jwt);
    }

    /**
     * 检查密码是否正确
     *
     * @param id       账号编号
     * @param password 账号密码
     * @return 是否正确
     */
    @Override
    public boolean checkPassword(Long id, String password) {

        PowerAccount account = accountMapper.selectByPrimaryKey(id);

        return passwordEncoder.matches(password, account.getPassword());
    }

    /**
     * 删除账号
     *
     * @param name 账号名
     * @return 是否成功
     */
    @Override
    public boolean delete(String name) {
        PowerAccountExample example = new PowerAccountExample();

        example.createCriteria()
                .andNameEqualTo(name);

        return accountMapper.deleteByExample(example) > 0;
    }

    /**
     * 更新账号状态
     *
     * @param param 账号编号、账号状态(1:开启,0:关闭)
     * @return 是否成功
     */
    @Override
    public boolean updateStatus(PowerAccountStatusParam param) {
        PowerAccount account = new PowerAccount();

        account.setId(param.getAccountId());
        account.setStatus(param.getStatus());

        account.setPassword(null);
        account.setGmtModified(new Date());

        return accountMapper.updateByPrimaryKeySelective(account) > 0;
    }

    /**
     * 修改用户角色关系
     *
     * @param accountId  帐号id
     * @param roleIdList 角色id列表
     * @return 成功记录
     */
    @Override
    public int updateRole(Long accountId, List<Long> roleIdList) {
        int count = roleIdList == null ? 0 : roleIdList.size();

        //先删除原来的关系
        PowerAccountRoleRelationExample accountRoleRelationExample = new PowerAccountRoleRelationExample();

        accountRoleRelationExample.createCriteria()
                .andAccountIdEqualTo(accountId);

        accountRoleRelationMapper.deleteByExample(accountRoleRelationExample);

        //建立新关系
        if (!CollectionUtils.isEmpty(roleIdList)) {

            List<PowerAccountRoleRelation> list = new ArrayList<>();

            for (Long roleId : roleIdList) {
                PowerAccountRoleRelation roleRelation = new PowerAccountRoleRelation();
                roleRelation.setAccountId(accountId);
                roleRelation.setRoleId(roleId);
                list.add(roleRelation);
            }

            accountRoleRelationDao.insertList(list);
        }

        return count;
    }

    /**
     * 更新密码
     *
     * @param accountId 帐号编号
     * @param password  密码
     * @return 更新结果
     */
    @Override
    public boolean updatePassword(Long accountId, String password) {
        PowerAccount account = new PowerAccount();

        account.setId(accountId);
        account.setPassword(passwordEncoder.encode(password));
        account.setGmtModified(new Date());

        return accountMapper.updateByPrimaryKeySelective(account) > 0;
    }

    /**
     * 通过用户账号名称,获取用户详情
     *
     * @param userName 用户账号名称
     * @return 用户详情
     */
    @Override
    public UserDetails loadUserByUserName(String userName) {
        Optional<PowerAccount> accountOptional = getByName(userName);

        if (accountOptional.isPresent()) {
            PowerAccount account = accountOptional.get();

            List<PowerResource> resourceList = listResource(account.getId());

            return new AccountDetails(account, resourceList);
        }

        throw new UsernameNotFoundException("用户名或密码错误!");
    }

    /**
     * 通过账号编号,获取资源列表
     *
     * @param accountId 账号编号
     * @return 资源列表
     */
    @Override
    public List<PowerResource> listResource(Long accountId) {
        return accountRoleRelationDao.getResourceList(accountId);
    }

    /**
     * 更新最后登录时间
     *
     * @param name 用户名称
     */
    @Override
    public void updateLoginTime(String name) {
        Optional<PowerAccount> accountOptional = getByName(name);

        // 账号存在
        if (accountOptional.isPresent()) {
            PowerAccount account = accountOptional.get();

            account.setPassword(null);
            account.setLoginTime(new Date());

            accountMapper.updateByPrimaryKeySelective(account);
        }
    }

}
<template>
  <div class="background">
    <el-form :model="ruleForm2" :rules="rules2" ref="ruleForm2" label-position="left"
             label-width="0px" class="demo-ruleForm login-container login-background">
      <h3 class="title">挂号系统后台管理中心</h3>
      <el-form-item prop="username">
        <el-input type="text" v-model="ruleForm2.username" auto-complete="off"
                  placeholder="账号" suffix-icon="el-icon-user-solid"></el-input>
      </el-form-item>
      <el-form-item prop="password">
        <el-input type="password" v-model="ruleForm2.password" auto-complete="off"
                  placeholder="密码" suffix-icon="el-icon-lock"></el-input>
      </el-form-item>
      <el-checkbox v-model="checked" checked class="remember">记住密码</el-checkbox>
      <el-form-item style="width:100%;">
        <el-button type="primary" style="width:100%;" @click="handleSubmit2" :loading="loading">登录</el-button>
       
      </el-form-item>
    </el-form>
  </div>
</template>

<script>
  import {getCookie, setCookie} from "@/utils/cookies";
  import {getPermission} from "@/permission";
  import {getToken} from "@/utils/auth";

  export default {
    name: "login",
    data(){
      return{
        loading: false,
        ruleForm2: {
          username: '',
          password: ''
        },
        rules2: {
          username: [{ required: true, message: '请输入账号',trigger: 'blur'}],
          password: [{required: true,message: '请输入密码',trigger: 'blur'}]
        },
        checked: false,
        redirect: undefined
      }
    },
    watch: {
      $route: {
        handler: function(route) {
          this.redirect = route.query && route.query.redirect
        },
        immediate: true
      }
    },
    methods: {
      handleSubmit2(ev) {
        var _this = this;
        _this.$refs.ruleForm2.validate((valid) => {
          if (valid) {
            _this.loading = true;

            // 实现登录
              this.$store.dispatch('Login', this.ruleForm2).then(() => {
              if (this.checked) {
                setCookie("username",this.ruleForm2.username,15);
                setCookie("password",this.ruleForm2.password,15);
              }

              _this.$router.push({path: this.redirect || '/home'});
              _this.loading = false

            }).catch(() => {
              _this.loading = false;
              _this.$alert('用户名或密码错误!', '提示信息', {
                confirmButtonText: '确定'
              });
            })
          } else {
            console.log('error submit!!');
            return false;
          }
        });

      }
    },
    created() {
      this.ruleForm2.username = getCookie('username');
      this.ruleForm2.password = getCookie('password');
      if(this.ruleForm2.username === undefined||this.ruleForm2.username==null||this.ruleForm2.username===''){
        this.ruleForm2.username = 'admin';
      }
      if(this.ruleForm2.password === undefined||this.ruleForm2.password==null){
        this.ruleForm2.password = '';
      }
    }
  }
</script>

<style scoped>
  .background{
    width: 100%;
    height: 100%;
    background: url("../.././assets/background.jpg") no-repeat;
    background-size: 100% 100%;
    position: fixed;
    top: 0px;
    left: 0px;
  }
  .login-container{
    -webkit-border-radius: 5px;
    border-radius: 5px;
    -moz-border-radius: 5px;
    background-clip: padding-box;
    margin: 180px auto;
    width: 350px;
    padding: 35px 35px 15px;
    background: #BED2F5;
    /*border: 1px solid #eaeaea;*/
    box-shadow: 0 0 25px #A7BBD4;
  }

  label.el-checkbox.remember {
    margin: 0px 0px 30px 0px;
  }
  .title{
    color: #ffffff;
  }
</style>

源码下载

链接:https://pan.baidu.com/s/1zn70zMBz6Mmf_Kvg0O7avA
提取码:1234

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

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

相关文章

【网络入侵检测】基于源码分析Suricata的IP分片重组

【作者主页】只道当时是寻常 【专栏介绍】Suricata入侵检测。专注网络、主机安全&#xff0c;欢迎关注与评论。 目录 目录 1.概要 2. 配置信息 2.1 名词介绍 2.2 defrag 配置 3. 代码实现 3.1 配置解析 3.1.1 defrag配置 3.1.2 主机系统策略 3.2 分片重组模块 3.2.1…

LVGL简易计算器实战

文章目录 &#x1f4c1; 文件结构建议&#x1f539; eval.h 表达式求值头文件&#x1f539; eval.c 表达式求值实现文件&#xff08;带详细注释&#xff09;&#x1f539; ui.h 界面头文件&#x1f539; ui.c 界面实现文件&#x1f539; main.c 主函数入口✅ 总结 项目效果&…

代码随想录算法训练营第60期第三十四天打卡

大家好&#xff0c;我们今天的内容依旧是贪心算法&#xff0c;我们上次的题目主要是围绕多维问题&#xff0c;那种时候我们需要分开讨论&#xff0c;不要一起并发进行很容易顾此失彼&#xff0c;那么我们今天的问题主要是重叠区间问题&#xff0c;又是一种全新的贪心算法思想&a…

关于IDE的相关知识之二【插件推荐】

成长路上不孤单&#x1f60a;&#x1f60a;&#x1f60a;&#x1f60a;&#x1f60a;&#x1f60a; 【14后&#x1f60a;///计算机爱好者&#x1f60a;///持续分享所学&#x1f60a;///如有需要欢迎收藏转发///&#x1f60a;】 今日分享关于ide插件推荐的相关内容&#xff01…

Axure RP9:列表新增

文章目录 列表新增思路新增按钮操作说明保存新增交互设置列表新增 思路 利用中继器新增行实现列表新增功能 新增按钮操作说明 工具栏中添加新增图标及标签,在图标标签基础上添加热区;对热区添加鼠标单击时交互事件,同步插入如下动作:显示/隐藏动作,设置目标元件为新增窗…

06 mysql之DML

一、什么是DML DML 用于操作数据库中的数据。主要命令包括&#xff1a; INSERT&#xff1a;添加数据SELECT&#xff1a;查询数据UPDATE&#xff1a;修改数据DELETE&#xff1a;删除数据 二、插入数据&#xff08;INSERT&#xff09; 2.1 插入单条记录 -- 插入学生记录&…

【最新版】likeshop连锁点餐系统-PHP版+uniapp前端全开源

一.系统介绍 likeshop外卖点餐系统适用于茶饮类的外卖点餐场景&#xff0c;搭建自己的一点点、奈雪、喜茶点餐系统。 系统基于总部多门店的连锁模式&#xff0c;拥有门店独立管理后台&#xff0c;支持总部定价和门店定价LBS定位点餐&#xff0c;可堂食可外卖。无论运营还是二开…

纯Java实现反向传播算法:零依赖神经网络实战

在深度学习框架泛滥的今天,理解算法底层实现变得愈发重要。反向传播(Backpropagation)作为神经网络训练的基石算法,其实现往往被各种框架封装。本文将突破常规,仅用Java标准库实现完整BP算法,帮助开发者: 1) 深入理解BP数学原理。2) 掌握面向对象的神经网络实现。3) 构建可…

海纳思(Hi3798MV300)机顶盒遇到海思摄像头

海纳思机顶盒遇到海思摄像头&#xff0c;正好家里有个海思Hi3516的摄像头模组开发板&#xff0c;结合机顶盒来做个录像。 准备工作 海纳斯机顶盒摄像机模组两根网线、两个电源、路由器一块64G固态硬盘 摄像机模组和机顶盒都接入路由器的LAN口&#xff0c;确保网络正常通信。 …

Axure应用交互设计:表格跟随菜单移动效果(超长表单)

亲爱的小伙伴,在您浏览之前,烦请关注一下,在此深表感谢!本文如有帮助请订阅 Axure产品经理精品视频课已登录CSDN可点击学习https://edu.csdn.net/course/detail/40420 课程主题:表格跟随菜单移动 主要内容:表格交互设计、动态面板嵌套、拖动时事件、移动动作 应用场景…

7系列 之 I/O标准和终端技术

背景 《ug471_7Series_SelectIO.pdf》介绍了Xilinx 7 系列 SelectIO 的输入/输出特性及逻辑资源的相关内容。 第 1 章《SelectIO Resources》介绍了输出驱动器和输入接收器的电气特性&#xff0c;并通过大量实例解析了各类标准接口的实现。 第 2 章《SelectIO Logic Resource…

github 上的 CI/CD 的尝试

效果 步骤 新建仓库设置仓库的 page 新建一个 vite 的项目&#xff0c;改一下 vite.config.js 中的 base 工作流 在项目的根目录下新建一个 .github/workflows/ci.yml 文件&#xff0c;然后编辑一下内容 name: Build & Deploy Vue 3 Appon:push:branches: [main]permi…

yup 使用 3 - 利用 meta 实现表单字段与表格列的统一结构配置(适配 React Table)

yup 使用 3 - 利用 meta 实现表单字段与表格列的统一结构配置&#xff08;适配 React Table&#xff09; Categories: Tools Last edited time: May 11, 2025 7:45 PM Status: Done Tags: form validation, schema design, yup 本文介绍如何通过 Yup 的 meta() 字段&#xff0…

【OpenCV】imread函数的简单分析

目录 1.imread()1.1 imread()1.2 imread_()1.2.1 查找解码器&#xff08;findDecoder&#xff09;1.2.2 读取数据头&#xff08;JpegDecoder-->readHeader&#xff09;1.2.2.1 初始化错误信息&#xff08;jpeg_std_error&#xff09;1.2.2.2 创建jpeg解压缩对象&#xff08;…

【Linux实践系列】:进程间通信:万字详解共享内存实现通信

&#x1f525; 本文专栏&#xff1a;Linux Linux实践项目 &#x1f338;作者主页&#xff1a;努力努力再努力wz &#x1f4aa; 今日博客励志语录&#xff1a; 人生就像一场马拉松&#xff0c;重要的不是起点&#xff0c;而是坚持到终点的勇气 ★★★ 本文前置知识&#xff1a; …

【笔记】BCEWithLogitsLoss

工作原理 BCEWithLogitsLoss 是 PyTorch 中的一个损失函数&#xff0c;用于二分类问题。 它结合了 Sigmoid 激活函数和二元交叉熵&#xff08;Binary Cross Entropy, BCE&#xff09;损失在一个类中。 这不仅简化了代码&#xff0c;而且通过数值稳定性优化提高了模型训练的效…

关于Go语言的开发环境的搭建

1.Go开发环境的搭建 其实对于GO语言的这个开发环境的搭建的过程&#xff0c;类似于java的开发环境搭建&#xff0c;我们都是需要去安装这个开发工具包的&#xff0c;也就是俗称的这个SDK&#xff0c;他是对于我们的程序进行编译的&#xff0c;不然我们写的这个代码也是跑不起来…

Flutter PIP 插件 ---- 为iOS 重构PipController, Demo界面,更好的体验

接上文 Flutter PIP 插件 ---- 新增PipActivity&#xff0c;Android 11以下支持自动进入PIP Mode 项目地址 PIP&#xff0c; pub.dev也已经同步发布 pip 0.0.3&#xff0c;你的加星和点赞&#xff0c;将是我继续改进最大的动力 在之前的界面设计中&#xff0c;还原动画等体验一…

数据库管理-第325期 ADG Failover后该做啥(20250513)

数据库管理325期 2025-05-13 数据库管理-第325期 ADG Failover后该做啥&#xff08;20250513&#xff09;1 故障处置2 恢复原主库3 其他操作总结 数据库管理-第325期 ADG Failover后该做啥&#xff08;20250513&#xff09; 作者&#xff1a;胖头鱼的鱼缸&#xff08;尹海文&a…

SQLi-Labs 第21-24关

Less-21 http://127.0.0.1/sqli-labs/Less-21/ 1&#xff0c;抓个请求包看看 分析分析cookie被base64URL编码了&#xff0c;解码之后就是admin 2&#xff0c;那么这个网站的漏洞利用方式也是和Less-20关一样的&#xff0c;只是攻击语句要先base64编码&#xff0c;再URL编码&…