[TOC]

一、 阿里云oss

用户认证需要上传证件图片、首页轮播也需要上传图片,因此我们要做文件服务,阿里云oss是一个很好的分布式文件服务系统,所以我们只需要集成阿里云oss即可

1、开通“对象存储OSS”服务

(1)申请阿里云账号
(2)实名认证
(3)开通“对象存储OSS”服务
(4)进入管理控制台

1.1创建Bucket

选择:标准存储、公共读、不开通
阿里云OSS、用户认证与就诊人 - 图1

1.2上传默认头像

创建文件夹avatar,上传默认的用户头像
阿里云OSS、用户认证与就诊人 - 图2

1.3获取用户acesskeys

阿里云OSS、用户认证与就诊人 - 图3

2、使用SDK文档

阿里云OSS、用户认证与就诊人 - 图4

阿里云OSS、用户认证与就诊人 - 图5

3、文件服务实现

3.1搭建service-oss模块

3.1.1 搭建service-oss模块

搭建过程参考service-user模块

3.1.2 修改配置

1、修改pom.xml,引入阿里云oss依赖

| <dependencies>

<dependency>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-sdk-oss</artifactId>
</dependency>

_<!-- 日期工具栏依赖 --><br />    _<**dependency**><br />        <**groupId**>joda-time</**groupId**><br />        <**artifactId**>joda-time</**artifactId**><br />    </**dependency**><br /></**dependencies**> |

| —- |

2、添加配置文件application.properties

# 服务端口server.port=8205# 服务名spring.application.name=service-oss
#返回json的全局时间格式spring.jackson.date-format=yyyy-MM-dd HH:mm:ssspring.jackson.time-zone=GMT+8
# nacos服务地址spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848
aliyun.oss.endpoint
=oss-cn-beijing.aliyuncs.comaliyun.oss.accessKeyId=LTAI4G4SV6WtST7UYH776b64aliyun.oss.secret=X9KHNYgztNr9MI5Zp8JffQPZO4uJo5aliyun.oss.bucket=yygh-atguigu

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配置网关

#设置路由idspring.cloud.gateway.routes[5].id=service-oss#设置路由的urispring.cloud.gateway.routes[5].uri=lb://service-oss#设置路由断言,代理servicerId为auth-service的/auth/路径spring.cloud.gateway.routes[5].predicates= Path=//oss/*

3.2 测试SDK

阿里云OSS、用户认证与就诊人 - 图6

3.3封装service接口

public interface FileService {
_//上传文件到阿里云oss
_String upload(MultipartFile file);
}

2、创建com.atguigu.yygh.oss.utils.ConstantOssPropertiesUtils配置类

| @Componentpublic class ConstantOssPropertiesUtils implements InitializingBean {

@Value(**"${aliyun.oss.endpoint}"**)<br />    **private **String **endpoint**;

@Value(**"${aliyun.oss.accessKeyId}"**)<br />    **private **String **accessKeyId**;

@Value(**"${aliyun.oss.secret}"**)<br />    **private **String **secret**;

@Value(**"${aliyun.oss.bucket}"**)<br />    **private **String **bucket**;

**public static **String _EDNPOINT_;<br />    **public static **String _ACCESS_KEY_ID_;<br />    **public static **String _SECRECT_;<br />    **public static **String _BUCKET_;

@Override<br />    **public void **afterPropertiesSet() **throws **Exception {<br />        _EDNPOINT_=**endpoint**;<br />        _ACCESS_KEY_ID_=**accessKeyId**;<br />        _SECRECT_=**secret**;<br />        _BUCKET_=**bucket**;<br />    }<br />} |

| —- |

3、创建接口类实现类

@Servicepublic class FileServiceImpl implements FileService {
@Override
public String upload(MultipartFile file) {
// Endpoint以杭州为例,其它Region请按实际情况填写。
_String endpoint = ConstantOssPropertiesUtils._EDNPOINT
;
String accessKeyId = ConstantOssPropertiesUtils.ACCESS_KEY_ID;
String accessKeySecret = ConstantOssPropertiesUtils.SECRECT;
String bucketName = ConstantOssPropertiesUtils.BUCKET;
try {
// 创建OSSClient实例。
_OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
// 上传文件流。
InputStream inputStream = file.getInputStream();
String fileName = file.getOriginalFilename();
//生成随机唯一值,使用uuid,添加到文件名称里面
String uuid = UUID._randomUUID().toString().replaceAll(“-“,“”);
fileName = uuid+fileName;
//按照当前日期,创建文件夹,上传到创建文件夹里面
// 2021/02/02/01.jpg
_String timeUrl = new DateTime().toString(“yyyy/MM/dd”);
fileName = timeUrl+“/“+fileName;
//调用方法实现上传
ossClient.putObject(bucketName, fileName, inputStream);
// 关闭OSSClient。
ossClient.shutdown();
//上传之后文件路径
// [_https://yygh-atguigu.oss-cn-beijing.aliyuncs.com/01.jpg](https://yygh-atguigu.oss-cn-beijing.aliyuncs.com/01.jpg)__ String url = “https://“+bucketName+“.”+endpoint+“/“+fileName;
//返回
_return url;
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
}

3.4封装controller接口

@RestController
@RequestMapping(“/api/oss/file”)public class FileApiController {
@Autowired
private FileService fileService;
//上传文件到阿里云oss
@PostMapping(“fileUpload”)
public Result fileUpload(MultipartFile file) {
//获取上传文件
_String url = fileService.upload(file);
return Result._ok
(url);
}
}

2 用户认证

3 需求分析

用户登录成功后都要进行身份认证,认证通过后才可以预约挂号
认证过程:用户填写信息(姓名、证件类型、证件号码和证件照片)==> 平台审批
用户认证设计接口:

  1. 提交认证
  2. 上传证件图片
  3. 获取提交认证信息

    4 api接口

    操作模块:service-user

    2.1 添加service接口及实现

    1、在UserInfoService类添加接口
//用户认证void userAuth(Long userId, UserAuthVo userAuthVo);

2、在UserInfoServiceImpl类添加实现

//用户认证@Overridepublic 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);
}

2.2 获取当前用户工具类

在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;
}
}

2.3 添加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);
}

3、前端

3.1封装api请求

在/api/userInfo.js添加方法

getUserInfo() {return request({ url: `${api_name}/auth/getUserInfo`, method: get})
},
saveUserAuah(userAuah) { return request({ url: `${api_name}/auth/userAuah`, method: ‘post’, data: userAuah
})
}

3.2 页面展示

创建/pages/user/index.vue组件




4、预约挂号页面调整

如果要预约挂号,我们必须要认证通过后才可以,所以我们在预约挂号前要做认证判断,如果没有认证通过,则跳转到认证页面
修改/pages/hospital/_hoscode.vue组件

import userInfoApi from ‘@/api/userInfo’
schedule(depcode) {
// 登录判断
let token = cookie.get(‘token’)
if (!token) {
loginEvent.$emit(‘loginDialogEvent’)
return
}

//判断认证
userInfoApi.getUserInfo().then(response => {
let authStatus = response.data.authStatus
// 状态为2认证通过
if (!authStatus || authStatus != 2) {
window.location.href = ‘/user’
return
}
})

window.location.href = ‘/hospital/schedule?hoscode=’ + this.hospital.hoscode + “&depcode=”+ depcode
},

三、就诊人管理

5 需求分析

预约下单需要选择就诊人,因此我们要实现就诊人管理,前端就诊人管理其实就是要实现一个完整的增删改查

6 api接口

2.1 引入依赖

<dependencies>
<dependency>
<groupId>com.atguigu</groupId>
<artifactId>service_cmn_client</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
</dependencies>

2.2 添加Mapper

添加com.atguigu.yygh.user.mapper.PatientMapper

public interface PatientMapper extends BaseMapper {
}

2.3 添加service接口及实现类

1、添加com.atguigu.yygh.user.service.PatientService 接口

public interface PatientService extends IService {
//获取就诊人列表
_List findAllUserId(Long userId);
//根据id获取就诊人信息
_Patient getPatientId(Long id);
}

2、添加com.atguigu.yygh.user.service.impl.PatientServiceImpl接口实现

@Servicepublic class PatientServiceImpl extends
ServiceImpl implements PatientService {
@Autowired
private DictFeignClient dictFeignClient;
//获取就诊人列表
@Override
public List findAllUserId(Long userId) {
//根据userid查询所有就诊人信息列表
_QueryWrapper wrapper = new QueryWrapper<>();
wrapper.eq(“user_id”,userId);
List patientList = baseMapper.selectList(wrapper);
//通过远程调用,得到编码对应具体内容,查询数据字典表内容
patientList.stream().forEach(item -> {
//其他参数封装
this.packPatient(item);
});
return patientList;
}
@Override
public Patient getPatientId(Long id) {
return this.packPatient(baseMapper.selectById(id));
}
//Patient对象里面其他参数封装
private Patient packPatient(Patient patient) {
//根据证件类型编码,获取证件类型具体指
String certificatesTypeString =
dictFeignClient.getName(DictEnum.**_CERTIFICATES_TYPE
.getDictCode(), patient.getCertificatesType());_//联系人证件
//联系人证件类型
_String contactsCertificatesTypeString =
dictFeignClient.getName(DictEnum.CERTIFICATES_TYPE.getDictCode(),patient.getContactsCertificatesType());
_//省
_String provinceString =
dictFeignClient.getName(patient.getProvinceCode());
_//市
_String cityString =
dictFeignClient.getName(patient.getCityCode());
_//区
_String districtString =
dictFeignClient.getName(patient.getDistrictCode());
patient.getParam().put(
“certificatesTypeString”, certificatesTypeString);
patient.getParam().put(
“contactsCertificatesTypeString”, contactsCertificatesTypeString);
patient.getParam().put(
“provinceString”, provinceString);
patient.getParam().put(
“cityString”, cityString);
patient.getParam().put(
“districtString”, districtString);
patient.getParam().put(
“fullAddress”, provinceString + cityString + districtString + patient.getAddress());
return **patient;
}
}

2.4 添加controller

添加com.atguigu.yygh.user.api.PatientApiController

//就诊人管理接口@RestController
@RequestMapping(“/api/user/patient”)public class PatientApiController {
@Autowired
private PatientService patientService;
//获取就诊人列表
@GetMapping(“auth/findAll”)
public Result findAll(HttpServletRequest request) {
//获取当前登录用户id
_Long userId = AuthContextHolder._getUserId
(request);
List list = patientService.findAllUserId(userId);
return Result.ok(list);
}
//添加就诊人
@PostMapping(“auth/save”)
public Result savePatient(@RequestBody Patient patient,HttpServletRequest request) {
//获取当前登录用户id
_Long userId = AuthContextHolder._getUserId
(request);
patient.setUserId(userId);
patientService.save(patient);
return Result.ok();
}
//根据id获取就诊人信息
@GetMapping(“auth/get/{id}”)
public Result getPatient(@PathVariable Long id) {
Patient patient = patientService.getPatientId(id);
return Result.ok(patient);
}
//修改就诊人
@PostMapping(“auth/update”)
public Result updatePatient(@RequestBody Patient patient) {
patientService.updateById(patient);
return Result.ok();
}
//删除就诊人
@DeleteMapping(“auth/remove/{id}”)
public Result removePatient(@PathVariable Long id) {
patientService.removeById(id);
return Result.ok();
}
}

7 前端

3.1 封装api请求

创建/api/patient.js文件

import request from ‘@/utils/request’
const api_name = /api/user/patient
export default {
//就诊人列表
findList() {
return request({
url: ${api_name}/auth/findAll,
method: get
})
},
//根据id查询就诊人信息
getById(id) {
return request({
url: ${api_name}/auth/get/${id},
method: ‘get’
})
},
//添加就诊人信息
save(patient) {
return request({
url: ${api_name}/auth/save,
method: ‘post’,
data: patient
})
},
//修改就诊人信息
updateById(patient) {
return request({
url: ${api_name}/auth/update,
method: ‘post’,
data: patient
})
},
//删除就诊人信息
removeById(id) {
return request({
url: ${api_name}/auth/remove/${id},
method: ‘delete’
})
}
}

3.2 列表

添加/pages/patient/index.vue组件



3.3 添加与修改

添加/pages/patient/add.vue组件



3.4 详情与删除

添加/pages/patient/show.vue组件



四、平台用户管理

前面我们做了用户登录、用户认证与就诊人,现在我们需要把这些信息在我们的平台管理系统做一个统一管理
操作模块:service-user

8 用户列表

8.1 api接口

8.1.1 添加service接口与实现

1、在UserInfoService类添加接口

_//用户列表(条件查询带分页)_IPage selectPage(Page pageParam, UserInfoQueryVo userInfoQueryVo);

2、在UserInfoServiceImpl类添加实现

| //用户列表(条件查询带分页)
@Override
public IPage selectPage(Page 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 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 pages = baseMapper.selectPage(pageParam, wrapper);
//编号变成对应值封装
_pages.getRecords().stream().forEach(item -> {
this.packageUserInfo(item);
});
return pages;
}

_//编号变成对应值封装<br />    _**private **UserInfo packageUserInfo(UserInfo userInfo) {<br />        _//处理认证状态编码<br />        _userInfo.getParam().put(**"authStatusString"**,AuthStatusEnum._getStatusNameByStatus_(userInfo.getAuthStatus()));<br />        _//处理用户状态 0  1<br />        _String statusString = userInfo.getStatus().intValue()==0 ?**"锁定" **: **"正常"**;<br />        userInfo.getParam().put(**"statusString"**,statusString);<br />        **return **userInfo;<br />    } |

| —- |

8.1.2 添加controller方法

添加com.atguigu.yygh.user.controller.UserController类

| @RestController
@RequestMapping(“/admin/user”)public class UserController {

@Autowired<br />    **private **UserInfoService **userInfoService**;

_//用户列表(条件查询带分页)<br />    _@GetMapping(**"{page}/{limit}"**)<br />    **public **Result list(@PathVariable Long page,<br />                       @PathVariable Long limit,<br />                       UserInfoQueryVo userInfoQueryVo) {<br />        Page<UserInfo> pageParam = **new **Page<>(page,limit);<br />        IPage<UserInfo> pageModel =<br />                **userInfoService**.selectPage(pageParam,userInfoQueryVo);<br />        **return **Result._ok_(pageModel);<br />    }<br />} |

| —- |

8.2 前端

1.2.1 添加路由

在 src/router/index.js 文件添加路由

{
path: ‘/user’,
component: Layout,
redirect: ‘/user/userInfo/list’,
name: ‘userInfo’,
meta: { title: ‘用户管理’, icon: ‘table’ },
alwaysShow: true,
children: [
{
path: ‘userInfo/list’,
name: ‘用户列表’,
component: () =>import(‘@/views/user/userInfo/list’),
meta: { title: ‘用户列表’, icon: ‘table’ }
}
]
},

1.2.2封装api请求

创建/api/user/userInfo.js

import request from ‘@/utils/request’
const
api_name = ‘/admin/user’
export default
{
getPageList(page, limit, searchObj) { return request({ url: `${api_name}/${page}/${limit}`, method: ‘get’, params: searchObj
})
}
}

1.2.3 添加组件

创建/views/user/userInfo/list.vue组件


9 锁定

2.1 api接口

2.1.1添加service接口与实现

1、在UserInfoService类添加接口

/*
用户锁定
*
@param __userId* @param __status 0:锁定 1:正常
*/
void lock(Long userId, Integer status);

2、在UserInfoServiceImpl类添加实现

@Overridepublic void lock(Long userId, Integer status) {
if(status.intValue() == 0 || status.intValue() == 1) {
UserInfo userInfo = this.getById(userId);
userInfo.setStatus(status);
this.updateById(userInfo);
}
}

2.1.2添加controller方法

在UserController类添加方法

@ApiOperation(value = “锁定”)@GetMapping(“lock/{userId}/{status}”)public Result lock(
@PathVariable(“userId”) Long userId,
@PathVariable(“status”) Integer status){
userInfoService.lock(userId, status);
return Result.ok();
}

2.2前端

2.2.1 封装api请求

在/api/user/userInfo.js文件添加方法

lock(id, status) {
return request({
url: ${api_name}/lock/${id}/${status},
method: ‘get’
})
}

2.2.2 添加组件

修改/views/user/userInfo/list.vue组件



添加方法

// 锁定
lock(id, status) {
this.$confirm(‘确定该操作吗?’, ‘提示’, {
confirmButtonText: ‘确定’,
cancelButtonText: ‘取消’,
type: ‘warning’
}).then(() => { // promise
// 点击确定,远程调用ajax
return userInfoApi.lock(id, status)
}).then((response) => {
this.fetchData(this.page)
if (response.code) {
this.$message({
type: ‘success’,
message: ‘操作成功!’
})
}
})
}

10 详情

详情展示用户信息、用户就诊人信息和登录日志信息

3.1 api接口

3.1.1添加service接口与实现

1、在UserInfoService类添加接口

/*
详情
*
@param __userId* @return_*/_Map show(Long userId);

2、在UserInfoServiceImpl类添加实现

@Autowiredprivate PatientService patientService;
//用户详情@Overridepublic Map show(Long userId) {
Map map = new HashMap<>();
//根据userid查询用户信息
_UserInfo userInfo = this.packageUserInfo(baseMapper.selectById(userId));
map.put(“userInfo”,userInfo);
//根据userid查询就诊人信息
_List patientList = patientService.findAllUserId(userId);
map.put(“patientList”,patientList);
return map;
}

3.1.2添加controller方法

在UserController类添加方法

//用户详情@GetMapping(“show/{userId}”)public Result show(@PathVariable Long userId) {
Map map = userInfoService.show(userId);
return Result.ok(map);
}

3.2前端

3.2.1 添加路由

{
path: ‘/user’,
component: Layout,
redirect: ‘/user/userInfo/list’,
name: ‘userInfo’,
meta: { title: ‘用户管理’, icon: ‘table’ },
alwaysShow: true,
children: [
{
path: ‘userInfo/list’,
name: ‘用户列表’,
component: () =>import(‘@/views/user/userInfo/list’),
meta: { title: ‘用户列表’, icon: ‘table’ }
},
{
path: ‘userInfo/show/:id’,
name: ‘用户查看’,
component: () =>import(‘@/views/user/userInfo/show’),
meta: { title: ‘用户查看’ },
hidden: true
}
]
},

3.2.2封装api请求

在/api/user/userInfo.js文件添加方法

//用户详情
show(id) {
return request({
url: ${api_name}/show/${id},
method: ‘get’
})
}

3.2.3 修改列表组件



3.2.4 添加组件

添加/views/user/userInfo/show.vue组件


11 用户认证列表

api接口与用户列表一致,只是默认加了一个认证状态搜索条件:authStatus

4.1 添加路由

{
path: ‘userInfo/authList’,
name: ‘认证审批列表’,
component: () =>import(‘@/views/user/userInfo/authList’),
meta: { title: ‘认证审批列表’, icon: ‘table’ }
}

4.2 添加组件

添加/views/user/userInfo/authList.vue组件


12 用户认证审批

5.1 api接口

5.1.1添加service接口与实现

1、在UserInfoService类添加接口

/*
认证审批
*
@param __userId* @param __authStatus 2:通过 -1:不通过
*/
void approval(Long userId, Integer authStatus);

2、在UserInfoServiceImpl类添加实现

//认证审批 2通过 -1不通过@Overridepublic void approval(Long userId, Integer authStatus) {
if(authStatus.intValue()==2 || authStatus.intValue()==-1) {
UserInfo userInfo = baseMapper.selectById(userId);
userInfo.setAuthStatus(authStatus);
baseMapper.updateById(userInfo);
}
}

5.1.2添加controller方法

在UserController类添加方法

//认证审批@GetMapping(“approval/{userId}/{authStatus}”)public Result approval(@PathVariable Long userId,@PathVariable Integer authStatus) {
userInfoService.approval(userId,authStatus);
return Result.ok();
}

5.2 前端

5.2.1 封装api请求

在/api/userInfo.js文件添加方法

//认证审批
approval(id, authStatus) {
return request({
url: ${api_name}/approval/${id}/${authStatus},
method: ‘get’
})
}

5.2.2 添加组件

修改/views/user/userInfo/authList.vue组件



添加方法

// 审批
approval(id, authStatus) {
// debugger
this.$confirm(‘确定该操作吗?’, ‘提示’, {
confirmButtonText: ‘确定’,
cancelButtonText: ‘取消’,
type: ‘warning’
}).then(() => { // promise
// 点击确定,远程调用ajax
return userInfoApi.approval(id, authStatus)
}).then((response) => {
this.fetchData(this.page)
if (response.code) {
this.$message({
type: ‘success’,
message: ‘操作成功!’
})
}
})
}