目录
- 一、对象存储OSS
- 1、开通“对象存储OSS”服务
- 2、创建Bucket
- 3、上传默认头像
- 4、创建RAM用户
- 5、使用SDK
- 二、后端集成OSS
- 1、新建云存储微服务
- 2、实现文件上传接口
- 三、用户认证功能
- 1、用户认证需求分析
- 2、开发用户认证接口
- 3、用户认证前端
一、对象存储OSS
用户认证需要上传证件图片、首页轮播也需要上传图片,因此我们要做文件服务,阿里云oss是一个很好的分布式文件服务系统,所以我们只需要集成阿里云oss即可
1、开通“对象存储OSS”服务
(1)申请阿里云账号
(2)实名认证
(3)开通“对象存储OSS”服务
(4)进入管理控制台
2、创建Bucket
选择:标准存储、公共读、不开通
3、上传默认头像
创建文件夹avatar,上传默认的用户头像
4、创建RAM用户
5、使用SDK
二、后端集成OSS
1、新建云存储微服务
1、在service模块下创建子模块service_oss
2、配置pom.xml
service-oss上级模块service已经引入service的公共依赖,service-oss模块只需引入阿里云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>
3、配置application.properties
#服务端口
server.port=8205
#服务名
spring.application.name=service-oss
#环境设置:dev、test、prod
spring.profiles.active=dev
#上传单个文件的最大值1G
spring.servlet.multipart.max-file-size=1024MB
#一次请求上传的所有文件的总大小1G
spring.servlet.multipart.max-request-size=1024MB
#阿里云 OSS
#不同的服务器,地址不同
aliyun.oss.file.endpoint=oss-cn-beijing.aliyuncs.com
aliyun.oss.file.keyid=your accessKeyId
aliyun.oss.file.keysecret=your accessKeySecret
#bucket可以在控制台创建,也可以使用java代码创建
aliyun.oss.file.bucketname=guli-file
4、创建启动类
创建OssApplication.java
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.context.annotation.ComponentScan;
@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
@ComponentScan(basePackages = {"com.donglin"})
public class OssApplication {
public static void main(String[] args) {
SpringApplication.run(OssApplication.class, args);
}
}
2、实现文件上传接口
1、从配置文件读取常量
创建常量读取工具类:ConstantPropertiesUtil.java
使用@Value读取application.properties里的配置内容
用spring的 InitializingBean 的 afterPropertiesSet 来初始化配置信息,这个方法将在所有的属性被初始化后调用。
/**
* 常量类,读取配置文件application.properties中的配置
*/
@Component
//@PropertySource("classpath:application.properties")
public class ConstantPropertiesUtil implements InitializingBean {
@Value("${aliyun.oss.file.endpoint}")
private String endpoint;
@Value("${aliyun.oss.file.keyid}")
private String keyId;
@Value("${aliyun.oss.file.keysecret}")
private String keySecret;
@Value("${aliyun.oss.file.bucketname}")
private String bucketName;
public static String END_POINT;
public static String ACCESS_KEY_ID;
public static String ACCESS_KEY_SECRET;
public static String BUCKET_NAME;
@Override
public void afterPropertiesSet() throws Exception {
END_POINT = endpoint;
ACCESS_KEY_ID = keyId;
ACCESS_KEY_SECRET = keySecret;
BUCKET_NAME = bucketName;
}
}
2、文件上传
创建Service接口:OssService .java
public interface OssService {
String upload(MultipartFile file);
}
实现:OssServiceImpl.java
参考SDK中的:Java->上传文件->简单上传->流式上传->上传文件流
@Service
public class OssServiceImpl implements OssService {
@Override
public String upload(MultipartFile file) {
// Endpoint以华东1(杭州)为例,其它Region请按实际情况填写。
String endpoint = ConstantPropertiesUtil.END_POINT;
// 阿里云账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM用户进行API访问或日常运维,请登录RAM控制台创建RAM用户。
String accessKeyId = ConstantPropertiesUtil.ACCESS_KEY_ID;
String accessKeySecret = ConstantPropertiesUtil.ACCESS_KEY_SECRET;
// 填写Bucket名称,例如examplebucket。
String bucketName = ConstantPropertiesUtil.BUCKET_NAME;
// 创建OSSClient实例。
OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
try {
// 上传文件流。
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);
//上传之后文件路径
// https://yygh-donglin.oss-cn-chengdu.aliyuncs.com/01.jpg
String url = "https://"+bucketName+"."+endpoint+"/"+fileName;
//返回
return url;
} catch (IOException e) {
e.printStackTrace();
return null;
} finally {
if (ossClient != null) {
ossClient.shutdown();
}
}
}
}
3、创建Controller
FileUploadController.java
@Api(tags="阿里云文件管理")
@RestController
@RequestMapping("/admin/oss/file")
public class FileUploadController {
@Autowired
private OssService ossService;
/**
* 文件上传
*/
@ApiOperation(value = "文件上传")
@PostMapping("upload")
public R upload(MultipartFile file){
String uploadUrl = ossService.upload(file);
return R.ok().data("url",uploadUrl);
}
}
4、配置网关
properties
#设置路由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/**
yml
三、用户认证功能
1、用户认证需求分析
1、需求分析
用户登录成功后都要进行身份认证,认证通过后才可以预约挂号
认证过程:用户填写信息(姓名、证件类型、证件号码和证件照片)==> 平台审批
用户认证设计接口:
1、提交认证
2、上传证件图片
3、获取提交认证信息
2、开发用户认证接口
操作service_user模块
1、添加service接口及实现
(1)在UserInfoService类添加接口
//用户认证
UserInfo getUserInfo(Long userId);
(2)在UserInfoServiceImpl添加实现
@Override
public UserInfo getUserInfo(Long userId) {
UserInfo userInfo = baseMapper.selectById(userId);
userInfo.getParam().put("authStatusString", AuthStatusEnum.getStatusNameByStatus(userInfo.getStatus()));
return userInfo;
}
2、添加controller方法
在UserInfoController类添加方法
// //获取用户id信息接口
// @GetMapping("auth/getUserInfo")
// public R getUserInfo(HttpServletRequest request) {
// Long userId = AuthContextHolder.getUserId(request);
// UserInfo userInfo = userInfoService.getById(userId);
// return R.ok().data("userInfo",userInfo);
// }
//查询用户信息
@GetMapping("/info")
public R getUserInfo(@RequestHeader String token){
Long userId = JwtHelper.getUserId(token);
UserInfo byId = userInfoService.getUserInfo(userId);
return R.ok().data("user",byId);
}
//提交之后修改用户信息
@PutMapping("/update")
public R update(@RequestHeader String token, @RequestBody UserAuthVo userAuthVo){
Long userId = JwtHelper.getUserId(token);
UserInfo userInfo = new UserInfo();
userInfo.setId(userId);
userInfo.setName(userAuthVo.getName());
userInfo.setCertificatesType(userAuthVo.getCertificatesType());
userInfo.setCertificatesNo(userAuthVo.getCertificatesNo());
userInfo.setCertificatesUrl(userAuthVo.getCertificatesUrl());
userInfo.setAuthStatus(AuthStatusEnum.AUTH_RUN.getStatus());
userInfoService.updateById(userInfo);
return R.ok();
}
3、用户认证前端
1、封装api请求
在api/userInfo.js添加方法
import request from '@/utils/request'
const api_name = `/user/userinfo`
export default {
getUserInfo() {
return request({
url: `${api_name}/info`,
method: `get`
})
},
saveUserAuah(userAuah) {
return request({
url: `${api_name}/update`,
method: 'put',
data: userAuah
})
}
}
2、页面展示
(1)myheader.vue页面添加方法
loginMenu(command) {
if('/logout' == command) {
cookie.set('name', '', {domain: 'localhost'})
cookie.set('token', '', {domain: 'localhost'})
//跳转页面
window.location.href = '/'
} else {
window.location.href = command
}
}
(2)修改utils/request.js文件
//引入js-cookie
import cookie from 'js-cookie'
// http request 拦截器 //浏览器访问服务器
service.interceptors.request.use(
config => {
// token 先不处理,后续使用时在完善
if (cookie.get('token')) {
//cookie本身不能跨域
config.headers['token'] = cookie.get('token')
}
return config
},
err => {
return Promise.reject(err)
})
(3)创建pages/user/index.vue
我们需要在pages下user文件下创建
<template>
<!-- header -->
<div class="nav-container page-component">
<!--左侧导航 #start -->
<div class="nav left-nav">
<div class="nav-item selected">
<span class="v-link selected dark" onclick="javascript:window.location='/user'">实名认证 </span>
</div>
<div class="nav-item">
<span class="v-link selected dark" onclick="javascript:window.location='/order'"> 挂号订单 </span>
</div>
<div class="nav-item ">
<span class="v-link clickable dark" onclick="javascript:window.location='/patient'"> 就诊人管理 </span>
</div>
<div class="nav-item ">
<span class="v-link clickable dark"> 修改账号信息 </span>
</div>
<div class="nav-item ">
<span class="v-link clickable dark"> 意见反馈 </span>
</div>
</div>
<!-- 左侧导航 #end -->
<!-- 右侧内容 #start -->
<div class="page-container">
<div>
<div class="title"> 实名认证</div>
<div class="status-bar">
<div class="status-wrapper"><span class="iconfont"></span>{{ userInfo.param.authStatusString }}</div>
</div>
<div class="tips"><span class="iconfont"></span>
完成实名认证后才能添加就诊人,正常进行挂号,为了不影响后续步骤,建议提前实名认证。
</div>
<div class="form-wrapper" v-if="userInfo.authStatus == 0">
<div>
<el-form :model="userAuah" label-width="110px" label-position="left">
<el-form-item prop="name" label="姓名:" class="form-normal">
<div class="name-input">
<el-input v-model="userAuah.name" placeholder="请输入联系人姓名全称" class="input v-input"/>
</div>
</el-form-item>
<el-form-item prop="certificatesType" label="证件类型:">
<el-select v-model="userAuah.certificatesType" placeholder="请选择证件类型" class="v-select patient-select">
<el-option
v-for="item in certificatesTypeList"
:key="item.value"
:label="item.name"
:value="item.name">
</el-option>
</el-select>
</el-form-item>
<el-form-item prop="certificatesNo" label="证件号码:">
<el-input v-model="userAuah.certificatesNo" placeholder="请输入联系人证件号码" class="input v-input"/>
</el-form-item>
<el-form-item prop="name" label="上传证件:">
<div class="upload-wrapper">
<div class="avatar-uploader">
<el-upload
class="avatar-uploader"
:action="fileUrl"
:show-file-list="false"
:on-success="onUploadSuccess">
<div class="upload-inner-wrapper">
<img v-if="userAuah.certificatesUrl" :src="userAuah.certificatesUrl" class="avatar">
<i v-else class="el-icon-plus avatar-uploader-icon"></i>
<div v-if="!userAuah.certificatesUrl" class="text"> 上传证件合照</div>
</div>
</el-upload>
</div>
<img src="//img.114yygh.com/static/web/auth_example.png" class="example">
</div>
</el-form-item>
</el-form>
<div class="bottom-wrapper">
<div class="button-wrapper">
<div class="v-button" @click="saveUserAuah()">{{ submitBnt }}</div>
</div>
</div>
</div>
</div>
<div class="context-container" v-if="userInfo.authStatus != 0">
<div>
<el-form :model="formData" label-width="110px" label-position="right">
<el-form-item prop="name" label="姓名:" class="form-normal">
<div class="name-input">
{{ userInfo.name }}
</div>
</el-form-item>
<el-form-item prop="name" label="证件类型:">
{{ userInfo.certificatesType }}
</el-form-item>
<el-form-item prop="name" label="证件号码:">
{{ userInfo.certificatesNo }}
</el-form-item>
</el-form>
</div>
</div>
</div>
</div><!-- 右侧内容 #end -->
<!-- 登录弹出框 -->
</div>
<!-- footer -->
</template>
<script>
import '~/assets/css/hospital_personal.css'
import '~/assets/css/hospital.css'
import '~/assets/css/personal.css'
import dictApi from '@/api/dict'
import userInfoApi from '@/api/userInfo'
const defaultForm = {
name: '',
certificatesType: '',
certificatesNo: '',
certificatesUrl: ''
}
export default {
data() {
return {
formData:{},
userAuah: defaultForm,
certificatesTypeList: [],
fileUrl:'http://localhost:8222/admin/oss/file/upload',
userInfo: {
param: {}
},
submitBnt: '提交'
}
},
//create 钩子函数:发送预请求----》请求到后端接口,自己写的请求
//mouted 钩子函数:发送预请求----》不会请求到后端接口,自己写的请求
mounted() {
this.init()
},
methods: {
init() {
this.getUserInfo()
this.getDict()
},
getUserInfo() {
userInfoApi.getUserInfo().then(response => {
this.userInfo = response.data.user
})
},
saveUserAuah() {
if(this.submitBnt == '正在提交...') {
this.$message.info('重复提交')
return
}
this.submitBnt = '正在提交...'
userInfoApi.saveUserAuah(this.userAuah).then(response => {
this.$message.success("提交成功")
window.location.reload()
}).catch(e => {
this.submitBnt = '提交'
})
},
getDict() {
dictApi.getChildList(20000).then(response => {
this.certificatesTypeList = response.data.items
})
},
//axios:Response.data---->R对象
//el-upload:response----->对象
onUploadSuccess(response, file) {
if(response.code !== 20000) {
this.$message.error("上传失败")
return
}
// 填充上传文件列表
this.userAuah.certificatesUrl = response.data.url
}
}
}
</script>
<style>
.header-wrapper .title {
font-size: 16px;
margin-top: 0;
}
.content-wrapper {
margin-left: 0;
}
.patient-card .el-card__header .detail {
font-size: 14px;
}
.page-container .title {
letter-spacing: 1px;
font-weight: 700;
color: #333;
font-size: 16px;
margin-top: 0;
margin-bottom: 20px;
}
.page-container .tips {
width: 100%;
padding-left: 0;
}
.page-container .form-wrapper {
padding-left: 92px;
width: 580px;
}
.form-normal {
height: 40px;
}
.bottom-wrapper{
width: 100%;
padding: 0;
margin-top: 0;
}
</style>
3、预约挂号页面跳转
点击门诊信息,你注册过了,判断实名认证过了没有,没有就不能跳到门诊信息里面,返回到实名认证页面
import cookie from 'js-cookie' //引入cookie
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.user.authStatus
// 状态为2认证通过
if (!authStatus || authStatus != 2) {
window.location.href = '/user'
return
}else{
window.location.href = '/hospital/schedule?hoscode=' + this.hospital.hoscode + "&depcode="+ depcode
}
})
}