用户首页数据分析
1,获取医院等级(根据数据字典编码获取)
2,获取地区(根据数据字典编码获取)
3,医院分页列表
4,根据医院名称关键字搜索医院列表
所有的后端接口都在HospitalApiController中
医院详情页
- 左侧预约挂号:获取科室信息和挂号规则
- 医院详情和预约规则调用一个接口,返回map
@Override
public Map<String, Object> item(String hoscode) {
Map<String, Object> result = new HashMap<>();
//医院详情
Hospital hospital = this.setHospitalHosType(this.getByHoscode(hoscode));
result.put("hospital", hospital);
//预约规则
result.put("bookingRule", hospital.getBookingRule());
//不需要重复返回
hospital.setBookingRule(null);
return result;
}

登录
登录需求
1,登录采取弹出层的形式
2,登录方式:
(1)手机号码+手机验证码
(2)微信扫描
3,无注册界面,第一次登录根据手机号判断系统是否存在,如果不存在则自动注册
4,微信扫描登录成功必须绑定手机号码,即:第一次扫描成功后绑定手机号,以后登录扫描直接登录成功
5,网关统一判断登录状态,如何需要登录,页面弹出登录层,不要session
login校验步骤
- 获取手机号和验证码
- 校验参数
- TODO 校验验证码(第三方短信服务)
- 校验是否被禁用 (判断status)
- JWT生成token
- userInfo不为空,返回页面显示名称
@Service
public class UserInfoServiceImpl extends
ServiceImpl<UserInfoMapper, UserInfo> implements UserInfoService {
@Autowired
private RedisTemplate redisTemplate;
@Override
public Map<String, Object> login(LoginVo loginVo) {
//获取手机号和验证码
String phone = loginVo.getPhone();
String code = loginVo.getCode();
//校验参数
if(StringUtils.isEmpty(phone) ||
StringUtils.isEmpty(code)) {
throw new YyghException(ResultCodeEnum.PARAM_ERROR);
}
//TODO 校验校验验证码
String mobleCode = redisTemplate.opsForValue().get(phone).toString();
if(!code.equals(mobleCode)) {
throw new YyghException(ResultCodeEnum.CODE_ERROR);
}
//手机号已被使用
QueryWrapper<UserInfo> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("phone", phone);
//获取会员
UserInfo userInfo = baseMapper.selectOne(queryWrapper);
if(null == userInfo) {
//第一次使用该手机号
userInfo = new UserInfo();
userInfo.setName("");
userInfo.setPhone(phone);
userInfo.setStatus(1);
baseMapper.insert(userInfo);
}
//校验是否被禁用
if(userInfo.getStatus() == 0) {
throw new YyghException(ResultCodeEnum.LOGIN_DISABLED_ERROR);
}
//userInfo不为空,返回页面显示名称
Map<String, Object> map = new HashMap<>();
String name = userInfo.getName();
if(StringUtils.isEmpty(name)) {
name = userInfo.getNickName();
}
if(StringUtils.isEmpty(name)) {
name = userInfo.getPhone();
}
//TODO 生成token记录登录
String token = JwtHelper.createToken(userInfo.getId(), name);
map.put("name", name);
map.put("token", token);
return map;
}
}
JWT
短信验证
- 调用第三方服务发送验证码短信
- 在前端中,二种登录方式,手机号,微信,优先使用手机号登录(设置一个默认值优先手机号登录)
- 发送短信验证码,调用后端msm中sendcode接口。
- 设置倒计时时间60s,setInterval方法。
- 验证码输入后,调用后端login接口进行登录验证,登录成功则设置cookies(name和token)

全局登录监听事件
目前登录层在myheader组件里面,登录按钮也在同一个组件里面,我们点击登录,调用showLogin()方法即可
目前的问题是,我们在预约挂号页面,选择科室去挂号时我们需要判断当前是否登录,如果登录可以进入下一个页面;如果没有登录需要显示登录层,那么这个问题怎么解决呢,我们不能直接调用头部登录方法,我们目前的组件是包含在nuxt里面的
问题总是能够解决的,其实很简单,我们可以注册一个全局登录监听事件,当需要登录层时,我们发送一个登录事件,头部监听登录事件,然后我们触发登录按钮的点击事件即可打开登录层。
mounted() {
// 注册全局登录事件对象
window.loginEvent = new Vue();
// 监听登录事件
loginEvent.$on('loginDialogEvent', function () {
document.getElementById("loginDialog").click();
})
// 触发事件,显示登录层:loginEvent.$emit('loginDialogEvent')
}
用户认证网关整合
思路:
- 所有请求都会经过服务网关,服务网关对外暴露服务,在网关进行统一用户认证;
- 既然要在网关进行用户认证,网关得知道对哪些url进行认证,所以我们得对ur制定规则
- Api接口异步请求的,我们采取url规则匹配,如:/api//auth/,如凡是满足该规则的都必须用户认证
@Override
public 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);
}
Long userId = this.getUserId(request);
//api接口,异步请求,校验用户必须登录
if(antPathMatcher.match("/api/**/auth/**", path)) {
if(StringUtils.isEmpty(userId)) {
ServerHttpResponse response = exchange.getResponse();
return out(response, ResultCodeEnum.LOGIN_AUTH);
}
}
return chain.filter(exchange);
}
在服务网关中判断用户登录状态
(看token有没有)
我们统一从header头信息中获取
如何判断用户信息合法:
登录时我们返回用户token,在服务网关中获取到token后,我在到redis中去查看用户id,如何用户id存在,则token合法,否则不合法
前端修改
请求服务器端接口时我们默认带上token,需要登录的接口如果token没有或者token过期,服务器端会返回208状态,然后发送登录事件打开登录弹出层登录
在前端request.js中,修改。因为在myheader.vue中已经定义过全局登录监听事件,这里状态码208,就会弹出登录框
if(response.data.code === 208) {
//弹出登录输入框
loginEvent.$emit('loginDialogEvent')
return
}