尚医通-手机登录-判断用户登录状态-用户网关整合(三十)

news/2025/1/12 10:56:36/

目录:

(1)前台用户系统-手机登录-前端整合

 (2)全局的登录事件-判断登录状态

 (3)登录注册-用户认证和网关整合


(1)前台用户系统-手机登录-前端整合

service-user模块的配置文件前面忘了配置Redis的配置,加上:

点击登录之后,再操作页面的其他部分,会判断当前的登录状态,在前端用一个对象叫做Cookie,登录之后把内容放到Cookie中,判断Cookie中是否有这个信息  

创建访问接口:userInfo.js 

 

import request from '@/utils/request'const api_name = `/api/user`export default {login(userInfo) {return request({url: `${api_name}/login`,method: `post`,data: userInfo})}
}

 创建发送短信的访问接口msm.js:

import request from '@/utils/request'const api_name = `/api/msm`export default {sendCode(mobile) {return request({url: `${api_name}/send/${mobile}`,method: `get`})}
}

 用户的前端主页面访问default.vue,这个页面进行了查分,头、中间内容、尾,登录的部分在头页面里面myheader.vue里面:

在myheader.vue中继续添加弹出框:

<template><div class="header-container"><div class="wrapper"><!-- logo --><div class="left-wrapper v-link selected"><img style="width: 50px" width="50" height="50" src="~assets/images/logo.png"><span class="text">尚医通 预约挂号统一平台</span></div><!-- 搜索框 --><div class="search-wrapper"><div class="hospital-search animation-show"><el-autocompleteclass="search-input small"prefix-icon="el-icon-search"v-model="hosname":fetch-suggestions="querySearchAsync"placeholder="点击输入医院名称"@select="handleSelect"><span slot="suffix" class="search-btn v-link highlight clickable selected">搜索 </span></el-autocomplete></div></div><!-- 右侧 --><!-- 右侧 --><div class="right-wrapper"><span class="v-link clickable">帮助中心</span><span v-if="name == ''" class="v-link clickable" @click="showLogin()" id="loginDialog">登录/注册</span><el-dropdown v-if="name != ''" @command="loginMenu"><span class="el-dropdown-link">{{ name }}<i class="el-icon-arrow-down el-icon--right"></i></span><el-dropdown-menu class="user-name-wrapper" slot="dropdown"><el-dropdown-item command="/user">实名认证</el-dropdown-item><el-dropdown-item command="/order">挂号订单</el-dropdown-item><el-dropdown-item command="/patient">就诊人管理</el-dropdown-item><el-dropdown-item command="/logout" divided>退出登录</el-dropdown-item></el-dropdown-menu></el-dropdown></div></div><!-- 登录弹出层 --><el-dialog :visible.sync="dialogUserFormVisible" style="text-align: left;display: none; " top="50px" :append-to-body="true"  width="960px" @close="closeDialog() "><div class="container"><!-- 手机登录 #start --><div class="operate-view" v-if="dialogAtrr.showLoginType === 'phone'"><div class="wrapper" style="width: 100%"><div class="mobile-wrapper" style="position: static; width: 70%"><span class="title">{{ dialogAtrr.labelTips }}</span><el-form><el-form-item><el-input v-model="dialogAtrr.inputValue" :placeholder="dialogAtrr.placeholder" :maxlength="dialogAtrr.maxlength" class="input v-input"><span slot="suffix" class="sendText v-link" v-if="dialogAtrr.second > 0">{{ dialogAtrr.second }}s </span><span slot="suffix" class="sendText v-link highlight clickable selected" v-if="dialogAtrr.second == 0" @click="getCodeFun()">重新发送 </span></el-input></el-form-item></el-form><div class="send-button v-button" @click="btnClick()"> {{ dialogAtrr.loginBtn }}</div></div><div class="bottom"><div class="wechat-wrapper" @click="weixinLogin()"><spanclass="iconfont icon"></span></div><span class="third-text"> 第三方账号登录 </span></div></div></div><!-- 手机登录 #end --><!-- 微信登录 #start --><div class="operate-view"  v-if="dialogAtrr.showLoginType === 'weixin'" ><div class="wrapper wechat" style="height: 400px"><div><div id="weixinLogin"></div></div><div class="bottom wechat" style="margin-top: -80px;"><div class="phone-container"><div class="phone-wrapper"  @click="phoneLogin()"><spanclass="iconfont icon"></span></div><span class="third-text"> 手机短信验证码登录 </span></div></div></div></div><!-- 微信登录 #end --><div class="info-wrapper"><div class="code-wrapper"><div><img src="//img.114yygh.com/static/web/code_login_wechat.png" class="code-img"><div class="code-text"><span class="iconfont icon"></span>微信扫一扫关注</div><div class="code-text"> “快速预约挂号”</div></div><div class="wechat-code-wrapper"><imgsrc="//img.114yygh.com/static/web/code_app.png"class="code-img"><div class="code-text"> 扫一扫下载</div><div class="code-text"> “预约挂号”APP</div></div></div><div class="slogan"><div>xxxxxx官方指定平台</div><div>快速挂号 安全放心</div></div></div></div></el-dialog><div></div>  <!--解决登录框样式不对--></div>
</template>

 添加Cookie,而Cookie在java代码中,通过request得到Cookie,而现在是在前端中在Vue中进行操作,要用Cookie需要安装以下Cookie的 插件:

命令行执行:

npm install js-cookie

拷贝js代码:

<script>
import cookie from 'js-cookie'
import Vue from 'vue'import userInfoApi from '@/api/userInfo'
import smsApi from '@/api/msm'
import hospitalApi from '@/api/hosp'const defaultDialogAtrr = {showLoginType: 'phone', // 控制手机登录与微信登录切换labelTips: '手机号码', // 输入框提示inputValue: '', // 输入框绑定对象placeholder: '请输入您的手机号', // 输入框placeholdermaxlength: 11, // 输入框长度控制loginBtn: '获取验证码', // 登录按钮或获取验证码按钮文本sending: true,      // 是否可以发送验证码second: -1,        // 倒计时间  second>0 : 显示倒计时 second=0 :重新发送 second=-1 :什么都不显示clearSmsTime: null  // 倒计时定时任务引用 关闭登录层清除定时任务
}
export default {data() {return {userInfo: {phone: '',code: '',openid: ''},dialogUserFormVisible: false,// 弹出层相关属性dialogAtrr:defaultDialogAtrr,name: '' // 用户登录显示的名称}},created() {this.showInfo()},methods: {// 绑定登录或获取验证码按钮btnClick() {// 判断是获取验证码还是登录if(this.dialogAtrr.loginBtn == '获取验证码') {this.userInfo.phone = this.dialogAtrr.inputValue// 获取验证码this.getCodeFun()} else {// 登录this.login()}},// 绑定登录,点击显示登录层showLogin() {this.dialogUserFormVisible = true// 初始化登录层相关参数this.dialogAtrr = { ...defaultDialogAtrr }},// 登录login() {this.userInfo.code = this.dialogAtrr.inputValueif(this.dialogAtrr.loginBtn == '正在提交...') {this.$message.error('重复提交')return;}if (this.userInfo.code == '') {this.$message.error('验证码必须输入')return;}if (this.userInfo.code.length != 6) {this.$message.error('验证码格式不正确')return;}this.dialogAtrr.loginBtn = '正在提交...'userInfoApi.login(this.userInfo).then(response => {console.log(response.data)// 登录成功 设置cookiethis.setCookies(response.data.name, response.data.token)}).catch(e => {this.dialogAtrr.loginBtn = '马上登录'})},setCookies(name, token) {cookie.set('token', token, { domain: 'localhost' })cookie.set('name', name, { domain: 'localhost' })window.location.reload()},// 获取验证码getCodeFun() {if (!(/^1[34578]\d{9}$/.test(this.userInfo.phone))) {this.$message.error('手机号码不正确')return;}// 初始化验证码相关属性this.dialogAtrr.inputValue = ''this.dialogAtrr.placeholder = '请输入验证码'this.dialogAtrr.maxlength = 6this.dialogAtrr.loginBtn = '马上登录'// 控制重复发送if (!this.dialogAtrr.sending) return;// 发送短信验证码this.timeDown();this.dialogAtrr.sending = false;smsApi.sendCode(this.userInfo.phone).then(response => {this.timeDown();}).catch(e => {this.$message.error('发送失败,重新发送')// 发送失败,回到重新获取验证码界面this.showLogin()})},// 倒计时timeDown() {if(this.clearSmsTime) {clearInterval(this.clearSmsTime);}this.dialogAtrr.second = 60;this.dialogAtrr.labelTips = '验证码已发送至' + this.userInfo.phonethis.clearSmsTime = setInterval(() => {--this.dialogAtrr.second;if (this.dialogAtrr.second < 1) {clearInterval(this.clearSmsTime);this.dialogAtrr.sending = true;this.dialogAtrr.second = 0;}}, 1000);},// 关闭登录层closeDialog() {if(this.clearSmsTime) {clearInterval(this.clearSmsTime);}},showInfo() {let token = cookie.get('token')if (token) {this.name = cookie.get('name')console.log(this.name)}},loginMenu(command) {if('/logout' == command) {cookie.set('name', '', {domain: 'localhost'})cookie.set('token', '', {domain: 'localhost'})//跳转页面window.location.href = '/'} else {window.location.href = command}},handleSelect(item) {window.location.href = '/hospital/' + item.hoscode},weixinLogin() {this.dialogAtrr.showLoginType = 'weixin'},phoneLogin() {this.dialogAtrr.showLoginType = 'phone'this.showLogin()}}
}
</script>

7.4.1 获取登录信息

  created() {

    this.showInfo()

  },
    showInfo() {

      let token = cookie.get('token')

      if (token) {

        this.name = cookie.get('name')

      }

    },

7.4.2 登录页面控制

<!-- 右侧 --><div class="right-wrapper"><span class="v-link clickable">帮助中心</span><span v-if="name == ''" class="v-link clickable" @click="showLogin()" id="loginDialog">登录/注册</span><el-dropdown v-if="name != ''" @command="loginMenu"><span class="el-dropdown-link">{{ name }}<i class="el-icon-arrow-down el-icon--right"></i></span><el-dropdown-menu class="user-name-wrapper" slot="dropdown"><el-dropdown-item command="/user">实名认证</el-dropdown-item><el-dropdown-item command="/order">挂号订单</el-dropdown-item><el-dropdown-item command="/patient">就诊人管理</el-dropdown-item><el-dropdown-item command="/logout" divided>退出登录</el-dropdown-item></el-dropdown-menu></el-dropdown></div>

说明:<el-dropdown-item command="/user">实名认证</el-dropdown-item>“command”的值为下拉列表的访问路径,即:实名认证的访问路径,后续会有对应的页面,目前我们将它处理好,方便后续使用
添加下拉列表事件处理:

loginMenu(command) {

  if('/logout' == command) {

    cookie.set('name''', {domain: 'localhost'})

    cookie.set('token''', {domain: 'localhost'})

    //跳转页面

    window.location.href = '/'

  } else {

    window.location.href = command

  }

},

点击登录,就会设置属性为true: 

 

点击登录:

输入验证码:

 

 

  

登录成功之后:右上角显示登录的手机号:

 多了这么一个下拉框的显示:

 (2)全局的登录事件-判断登录状态

在医院详情页面,点击某个科室,根据Cookie判断用户是否登录,没有登录,弹出登录框进行登录,医院详情页面在pages目录下,而弹框在myheader.vue页面下,是两个不同的页面,通过hoscode.vue页面无法调用myheader.vue的弹框,怎么办呢?可以使用全局事件方案

 

登录全局事件

目前登录层在myheader组件里面,登录按钮也在同一个组件里面,我们点击登录,调用showLogin()方法即可

目前的问题是,我们在预约挂号页面,选择科室去挂号时我们需要判断当前是否登录,如果登录可以进入下一个页面;如果没有登录需要显示登录层,那么这个问题怎么解决呢,我们不能直接调用头部登录方法,我们目前的组件是包含在nuxt里面的

问题总是能够解决的,其实很简单,我们可以注册一个全局登录事件,当需要登录层是,我们发送一个登录事件,头部监听登录事件,然后我们触发登录按钮的点击事件即可打开登录层,下面我们来试试

 在myheader.vue添加一个全局的登录事件,监听一下当前是否是登录状态,这个事件是一个全局的事件,在别的页面中也可以调用这个事件做操作

注册与监听事件

mounted() {// 注册全局登录事件对象window.loginEvent = new Vue();// 监听登录事件loginEvent.$on('loginDialogEvent', function () {document.getElementById("loginDialog").click();})// 触发事件,显示登录层:loginEvent.$emit('loginDialogEvent')}

在_hoscode.vue中引入Cookie:

1、引入cookie

import cookie from 'js-cookie'

2、添加方法

schedule(depcode) {

  // 登录判断

  let token = cookie.get('token')

  if (!token) {

    loginEvent.$emit('loginDialogEvent')

    return

  }

  window.location.href = '/hospital/schedule?hoscode=' + this.hospital.hoscode + "&depcode="depcode

},

 当点击科室的时候,触发事件进行判断cookie

 

目前是没有登录的,点击某一个科室:弹出弹框

 (3)登录注册-用户认证和网关整合

有些接口访问,必须是用户登录之后才能进行操作,比如说做预约挂号都是登录之后才能进行,这个登录过程可以在网关中做判断,当你访问接口,当你是登录才让你访问,不登录不让你访问,直接放回登录之后才让你操作,把登录验证放到网关中实现

  • 用户认证与网关整合

思路:

  1. 所有请求都会经过服务网关,服务网关对外暴露服务,在网关进行统一用户认证;
  2. 既然要在网关进行用户认证,网关得知道对哪些url进行认证,所以我们得对ur制定规则
  3. Api接口异步请求的,我们采取url规则匹配,如:/api/**/auth/**,如凡是满足该规则的都必须用户认证

 在service_gateway模块中先加入依赖:

创建类:AuthGlobalFilter 

package com.atguigu.yygh.gateway.filter;import com.alibaba.fastjson.JSONObject;
import com.atguigu.yygh.common.helper.JwtHelper;
import com.atguigu.yygh.common.result.Result;
import com.atguigu.yygh.common.result.ResultCodeEnum;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.StringUtils;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;import java.nio.charset.StandardCharsets;
import java.util.List;/*** <p>* 全局Filter,统一处理会员登录与外部不允许访问的服务* </p>** @author qy* @since 2019-11-21*/
@Component
public class AuthGlobalFilter implements GlobalFilter, Ordered {private AntPathMatcher antPathMatcher = new AntPathMatcher();@Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {ServerHttpRequest request = exchange.getRequest();String path = request.getURI().getPath();//当前访问的路径System.out.println("==="+path);//内部服务接口,不允许外部访问if(antPathMatcher.match("/**/inner/**", path)) {ServerHttpResponse response = exchange.getResponse();return out(response, ResultCodeEnum.PERMISSION);}//api接口,异步请求,校验用户必须登录if(antPathMatcher.match("/api/**/auth/**", path)) {Long userId = this.getUserId(request);if(StringUtils.isEmpty(userId)) {ServerHttpResponse response = exchange.getResponse();return out(response, ResultCodeEnum.LOGIN_AUTH);//未登录放回未登录状态码208}}return chain.filter(exchange);}@Overridepublic int getOrder() {return 0;}/*** api接口鉴权失败返回数据* @param response* @return*/private Mono<Void> out(ServerHttpResponse response, ResultCodeEnum resultCodeEnum) {Result result = Result.build(null, resultCodeEnum);byte[] bits = JSONObject.toJSONString(result).getBytes(StandardCharsets.UTF_8);DataBuffer buffer = response.bufferFactory().wrap(bits);//指定编码,否则在浏览器中会中文乱码response.getHeaders().add("Content-Type", "application/json;charset=UTF-8");return response.writeWith(Mono.just(buffer));}/*** 获取当前登录用户id* @param request* @return*/private Long getUserId(ServerHttpRequest request) {String token = "";List<String> tokenList = request.getHeaders().get("token");if(null  != tokenList) {token = tokenList.get(0);}if(!StringUtils.isEmpty(token)) {return JwtHelper.getUserId(token);}return null;}
}

修改前端:在request.js中添加代码:

import axios from 'axios'
import { MessageBox, Message } from 'element-ui'
import cookie from 'js-cookie'// 创建axios实例
const service = axios.create({baseURL: 'http://localhost:83',timeout: 15000 // 请求超时时间
})
// http request 拦截器
service.interceptors.request.use(config => {// token 先不处理,后续使用时在完善//判断cookie是否有token值if (cookie.get('token')) {//token值放到cookie里面config.headers['token'] = cookie.get('token')}return config},err => {return Promise.reject(err)})
// http response 拦截器
service.interceptors.response.use(response => {//状态码是208if (response.data.code === 208) {//弹出登录输入框loginEvent.$emit('loginDialogEvent')return} else {if (response.data.code !== 200) {Message({message: response.data.message,type: 'error',duration: 5 * 1000})return Promise.reject(response.data)} else {return response.data}}},error => {return Promise.reject(error.response)})
export default service


http://www.ppmy.cn/news/19329.html

相关文章

【Hadoop】HDFS+Shell实践(定时上传数据至HDFS)

这篇博客是一个结合HDFS的Shell练习&#xff0c;相对简单。现有需求&#xff1a;每天1:00需要从系统上传一份昨天的日志文件到HDFS&#xff0c;日志文件的格式为access_2023_01_01.log&#xff0c;HDFS目录格式为20230101。这个需求是相对简单的&#xff0c;分为以下几个步骤&a…

Issues with peer dependencies found

问题背景&#xff1a; 今天安装一些依赖&#xff0c;报了这个错误 Issues with peer dependencies found 那么这个错误是什么意思呢&#xff1f; WARN  Issues with peer dependencies found . └─┬ typescript-eslint/eslint-plugin ├── ✕ missing peer typescrip…

十二、创建和管理表

文章目录一、基础知识1.1 一条数据存储的过程1.2 标识符命名规则1.3 数据类型及数据库操作二、创建表三、查看表结构3.1 使用 SHOW COLUMNS 语句查看3.2 使用 DESCRIBE 语句查看3.3 查看表详细结构语句 SHOW CREATE TABLE四、修改表结构4.1 添加新字段和修改字段定义4.2 修改字…

基于Andriod的智慧校园卡系统的设计与实现

目录 1.课题研究立项依据 2.文献综述 3.课题研究的基本内容及预期目标或成果 4.课题的研究方案 5.研究进度安排 6.主要参考文献 1.课题研究立项依据 随着信息技术的不断发展,数字化、智能化校园的提出与教育现代化建设的不断推进,智能卡技术的不断发展进步,国内各高校都在…

【蓝桥云课】进制

对于任意数制RRR的数nnn&#xff0c;都可以表达为n∑i0kaiRia0R0a1R1a2R2...akRkn\sum_{i0}^{k}a_{i}R^{i} a_{0}R^{0}a_{1}R^{1}a_{2}R^{2}...a_{k}R^{k}ni0∑k​ai​Ria0​R0a1​R1a2​R2...ak​Rk 一、十进制转RRR进制 方法&#xff1a;十进制数除RRR取余&#xff0c;余数…

二叉树专题汇总

二叉树的前中后序遍历day11|144.二叉树的前序遍历、145.二叉树的后序遍历、94.二叉树的中序遍历_奈川直子的博客-CSDN博客 二叉树的层序遍历 翻转二叉树 对称二叉树 day12|层序遍历合集、226.翻转二叉树、101.对称二叉树_奈川直子的博客-CSDN博客 N叉树最大深度 完全二叉树节点…

spring Xml方式实现DI

spring中的Bean的管理: Bean(汉译咖啡豆). 又称JAVABean.其实就是JAVA程序程序中的一个个对象,所以Bean的管理其实就是spring对于JAVA程序中的对象的管理 管理的内容是什么 1 .对象的创建 IOC IOC 叫做控制反转,就是Spring给我们创建对象,然后我们直接用,不用自己NEW,前面已经…

9.Java数组知识大全

文章目录前言一、数组介绍二、数组的定义域静态初始化三、数组元素访问数组地址中的小拓展:四、数组遍历1.获取数组里面的元素2.把数据存储到数组中3.遍历数组的最快方式4.遍历数组并求和5.统计个数6.变化数据五、数组动态初始化1.数组默认初始化值的规律2.数组动态初始化和静态…