一、阿里云存储oss
用户验证需要上传证件图片、首页轮播也需要上传图片,因此我们要做文件服务,阿里云oss是一个很好的分布式文件服务系统,所以我们只需要集成阿里云oss即可
1、开通“对象存储OSS”服务
(1)申请阿里云账号
(2)实名验证
(3)开通“对象存储OSS”服务
(4)进入管理控制台
1.1创建Bucket
选择:标准存储、公共读、不开通
2、使用SDK文档
3、文件服务实现
3.1搭建service-oss模块
3.1.1 搭建service-oss模块
搭建过程参考service-user模块
3.1.2 修改配置
1、修改pom.xml,引入阿云oss依赖
<dependencies>
<!-- 阿云oss依赖 -->
<dependency>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-sdk-oss</artifactId>
</dependency>
<!-- 日期工具栏依赖 -->
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
</dependency>
</dependencies>
2、添加配置文件application.properties:
# 服务端口
server.port=8205
# 服务名
spring.application.name=service-oss
#返回json的全局时间格式
spring.jackson.date-format=yyyy-MM-dd HH:mm:ss
spring.jackson.time-zone=GMT+8
# nacos服务地址
spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848
3.1.3 启动类
//取消数据源自动配置
@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
@EnableDiscoveryClient
@ComponentScan(basePackages = {"com.atguigu"})
public class ServiceOssApplication {
public static void main(String[] args) {
SpringApplication.run(ServiceOssApplication.class, args);
}
}
3.1.4配置网关,在网关服务中配置
#设置路由id
spring.cloud.gateway.routes[5].id=service-oss
#设置路由的uri
spring.cloud.gateway.routes[5].uri=lb://service-oss
#设置路由断言,代理servicerId为auth-service的/auth/路径
spring.cloud.gateway.routes[5].predicates= Path=/*/oss/**
3.2 测试SDK :
package com.fan.yygh.oss;
import com.aliyun.oss.ClientException;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.OSSException;
public class Demo {
public static void main(String[] args) throws Exception {
// Endpoint以华东1(杭州)为例,其它Region请按实际情况填写。
String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
// 阿里云账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM用户进行API访问或日常运维,请登录RAM控制台创建RAM用户。
String accessKeyId = "xxx";
String accessKeySecret = "xxx";
// 填写Bucket名称,例如examplebucket。
String bucketName = "fanbucket-test";
// 创建OSSClient实例。
OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
try {
// 创建存储空间。
ossClient.createBucket(bucketName);
} catch (OSSException oe) {
System.out.println("Caught an OSSException, which means your request made it to OSS, "
+ "but was rejected with an error response for some reason.");
System.out.println("Error Message:" + oe.getErrorMessage());
System.out.println("Error Code:" + oe.getErrorCode());
System.out.println("Request ID:" + oe.getRequestId());
System.out.println("Host ID:" + oe.getHostId());
} catch (ClientException ce) {
System.out.println("Caught an ClientException, which means the client encountered "
+ "a serious internal problem while trying to communicate with OSS, "
+ "such as not being able to access the network.");
System.out.println("Error Message:" + ce.getMessage());
} finally {
if (ossClient != null) {
ossClient.shutdown();
}
}
}
}
封装controller接口
controller.FileApiController:
2、创建com.atguigu.yygh.oss.utils.ConstantOssPropertiesUtils配置类
@Component
public class ConstantOssPropertiesUtils implements InitializingBean {
@Value("${aliyun.oss.endpoint}")
private String endpoint;
@Value("${aliyun.oss.accessKeyId}")
private String accessKeyId;
@Value("${aliyun.oss.secret}")
private String secret;
@Value("${aliyun.oss.bucket}")
private String bucket;
public static String EDNPOINT;
public static String ACCESS_KEY_ID;
public static String SECRECT;
public static String BUCKET;
@Override
public void afterPropertiesSet() throws Exception {
EDNPOINT=endpoint;
ACCESS_KEY_ID=accessKeyId;
SECRECT=secret;
BUCKET=bucket;
}
}
3、创建接口类实现类
二、用户人证
1、需求分析
用户登录成功后都要进行身份验证,验证通过后才可以预约挂号
验证过程:用户填写信息(姓名、证件类型、证件号码和证件照片)==> 平台审批
用户验证设计接口:
1、提交验证
2、上传证件图片
3、获取提交验证信息
2、api接口
操作模块:service-user
获取当前用户工具类
在common-util模块添加工具类
//获取当前用户信息工具类
public class AuthContextHolder {
//获取当前用户id
public static Long getUserId(HttpServletRequest request) {
//从header获取token
String token = request.getHeader("token");
//jwt从token获取userid
Long userId = JwtHelper.getUserId(token);
return userId;
}
//获取当前用户名称
public static String getUserName(HttpServletRequest request) {
//从header获取token
String token = request.getHeader("token");
//jwt从token获取userid
String userName = JwtHelper.getUserName(token);
return userName;
}
}
controller:
添加controller方法
在UserInfoApiController类添加方法
//用户人证接口
@PostMapping("auth/userAuth")
public Result userAuth(@RequestBody UserAuthVo userAuthVo, HttpServletRequest request) {
//传递两个参数,第一个参数用户id,第二个参数验证数据vo对象
userInfoService.userAuth(AuthContextHolder.getUserId(request),userAuthVo);
return Result.ok();
}
//获取用户id信息接口
@GetMapping("auth/getUserInfo")
public Result getUserInfo(HttpServletRequest request) {
Long userId = AuthContextHolder.getUserId(request);
UserInfo userInfo = userInfoService.getById(userId);
return Result.ok(userInfo);
}
//用户人证接口
@Override
public void userAuth(Long userId, UserAuthVo userAuthVo) {
//根据用户id查询用户信息
UserInfo userInfo = baseMapper.selectById(userId);
//设置验证信息
//验证人姓名
userInfo.setName(userAuthVo.getName());
userInfo.setCertificatesType(userAuthVo.getCertificatesType());
userInfo.setCertificatesNo(userAuthVo.getCertificatesNo());
userInfo.setCertificatesUrl(userAuthVo.getCertificatesUrl());
userInfo.setAuthStatus(AuthStatusEnum.AUTH_RUN.getStatus());
//进行信息更新
baseMapper.updateById(userInfo);
}
前端:
3、前端
3.1封装api请求
在/api/userInfo.js添加方法:
getUserInfo() {
return request({
url: `${api_name}/auth/getUserInfo`,
method: `get`
})
},
saveUserAuah(userAuth) {
return request({
url: `${api_name}/auth/userAuth`,
method: 'post',
data: userAuth
})
}
3.2 页面展示
创建/pages/user/index.vue组件
测试:
三、就诊人管理
1、需求分析
预约下单需要选择就诊人,因此我们要实现就诊人管理,前端就诊人管理其实就是要实现一个完整的增删改查
添加:
package com.fan.yygh.user.api;
import com.fan.yygh.common.result.Result;
import com.fan.yygh.common.utils.AuthContextHolder;
import com.fan.yygh.model.user.Patient;
import com.fan.yygh.user.service.PatientService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
@RestController
@Api("就诊人接口")
@RequestMapping("/api/user/patient")
public class PatientController {
@Resource
private PatientService patientService;
//获取就诊人列表
@GetMapping("auth/findAll")
@ApiOperation("//获取就诊人列表") //需要参数:账号拥有者的userId
public Result findAll(HttpServletRequest request){
//获取当前登录用户userId
Long userId = AuthContextHolder.getUserId(request);
//根据当前登录用户查询关联的其他就诊者列表
List<Patient> list = patientService.findAllUserId(userId);
return Result.ok(list);
}
//根据id获取就诊人信息
@ApiOperation("//根据id获取就诊人信")
@GetMapping("auth/get/{id}")
public Result getPatient(@PathVariable Long id){
Patient patient = patientService.getPatientId(id);//此方法getPatientId需要单独补充信息。
return Result.ok(patient);
}
@ApiOperation("//添加就诊人")
@PostMapping("auth/save") //此方法比较特殊,需要多一个参数
public Result savePatient(@RequestBody Patient patient,
HttpServletRequest request){
//获取当前登录用户id,补全信息,即将其他就诊人绑定到当前登录账户上。所以需要userid参数
Long userId = AuthContextHolder.getUserId(request);
patient.setUserId(userId);
patientService.save(patient);
return Result.ok();
}
@ApiOperation("//删除就诊人")
@DeleteMapping("auth/remove/{id}")
public Result deletePatient(@PathVariable Long id){
patientService.removeById(id);
return Result.ok();
}
@ApiOperation("修改就诊人信息")
@PutMapping("auth/update")
public Result updatePatient(@RequestBody Patient patient){
//根据id修改,此对象包含id
patientService.updateById(patient);
return Result.ok();
}
}
3、前端
3.1 封装api请求
创建/api/patient.js文件
3.2 列表
添加/pages/patient/index.vue组件
3.3 添加与修改
添加/pages/patient/add.vue组件
3.4 详情与删除
添加/pages/patient/show.vue组件
四、平台用户管理
前面我们做了用户登录、用户验证与就诊人,现在我们需要把这些信息在我们的平台管理系统做一个统一管理
操作模块:service-user
使用枚举类处理验证状态,将数字编码变成文字的验证状态;
package com.fan.yygh.user.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fan.yygh.common.exception.YyghException;
import com.fan.yygh.common.result.ResultCodeEnum;
import com.fan.yygh.enums.AuthStatusEnum;
import com.fan.yygh.common.helper.JwtHelper;
import com.fan.yygh.model.user.UserInfo;
import com.fan.yygh.user.mapper.UserInfoMapper;
import com.fan.yygh.user.service.UserInfoService;
import com.fan.yygh.vo.user.LoginVo;
import com.fan.yygh.vo.user.UserAuthVo;
import com.fan.yygh.vo.user.UserInfoQueryVo;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import javax.annotation.Resource;
import java.util.HashMap;
import java.util.Map;
@Service //先继承《M是mapper,T是实体类》后实现
public class UserInfoImpl extends ServiceImpl<UserInfoMapper, UserInfo>
implements UserInfoService {
@Resource
private UserInfoMapper userInfoMapper;
@Resource
private RedisTemplate<String,String> redisTemplate;
@Override
public IPage<UserInfo> selectPage(Page<UserInfo> pageParam,
UserInfoQueryVo userInfoQueryVo) {
//UserInfoQueryVo获取条件值
String name = userInfoQueryVo.getKeyword(); //用户名称
Integer status = userInfoQueryVo.getStatus();//用户状态
Integer authStatus = userInfoQueryVo.getAuthStatus(); //验证状态
String createTimeBegin = userInfoQueryVo.getCreateTimeBegin(); //开始时间
String createTimeEnd = userInfoQueryVo.getCreateTimeEnd(); //结束时间
//对条件值进行非空判断
QueryWrapper<UserInfo> wrapper = new QueryWrapper<>();
if(!StringUtils.isEmpty(name)) {
wrapper.like("name",name);
}
if(!StringUtils.isEmpty(status)) {
wrapper.eq("status",status);
}
if(!StringUtils.isEmpty(authStatus)) {
wrapper.eq("auth_status",authStatus);
}
if(!StringUtils.isEmpty(createTimeBegin)) {
wrapper.ge("create_time",createTimeBegin);
}
if(!StringUtils.isEmpty(createTimeEnd)) {
wrapper.le("create_time",createTimeEnd);
}
//调用mapper的方法,这里为何使用IPage
IPage<UserInfo> pages = baseMapper.selectPage(pageParam, wrapper);
//编号变成对应的中文值的 封装
pages.getRecords().stream().forEach( item -> {
//盗用方法进行封装
this.packageUserInfo(item);
});
return pages;
}
//编号变成文字的对应值 封装
private UserInfo packageUserInfo(UserInfo userInfo) {
//处理验证状态的编码,这里使用枚举类进行装换
userInfo.getParam().put("authStatusString",
//根据用户数字状态 转换
AuthStatusEnum.getStatusNameByStatus(userInfo.getAuthStatus()));
/*整数类intValue()方法
intValue()方法在java.lang包中可用。
intValue()方法用于返回此Integer对象表示的值,该值转换为int类型(通过强制转换)。
intValue()方法是一个非静态方法,只能通过类对象访问,如果尝试使用类名称访问该方法,则会收到错误消息。
从整数转换为int时,intValue()方法不会引发异常。*/
//处理用户状态 0 1
String statusString = userInfo.getStatus().intValue()==0 ? "锁定" : "正常";
userInfo.getParam().put("statusString",statusString);
return userInfo;
}
//用户验证接口
@Override
public void userAuth(Long userId, UserAuthVo userAuthVo) {
//根据用户id查询用户信息
System.out.println("userId:"+userId);
UserInfo userInfo = baseMapper.selectById(userId);
System.out.println("userInfo:"+userInfo);
//设置验证信息
//验证人姓名
userInfo.setName(userAuthVo.getName());
userInfo.setCertificatesType(userAuthVo.getCertificatesType());
userInfo.setCertificatesNo(userAuthVo.getCertificatesNo());
userInfo.setCertificatesUrl(userAuthVo.getCertificatesUrl());
userInfo.setAuthStatus(AuthStatusEnum.AUTH_RUN.getStatus());
//进行信息更新
baseMapper.updateById(userInfo);
}
//判断数据库是否存在微信的扫描人信息,根据openid判断
@Override
public UserInfo selectWxInfoOpenId(String openid) {
QueryWrapper<UserInfo> wrapper = new QueryWrapper<>();
wrapper.eq("openid",openid);
UserInfo userInfo = baseMapper.selectOne(wrapper);
return userInfo;
}
//用户手机号登录接口
@Override
public Map<String, Object> loginUser(LoginVo loginVo) {
//从vo中获取参数
String phone = loginVo.getPhone();
String code = loginVo.getCode();
//参数校验
if(StringUtils.isEmpty(phone) || StringUtils.isEmpty(code)){
throw new YyghException(ResultCodeEnum.PARAM_ERROR);//ResultCodeEnum枚举类
}
//TODO 校验校验验证码
//校验校验验证码
String mobleCode = redisTemplate.opsForValue().get(phone);
if(!code.equals(mobleCode)) {
throw new YyghException(ResultCodeEnum.CODE_ERROR);
}
//绑定手机号码
UserInfo userInfo = null;
if(!StringUtils.isEmpty(loginVo.getOpenid())) {
userInfo = this.selectWxInfoOpenId(loginVo.getOpenid());
if(null != userInfo) {
userInfo.setPhone(loginVo.getPhone());
this.updateById(userInfo);
} else {
throw new YyghException(ResultCodeEnum.DATA_ERROR);
}
}
if(userInfo == null){
//判断是否第一次登录,根据手机号查询数据库,如果不存在相同的手机号就是第一次登录
QueryWrapper<UserInfo> wrapper = new QueryWrapper<>();
wrapper.eq("phone",phone);
userInfo = baseMapper.selectOne(wrapper);
if(null==userInfo ){//第一次使用这个手机号登录
//添加信息到数据库
userInfo = new UserInfo();
userInfo.setName("");
userInfo.setPhone(phone);
userInfo.setStatus(1);//设置可用
//this.save(userInfo);//保存到数据库
baseMapper.insert(userInfo);
}
}
//校验是否被禁用
if(userInfo.getStatus() == 0) {
throw new YyghException(ResultCodeEnum.LOGIN_DISABLED_ERROR);
}
//返回给页面的map信息
HashMap<String, Object> map = new HashMap<>();
String name = userInfo.getName();
if (StringUtils.isEmpty(name)) {//如果名字为空
name = userInfo.getNickName();//用昵称代替名字
}
if(StringUtils.isEmpty(name)){
name = userInfo.getPhone();//如果名字为空,用手机号代替名字
}
map.put("name",name);//返回name和token
//利用工具生成token
String token = JwtHelper.createToken(userInfo.getId(), name);
map.put("token",token);//token 被写错了
return map; //记得返回map
}
}
后台管理系统的前端:
修改网关:
2.用户锁定的后台管理:
2、锁定
2.1 api接口
添加controller方法
2.2.1 封装api请求
在/api/user/userInfo.js文件添加方法
2.2.2 添加组件
修改/views/user/userInfo/list.vue组件
3.详情页面:
4、用户列表
4.1 添加路由
{
path: 'userInfo/authList',
name: '验证审批列表',
component: () =>import('@/views/user/userInfo/authList'),
meta: { title: '验证审批列表', icon: 'table' }
}
4.2 添加组件
添加/views/user/userInfo/authList.vue组件
5、用户审批
5.1 api接口
@Override
public void approval(Long userId, Integer authStatus) {
System.out.println(userId+":"+authStatus);
//当页面点击通过按钮或者不通过按钮的时候,参数传过来是2/-1
if(authStatus.intValue() ==2 || authStatus.intValue() == -1){
UserInfo userInfo = baseMapper.selectById(userId);
userInfo.setAuthStatus(authStatus);//忘了写
int i = baseMapper.updateById(userInfo);//可以用baseMapper进行更改
}
}