目录
- 一、就诊人管理需求和接口开发
- 1、需求
- 2、就诊人管理接口
- 二、就诊人管理前端整合
- 1、封装api请求
- 2、就诊人列表
- 3、就诊人添加与修改
- 4、就诊人详情与删除
- 三、平台用户管理-用户列表
- 1、用户列表接口
- 2、用户列表前端整合
- 四、平台用户管理-用户锁定
- 五、平台用户管理-用户详情
- 1、用户详情接口
- 六、用户认证列表
- 1、用户认证列表接口
- 2、用户认证列表前端
- 七、用户认证审批![在这里插入图片描述](https://img-blog.csdnimg.cn/375e9cdb8d9c4ee7aca9f7c3355c2333.png)
- 1、用户认证审批接口
- 2、用户认证审批前端
一、就诊人管理需求和接口开发
1、需求
预约下单需要选择就诊人,因此我们要实现就诊人管理,就诊人管理其实就是要实现一个完整的增删改查
2、就诊人管理接口
(1)引入依赖
java"><dependencies>
<dependency>
<groupId>com.donglin</groupId>
<artifactId>service_cmn_client</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
</dependencies>
(2)添加PatientMapper
java">public interface PatientMapper extends BaseMapper<Patient> {
}
(3)添加PatientService
前端需要这个类型,这里用了openfeign,远程调用cmn服务器
java">public interface PatientService extends IService<Patient> {
List<Patient> findAll(String token);
Patient getPatient(Long id);
}
(4)添加PatientServiceImpl
java">@Service
public class PatientServiceImpl extends ServiceImpl<PatientMapper, Patient> implements PatientService {
@Autowired
private DictFeignClient dictFeignClient;
@Override
public List<Patient> findAll(@RequestHeader String token) {
Long userId = JwtHelper.getUserId(token);
QueryWrapper<Patient> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("user_id",userId);
List<Patient> patients = baseMapper.selectList(queryWrapper);
patients.stream().forEach(item->{
this.packagePatient(item);
});
return patients;
}
@Override
public Patient getPatient(Long id) {
Patient patients = baseMapper.selectById(id);
this.packagePatient(patients);
return patients;
}
private void packagePatient(Patient item) {
item.getParam().put("certificatesTypeString",dictFeignClient.getNameByValue(Long.parseLong(item.getCertificatesType())));
item.getParam().put("provinceString",dictFeignClient.getNameByValue(Long.parseLong(item.getProvinceCode())));
item.getParam().put("cityString",dictFeignClient.getNameByValue(Long.parseLong(item.getCityCode())));
item.getParam().put("districtString",dictFeignClient.getNameByValue(Long.parseLong(item.getDistrictCode())));
}
}
(5)添加PatientController
java">@RestController
@RequestMapping("/user/userinfo/patient")
public class PatientController {
@Autowired
private PatientService patientService;
//获取就诊人列表
@GetMapping("/all")
public R findAll(@RequestHeader String token) {
List<Patient> list = patientService.findAll(token);
return R.ok().data("list",list);
}
//添加就诊人
@PostMapping("/save")
public R savePatient(@RequestBody Patient patient, @RequestHeader String token) {
//获取当前登录用户id
Long userId = JwtHelper.getUserId(token);
patient.setUserId(userId);
patientService.save(patient);
return R.ok();
}
//根据id获取就诊人信息,修改就诊人信息时回显
@GetMapping("detail/{id}")
public R getPatient(@PathVariable Long id) {
Patient patient = patientService.getPatient(id);
return R.ok().data("patient",patient);
}
//修改就诊人
@PostMapping("/update")
public R updatePatient(@RequestBody Patient patient) {
patientService.updateById(patient);
return R.ok();
}
//删除就诊人
@DeleteMapping("/remove/{id}")
public R removePatient(@PathVariable Long id) {
patientService.removeById(id);
return R.ok();
}
}
二、就诊人管理前端整合
1、封装api请求
创建api/patient.js
java">import request from '@/utils/request'
const api_name = `/user/userinfo/patient`
export default {
//就诊人列表
findList() {
return request({
url: `${api_name}/all`,
method: `get`
})
},
//根据id查询就诊人信息
getById(id) {
return request({
url: `${api_name}/detail/${id}`,
method: 'get'
})
},
//添加就诊人信息
save(patient) {
return request({
url: `${api_name}/save`,
method: 'post',
data: patient
})
},
//修改就诊人信息
updateById(patient) {
return request({
url: `${api_name}/update`,
method: 'post',
data: patient
})
},
//删除就诊人信息
removeById(id) {
return request({
url: `${api_name}/remove/${id}`,
method: 'delete'
})
}
}
2、就诊人列表
创建pages/patient/index.vue
java"><template>
<!-- header -->
<div class="nav-container page-component">
<!--左侧导航 #start -->
<div class="nav left-nav">
<div class="nav-item ">
<span class="v-link clickable dark" onclick="javascript:window.location='/user'">实名认证 </span>
</div>
<div class="nav-item ">
<span class="v-link clickable dark" onclick="javascript:window.location='/order'"> 挂号订单 </span>
</div>
<div class="nav-item selected">
<span class="v-link selected 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 class="personal-patient">
<div class="header-wrapper">
<div class="title"> 就诊人管理</div>
</div>
<div class="content-wrapper">
<el-card class="patient-card" shadow="always" v-for="item in patientList" :key="item.id">
<div slot="header" class="clearfix">
<div>
<span class="name">{{ item.name }}</span>
<span>{{ item.certificatesNo }} {{ item.param.certificatesTypeString }}</span>
<div class="detail" @click="show(item.id)"> 查看详情 <span class="iconfont"></span></div>
</div>
</div>
<div class="card SELF_PAY_CARD">
<div class="info">
<span class="type">{{ item.isInsure == 0 ? '自费' : '医保'}}</span>
<span class="card-no">{{ item.certificatesNo }}</span>
<span class="card-view">{{ item.param.certificatesTypeString }}</span>
</div>
<span class="operate"></span>
</div>
<div class="card">
<div class="text bind-card"></div>
</div>
</el-card>
<div class="item-add-wrapper v-card clickable" @click="add()">
<div class="">
<div>+ 添加就诊人</div>
</div>
</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 patientApi from '@/api/patient'
export default {
data() {
return {
patientList: []
}
},
mounted() {
this.findPatientList()
},
methods: {
findPatientList() {
patientApi.findList().then(response => {
this.patientList = response.data.list
console.log(this.patientList)
})
},
add() {
window.location.href = '/patient/add'
},
show(id) {
window.location.href = '/patient/show?id=' + id
}
}
}
</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;
}
</style>
3、就诊人添加与修改
添加/pages/patient/add.vue组件
java"><template>
<!-- header -->
<div class="nav-container page-component">
<!--左侧导航 #start -->
<div class="nav left-nav">
<div class="nav-item ">
<span class="v-link clickable dark" onclick="javascript:window.location='/user'">实名认证 </span>
</div>
<div class="nav-item ">
<span class="v-link clickable dark" onclick="javascript:window.location='/order'"> 挂号订单 </span>
</div>
<div class="nav-item selected">
<span class="v-link selected 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 class="personal-patient">
<div class="header-wrapper">
<div class="title"> 添加就诊人</div>
</div>
<div>
<div class="sub-title">
<div class="block"></div>
就诊人信息
</div>
<div class="content-wrapper">
<el-form :model="patient" label-width="110px" label-position="left" ref="patient" :rules="validateRules">
<el-form-item prop="name" label="姓名:">
<el-input v-model="patient.name" placeholder="请输入真实姓名全称" class="input v-input"/>
</el-form-item>
<el-form-item prop="certificatesType" label="证件类型:">
<el-select v-model="patient.certificatesType" placeholder="请选择证件类型" class="v-select patient-select">
<el-option
v-for="item in certificatesTypeList"
:key="item.value"
:label="item.name"
:value="item.value">
</el-option>
</el-select>
</el-form-item>
<el-form-item prop="certificatesNo" label="证件号码:">
<el-input v-model="patient.certificatesNo" placeholder="请输入证件号码" class="input v-input"/>
</el-form-item>
<el-form-item prop="sex" label="性别:">
<el-radio-group v-model="patient.sex">
<el-radio :label="1">男</el-radio>
<el-radio :label="0">女</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item prop="birthdate" label="出生日期:">
<el-date-picker
v-model="patient.birthdate"
class="v-date-picker"
type="date"
placeholder="选择日期">
</el-date-picker>
</el-form-item>
<el-form-item prop="phone" label="手机号码:">
<el-input v-model="patient.phone" placeholder="请输入手机号码" maxlength="11" class="input v-input"/>
</el-form-item>
</el-form>
</div>
<div class="sub-title">
<div class="block"></div>
建档信息(完善后部分医院首次就诊不排队建档)
</div>
<div class="content-wrapper">
<el-form :model="patient" label-width="110px" label-position="left" ref="patient" :rules="validateRules">
<el-form-item prop="isMarry" label="婚姻状况:">
<el-radio-group v-model="patient.isMarry">
<el-radio :label="0">未婚</el-radio>
<el-radio :label="1">已婚</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item prop="isInsure" label="自费/医保:">
<el-radio-group v-model="patient.isInsure">
<el-radio :label="0">自费</el-radio>
<el-radio :label="1">医保</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item prop="addressSelected" label="当前住址:">
<el-cascader
ref="selectedShow"
v-model="patient.addressSelected"
class="v-address"
:props="props"></el-cascader>
</el-form-item>
<el-form-item prop="address" label="详细地址:">
<el-input v-model="patient.address" placeholder="应公安机关要求,请填写现真实住址" class="input v-input"/>
</el-form-item>
</el-form>
</div>
<div class="sub-title">
<div class="block"></div>
联系人信息(选填)
</div>
<div class="content-wrapper">
<el-form :model="patient" label-width="110px" label-position="left">
<el-form-item prop="contactsName" label="姓名:">
<el-input v-model="patient.contactsName" placeholder="请输入联系人姓名全称" class="input v-input"/>
</el-form-item>
<el-form-item prop="contactsCertificatesType" label="证件类型:">
<el-select v-model="patient.contactsCertificatesType" placeholder="请选择证件类型" class="v-select patient-select">
<el-option
v-for="item in certificatesTypeList"
:key="item.value"
:label="item.name"
:value="item.value">
</el-option>
</el-select>
</el-form-item>
<el-form-item prop="contactsCertificatesNo" label="证件号码:">
<el-input v-model="patient.contactsCertificatesNo" placeholder="请输入联系人证件号码" class="input v-input"/>
</el-form-item>
<el-form-item prop="contactsPhone" label="手机号码:">
<el-input v-model="patient.contactsPhone" placeholder="请输入联系人手机号码" class="input v-input"/>
</el-form-item>
</el-form>
</div>
</div>
<div class="bottom-wrapper">
<div class="button-wrapper">
<div class="v-button" @click="saveOrUpdate()">{{ submitBnt }}</div>
</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/yygh/dict'
import patientApi from '@/api/yygh/patient'
const defaultForm = {
name: '',
certificatesType: '',
certificatesNo: '',
sex: 1,
birthdate: '',
phone: '',
isMarry: 0,
isInsure: 0,
provinceCode: '',
cityCode: '',
districtCode: '',
addressSelected: null,
address: '',
contactsName: '',
contactsCertificatesType: '',
contactsCertificatesNo: '',
contactsPhone: '',
param: {}
}
export default {
data() {
return {
patient: defaultForm,
certificatesTypeList: [],
props: {
lazy: true,
async lazyLoad (node, resolve) {
const { level } = node
//异步获取省市区
dictApi.findByParentId(level ? node.value : '86').then(response => {
let list= response.data.list
let provinceList = list.map((item, i) => {
return {
value: item.id,
label: item.name,
leaf: node.level == 2 ? true : false,//可控制显示几级
}
})
resolve && resolve(provinceList)
})
}
},
submitBnt: '保存',
validateRules: {
name: [{ required: true, trigger: 'blur', message: '必须输入' }],
certificatesType: [{ required: true, trigger: 'blur', message: '必须输入' }],
certificatesNo: [{ required: true, trigger: 'blur', message: '必须输入' }],
birthdate: [{ required: true, trigger: 'blur', message: '必须输入' }],
phone: [{ required: true, trigger: 'blur', message: '必须输入' }],
addressSelected: [{ required: true, trigger: 'blur', message: '必须输入' }],
address: [{ required: true, trigger: 'blur', message: '必须输入' }]
}
}
},
created() {
this.init();
},
mounted() {
if (this.$route.query.id) {
setTimeout(()=>{
this.$refs.selectedShow.presentText = this.patient.param.provinceString + '/' + this.patient.param.cityString + '/' +this.patient.param.districtString //"北京市/市辖区/西城区";// 首次手动复制
// this.$refs.selectedShow.value = '110000/110100/110102';
},1000)
}
},
methods: {
init() {
if (this.$route.query.id) {
const id = this.$route.query.id
this.fetchDataById(id)
} else {
// 对象拓展运算符:拷贝对象,而不是赋值对象的引用
this.patient = { ...defaultForm }
}
this.getDict()
},
fetchDataById(id) {
patientApi.getById(id).then(response => {
this.patient = response.data.patient
//添加默认值
this.patient.addressSelected = [this.patient.provinceCode, this.patient.cityCode, this.patient.districtCode]
})
},
getDict() {
dictApi.findByDictCode("CertificatesType").then(response => {
this.certificatesTypeList = response.data.list
})
},
saveOrUpdate() {
this.$refs.patient.validate(valid => {
if (valid) {
//地址处理
if(this.patient.addressSelected.length == 3) {
this.patient.provinceCode = this.patient.addressSelected[0]
this.patient.cityCode = this.patient.addressSelected[1]
this.patient.districtCode = this.patient.addressSelected[2]
}
if (!this.patient.id) {
this.saveData()
} else {
this.updateData()
}
}
})
},
// 新增
saveData() {
if(this.submitBnt == '正在提交...') {
this.$message.info('重复提交')
return
}
this.submitBnt = '正在提交...'
patientApi.save(this.patient).then(response => {
this.$message.success("提交成功")
window.location.href = '/patient'
}).catch(e => {
this.submitBnt = '保存'
})
},
// 根据id更新记录
updateData() {
if(this.submitBnt == '正在提交...') {
this.$message.info('重复提交')
return
}
this.submitBnt = '正在提交...'
patientApi.updateById(this.patient).then(response => {
this.$message.success("提交成功")
window.location.href = '/patient'
}).catch(e => {
this.submitBnt = '保存'
})
}
}
}
</script>
<style>
.header-wrapper .title {
font-size: 16px;
margin-top: 0;
}
.sub-title {
margin-top: 0;
}
.bottom-wrapper{
padding: 0;
margin: 0;
}
.bottom-wrapper .button-wrapper{
margin-top: 0;
}
</style>
4、就诊人详情与删除
添加/pages/patient/show.vue组件
java"><template>
<!-- header -->
<div class="nav-container page-component">
<!--左侧导航 #start -->
<div class="nav left-nav">
<div class="nav-item ">
<span class="v-link clickable dark" onclick="javascript:window.location='/user'">实名认证 </span>
</div>
<div class="nav-item ">
<span class="v-link clickable dark" onclick="javascript:window.location='/order'"> 挂号订单 </span>
</div>
<div class="nav-item selected">
<span class="v-link selected 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 class="personal-patient">
<div class="header-wrapper">
<div class="title"> 添加就诊人</div>
</div>
<div>
<div class="sub-title">
<div class="block"></div>
就诊人信息
</div>
<div class="content-wrapper">
<el-form :model="patient" label-width="110px" label-position="left" ref="patient" :rules="validateRules">
<el-form-item prop="name" label="姓名:">
<el-input v-model="patient.name" placeholder="请输入真实姓名全称" class="input v-input"/>
</el-form-item>
<el-form-item prop="certificatesType" label="证件类型:">
<el-select v-model="patient.certificatesType" placeholder="请选择证件类型" class="v-select patient-select">
<el-option
v-for="item in certificatesTypeList"
:key="item.value"
:label="item.name"
:value="item.value">
</el-option>
</el-select>
</el-form-item>
<el-form-item prop="certificatesNo" label="证件号码:">
<el-input v-model="patient.certificatesNo" placeholder="请输入证件号码" class="input v-input"/>
</el-form-item>
<el-form-item prop="sex" label="性别:">
<el-radio-group v-model="patient.sex">
<el-radio :label="1">男</el-radio>
<el-radio :label="0">女</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item prop="birthdate" label="出生日期:">
<el-date-picker
v-model="patient.birthdate"
class="v-date-picker"
type="date"
placeholder="选择日期">
</el-date-picker>
</el-form-item>
<el-form-item prop="phone" label="手机号码:">
<el-input v-model="patient.phone" placeholder="请输入手机号码" maxlength="11" class="input v-input"/>
</el-form-item>
</el-form>
</div>
<div class="sub-title">
<div class="block"></div>
建档信息(完善后部分医院首次就诊不排队建档)
</div>
<div class="content-wrapper">
<el-form :model="patient" label-width="110px" label-position="left" ref="patient" :rules="validateRules">
<el-form-item prop="isMarry" label="婚姻状况:">
<el-radio-group v-model="patient.isMarry">
<el-radio :label="0">未婚</el-radio>
<el-radio :label="1">已婚</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item prop="isInsure" label="自费/医保:">
<el-radio-group v-model="patient.isInsure">
<el-radio :label="0">自费</el-radio>
<el-radio :label="1">医保</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item prop="addressSelected" label="当前住址:">
<el-cascader
ref="selectedShow"
v-model="patient.addressSelected"
class="v-address"
:props="props"></el-cascader>
</el-form-item>
<el-form-item prop="address" label="详细地址:">
<el-input v-model="patient.address" placeholder="应公安机关要求,请填写现真实住址" class="input v-input"/>
</el-form-item>
</el-form>
</div>
<div class="sub-title">
<div class="block"></div>
联系人信息(选填)
</div>
<div class="content-wrapper">
<el-form :model="patient" label-width="110px" label-position="left">
<el-form-item prop="contactsName" label="姓名:">
<el-input v-model="patient.contactsName" placeholder="请输入联系人姓名全称" class="input v-input"/>
</el-form-item>
<el-form-item prop="contactsCertificatesType" label="证件类型:">
<el-select v-model="patient.contactsCertificatesType" placeholder="请选择证件类型" class="v-select patient-select">
<el-option
v-for="item in certificatesTypeList"
:key="item.value"
:label="item.name"
:value="item.value">
</el-option>
</el-select>
</el-form-item>
<el-form-item prop="contactsCertificatesNo" label="证件号码:">
<el-input v-model="patient.contactsCertificatesNo" placeholder="请输入联系人证件号码" class="input v-input"/>
</el-form-item>
<el-form-item prop="contactsPhone" label="手机号码:">
<el-input v-model="patient.contactsPhone" placeholder="请输入联系人手机号码" class="input v-input"/>
</el-form-item>
</el-form>
</div>
</div>
<div class="bottom-wrapper">
<div class="button-wrapper">
<div class="v-button" @click="saveOrUpdate()">{{ submitBnt }}</div>
</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 patientApi from '@/api/patient'
const defaultForm = {
name: '',
certificatesType: '',
certificatesNo: '',
sex: 1,
birthdate: '',
phone: '',
isMarry: 0,
isInsure: 0,
provinceCode: '',
cityCode: '',
districtCode: '',
addressSelected: null,
address: '',
contactsName: '',
contactsCertificatesType: '',
contactsCertificatesNo: '',
contactsPhone: '',
param: {}
}
export default {
data() {
return {
patient: defaultForm,
certificatesTypeList: [],
props: {
lazy: true,
async lazyLoad (node, resolve) {
const { level } = node
//异步获取省市区
dictApi.getChildList(level ? node.value : '86').then(response => {
let list= response.data.items
let provinceList = list.map((item, i) => {
return {
value: item.id,
label: item.name,
leaf: node.level == 2 ? true : false,//可控制显示几级
}
})
//作用:将当前元素的子元素列表都挂在到当前元素下边
resolve && resolve(provinceList)
})
}
},
submitBnt: '保存',
validateRules: {
name: [{ required: true, trigger: 'blur', message: '必须输入' }],
certificatesType: [{ required: true, trigger: 'blur', message: '必须输入' }],
certificatesNo: [{ required: true, trigger: 'blur', message: '必须输入' }],
birthdate: [{ required: true, trigger: 'blur', message: '必须输入' }],
phone: [{ required: true, trigger: 'blur', message: '必须输入' }],
addressSelected: [{ required: true, trigger: 'blur', message: '必须输入' }],
address: [{ required: true, trigger: 'blur', message: '必须输入' }]
}
}
},
created() {
this.init();
},
mounted() {
if (this.$route.query.id) {
setTimeout(()=>{
this.$refs.selectedShow.presentText = this.patient.param.provinceString + '/' + this.patient.param.cityString + '/' +this.patient.param.districtString //"北京市/市辖区/西城区";// 首次手动复制
// this.$refs.selectedShow.value = '110000/110100/110102';
},1000)
}
},
methods: {
init() {
if (this.$route.query.id) {
const id = this.$route.query.id
this.fetchDataById(id)
} else {
// 对象拓展运算符:拷贝对象,而不是赋值对象的引用
this.patient = { ...defaultForm }
}
this.getDict()
},
fetchDataById(id) {
patientApi.getById(id).then(response => {
this.patient = response.data.patient
//添加默认值
this.patient.addressSelected = [this.patient.provinceCode, this.patient.cityCode, this.patient.districtCode]
})
},
getDict() {
dictApi.getChildList(20000).then(response => {
this.certificatesTypeList = response.data.items
})
},
saveOrUpdate() {
this.$refs.patient.validate(valid => {
if (valid) {
//地址处理
if(this.patient.addressSelected.length == 3) {
this.patient.provinceCode = this.patient.addressSelected[0]
this.patient.cityCode = this.patient.addressSelected[1]
this.patient.districtCode = this.patient.addressSelected[2]
}
if (!this.patient.id) {
this.saveData() //添加
} else {
this.updateData() //修改
}
}
})
},
// 新增
saveData() {
if(this.submitBnt == '正在提交...') {
this.$message.info('重复提交')
return
}
this.submitBnt = '正在提交...'
patientApi.save(this.patient).then(response => {
this.$message.success("提交成功")
window.location.href = '/patient'
}).catch(e => {
this.submitBnt = '保存'
})
},
// 根据id更新记录
updateData() {
if(this.submitBnt == '正在提交...') {
this.$message.info('重复提交')
return
}
this.submitBnt = '正在提交...'
patientApi.updateById(this.patient).then(response => {
this.$message.success("提交成功")
window.location.href = '/patient'
}).catch(e => {
this.submitBnt = '保存'
})
}
}
}
</script>
<style>
.header-wrapper .title {
font-size: 16px;
margin-top: 0;
}
.sub-title {
margin-top: 0;
}
.bottom-wrapper{
padding: 0;
margin: 0;
}
.bottom-wrapper .button-wrapper{
margin-top: 0;
}
</style>
三、平台用户管理-用户列表
前面我们完成了用户登录、用户认证与就诊人,现在我们需要把这些信息在我们的平台管理系统中进行统一管理
1、用户列表接口
(1)添加UserInfoService接口
java"> //用户列表(条件查询带分页)
Page<UserInfo> getUserInfoPage(Long pageNum, Long limit, UserInfoQueryVo userInfoQueryVo);
(2)添加UserInfoServiceImpl实现
java"> @Override
public Page<UserInfo> getUserInfoPage(Long pageNum, Long limit, UserInfoQueryVo userInfoQueryVo) {
Page<UserInfo> page = new Page<>(pageNum,limit);
QueryWrapper<UserInfo> queryWrapper = new QueryWrapper<>();
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).or().eq("phone",userInfoQueryVo.getKeyword());
}
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);
}
Page<UserInfo> page1 = baseMapper.selectPage(page, wrapper);
page1.getRecords().stream().forEach(item->{
this.packageUserInfo(item);
});
return page1;
}
private void packageUserInfo(UserInfo item) {
//处理认证状态编码
item.getParam().put("authStatusString",AuthStatusEnum.getStatusNameByStatus(item.getAuthStatus()));
//处理用户状态 0 1 intValue()转换成int类型
String statusString = item.getStatus().intValue()==0 ?"锁定" : "正常";
item.getParam().put("statusString",statusString);
}
}
(3)添加AdminUserInfoController方法
java">@RestController
@RequestMapping("/admin/userinfo")
public class AdminUserInfoController {
@Autowired
private UserInfoService userInfoService;
//用户列表(条件查询带分页)
@GetMapping("{pageNum}/{limit}")
public R getUserInfoPage(@PathVariable Long pageNum,
@PathVariable Long limit,
UserInfoQueryVo userInfoQueryVo) {
Page<UserInfo> page = userInfoService.getUserInfoPage(pageNum,limit,userInfoQueryVo);
return R.ok().data("total",page.getTotal()).data("list",page.getRecords());
}
}
2、用户列表前端整合
(1)添加用户管理路由
在 src/router/index.js 文件添加路由
alt+shift+f格式化
java"> {
path: '/user',
component: Layout,
redirect: '/user/userInfo/list',
name: 'userInfo',
meta: { title: '用户管理', icon: 'table' },
alwaysShow: true,
children: [
{
path: 'userInfo/list',
name: '用户列表',
component: () => import('@/views/yygh/userInfo/list'),
meta: { title: '用户列表', icon: 'table' }
}
]
},
(2)封装api请求
创建/api/userinfo.js
java">import request from '@/utils/request'
const api_name = '/admin/userinfo'
export default {
getPageList(pageNum, limit, searchObj) {
return request({
url: `${api_name}/${pageNum}/${limit}`,
method: 'get',
params: searchObj
})
}
}
(3)添加列表页面
创建views/yygh/userInfo/list.vue
java"><template>
<div class="app-container">
<!--查询表单-->
<el-form :inline="true" class="demo-form-inline">
<el-form-item>
<el-input v-model="searchObj.keyword" placeholder="姓名/手机"/>
</el-form-item>
<el-form-item label="创建时间">
<el-date-picker
v-model="searchObj.createTimeBegin"
type="datetime"
placeholder="选择开始时间"
value-format="yyyy-MM-dd HH:mm:ss"
default-time="00:00:00"
/>
</el-form-item>
至
<el-form-item>
<el-date-picker
v-model="searchObj.createTimeEnd"
type="datetime"
placeholder="选择截止时间"
value-format="yyyy-MM-dd HH:mm:ss"
default-time="00:00:00"
/>
</el-form-item>
<el-button type="primary" icon="el-icon-search" @click="fetchData()">查询</el-button>
<el-button type="default" @click="resetData()">清空</el-button>
</el-form>
<!-- 列表 -->
<el-table
v-loading="listLoading"
:data="list"
stripe
style="width: 100%">
<el-table-column
label="序号"
width="70"
align="center">
<template slot-scope="scope">
{{ (page - 1) * limit + scope.$index + 1 }}
</template>
</el-table-column>
<el-table-column prop="phone" label="手机号"/>
<el-table-column prop="nickName" label="昵称"/>
<el-table-column prop="name" label="姓名"/>
<el-table-column label="状态" prop="param.statusString"/>
<el-table-column label="认证状态" prop="param.authStatusString"/>
<el-table-column prop="createTime" label="创建时间"/>
<el-table-column label="操作" width="200" align="center">
</el-table-column>
</el-table>
<!-- 分页组件 -->
<el-pagination
:current-page="page"
:total="total"
:page-size="limit"
:page-sizes="[5, 10, 20, 30, 40, 50, 100]"
style="padding: 30px 0; text-align: center;"
layout="sizes, prev, pager, next, jumper, ->, total, slot"
@current-change="fetchData"
@size-change="changeSize"
/>
</div>
</template>
<script>
import userInfoApi from '@/api/userinfo'
export default {
// 定义数据
data() {
return {
listLoading: true, // 数据是否正在加载
list: null, // banner列表
total: 0, // 数据库中的总记录数
page: 1, // 默认页码
limit: 10, // 每页记录数
searchObj: {} // 查询表单对象
}
},
// 当页面加载时获取数据
created() {
this.fetchData()
},
methods: {
// 调用api层获取数据库中的数据
fetchData(page = 1) {
console.log('翻页。。。' + page)
// 异步获取远程数据(ajax)
this.page = page
userInfoApi.getPageList(this.page, this.limit, this.searchObj).then(
response => {
this.list = response.data.list
this.total = response.data.total
// 数据加载并绑定成功
this.listLoading = false
}
)
},
// 当页码发生改变的时候
changeSize(size) {
console.log(size)
this.limit = size
this.fetchData(1)
},
// 重置查询表单
resetData() {
console.log('重置查询表单')
this.searchObj = {}
this.fetchData()
}
}
}
</script>
四、平台用户管理-用户锁定
1、用户锁定接口
(1)添加UserInfoService接口和实现
java">/**
* 用户锁定
* @param userId
* @param status 0:锁定 1:正常
*/
void lock(Long userId, Integer status);
//实现方法
@Override
public void lock(Long userId, Integer status) {
if(status.intValue() == 0 || status.intValue() == 1) {
UserInfo userInfo = this.getById(userId);
userInfo.setStatus(status);
//baseMapper.updateById(userInfo);
this.updateById(userInfo);
}
}
(2)添加UserController方法
java">@ApiOperation(value = "锁定")
@GetMapping("lock/{userId}/{status}")
public R lock(
@PathVariable("userId") Long userId,
@PathVariable("status") Integer status){
userInfoService.lock(userId, status);
return R.ok();
}
2、用户锁定前端整合
(1)封装api方法
在api/userinfo.js添加方法
java"> lock(id, status) {
return request({
url: `${api_name}/lock/${id}/${status}`,
method: 'get'
})
}
(2)在用户列表页面添加组件
java"> <el-table-column label="操作" width="200" align="center">
<template slot-scope="scope">
<el-button v-if="scope.row.status == 1" type="primary" size="mini" @click="lock(scope.row.id, 0)">锁定</el-button>
<el-button v-if="scope.row.status == 0" type="danger" size="mini" @click="lock(scope.row.id, 1)">取消锁定</el-button>
</template>
</el-table-column>
(3)在页面列表页面添加方法
java"> // 锁定
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: "操作成功!",
});
}
});
},
五、平台用户管理-用户详情
详情展示用户信息、用户就诊人信息
1、用户详情接口
(1)添加UserInfoService接口
java"> Map<String, Object> show(Long userId);
(2)添加UserInfoServiceImpl实现
PatientServiceImpl
java"> @Autowired
private PatientService patientService;
@Override
public Map<String, Object> show(Long userId) {
UserInfo userInfo = baseMapper.selectById(userId);
QueryWrapper<Patient> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("user_id",userId);
List<Patient> patients = patientService.selectList(queryWrapper);
Map<String,Object> map = new HashMap<>();
map.put("userInfo",userInfo);
map.put("patients",patients);
return map;
}
java"> @Override
public List<Patient> selectList(QueryWrapper<Patient> queryWrapper) {
List<Patient> patients = baseMapper.selectList(queryWrapper);
patients.stream().forEach(item->{
this.packagePatient(item);
});
return patients;
}
private void packagePatient(Patient item) {
item.getParam().put("certificatesTypeString",dictFeignClient.getNameByValue(Long.parseLong(item.getCertificatesType())));
String provinceString = dictFeignClient.getNameByValue(Long.parseLong(item.getProvinceCode()));
String cityString = dictFeignClient.getNameByValue(Long.parseLong(item.getCityCode()));
String districtString = dictFeignClient.getNameByValue(Long.parseLong(item.getDistrictCode()));
item.getParam().put("provinceString",provinceString);
item.getParam().put("cityString",cityString);
item.getParam().put("districtString",districtString);
item.getParam().put("fullAddress",provinceString+cityString+districtString);
}
}
(3)添加AdminUserInfoController方法
java"> //用户详情
@GetMapping("show/{userId}")
public R show(@PathVariable Long userId) {
Map<String,Object> map = userInfoService.show(userId);
return R.ok().data(map);
}
2、用户详情前端
(1)添加路由
java"> {
path: 'userInfo/show/:id',
name: '用户查看',
component: () => import('@/views/yygh/userInfo/show'),
meta: { title: '用户查看' },
hidden: true
}
(2)封装api方法
在api/userinfo.js添加
java"> //用户详情
show(id) {
return request({
url: `${api_name}/show/${id}`,
method: 'get'
})
}
(3)修改列表组件,添加查看按钮
java"> <router-link :to="'/user/userInfo/show/'+scope.row.id">
<el-button type="primary" size="mini">查看</el-button>
</router-link>
(4)添加详情页面
添加/views/yygh/userInfo/show.vue组件
java"><template>
<div class="app-container">
<h4>用户信息</h4>
<table class="table table-striped table-condenseda table-bordered" width="100%">
<tbody>
<tr>
<th width="15%">手机号</th>
<td width="35%"><b>{{ userInfo.phone }}</b></td>
<th width="15%">用户姓名</th>
<td width="35%">{{ userInfo.name }}</td>
</tr>
<tr>
<th>状态</th>
<td>{{ userInfo.status == 0 ? '锁定' : '正常' }}</td>
<th>注册时间</th>
<td>{{ userInfo.createTime }}</td>
</tr>
</tbody>
</table>
<h4>认证信息</h4>
<table class="table table-striped table-condenseda table-bordered" width="100%">
<tbody>
<tr>
<th width="15%">姓名</th>
<td width="35%"><b>{{ userInfo.name }}</b></td>
<th width="15%">证件类型</th>
<td width="35%">{{ userInfo.certificatesType }}</td>
</tr>
<tr>
<th>证件号</th>
<td>{{ userInfo.certificatesNo }}</td>
<th>证件图片</th>
<td><img :src="userInfo.certificatesUrl" width="80px"></td>
</tr>
</tbody>
</table>
<h4>就诊人信息</h4>
<el-table
v-loading="listLoading"
:data="patientList"
stripe
style="width: 100%">
<el-table-column
label="序号"
width="70"
align="center">
<template slot-scope="scope">
{{ scope.$index + 1 }}
</template>
</el-table-column>
<el-table-column prop="name" label="姓名"/>
<el-table-column prop="param.certificatesTypeString" label="证件类型"/>
<el-table-column prop="certificatesNo" label="证件编号"/>
<el-table-column label="性别">
<template slot-scope="scope">
{{ scope.row.sex == 1 ? '男' : '女' }}
</template>
</el-table-column>
<el-table-column prop="birthdate" label="出生年月"/>
<el-table-column prop="phone" label="手机"/>
<el-table-column label="是否结婚">
<template slot-scope="scope">
{{ scope.row.isMarry == 1 ? '时' : '否' }}
</template>
</el-table-column>
<el-table-column prop="param.fullAddress" label="地址"/>
<el-table-column prop="createTime" label="注册时间"/>
</el-table>
<br>
<el-row>
<el-button @click="back">返回</el-button>
</el-row>
</div>
</template>
<script>
import userInfoApi from '@/api/userinfo'
export default {
// 定义数据
data() {
return {
id: this.$route.params.id,
userInfo: {}, // 会员信息
patientList: [] // 就诊人列表
}
},
// 当页面加载时获取数据
created() {
this.fetchDataById()
},
methods: {
// 根据id查询会员记录
fetchDataById() {
userInfoApi.show(this.id).then(response => {
this.userInfo = response.data.userInfo
this.patientList = response.data.patients
})
},
back() {
window.history.back(-1) //从哪儿来,回哪去
}
}
}
</script>
六、用户认证列表
1、用户认证列表接口
用户认证列表接口与用户列表一致,只是默认加了一个认证状态搜索条件:authStatus
2、用户认证列表前端
(1)添加路由
java"> {
path: 'userInfo/authList',
name: '认证审批列表',
component: () =>import('@/views/yygh/userInfo/authList'),
meta: { title: '认证审批列表', icon: 'table' }
}
(2)添加用户认证列表页面
添加/views/yygh/userInfo/authList.vue组件
java"><template>
<div class="app-container">
<!--查询表单-->
<el-form :inline="true" class="demo-form-inline">
<el-form-item>
<el-input v-model="searchObj.keyword" placeholder="姓名/手机"/>
</el-form-item>
<el-form-item label="创建时间">
<el-date-picker
v-model="searchObj.createTimeBegin"
type="datetime"
placeholder="选择开始时间"
value-format="yyyy-MM-dd HH:mm:ss"
default-time="00:00:00"
/>
</el-form-item>
至
<el-form-item>
<el-date-picker
v-model="searchObj.createTimeEnd"
type="datetime"
placeholder="选择截止时间"
value-format="yyyy-MM-dd HH:mm:ss"
default-time="00:00:00"
/>
</el-form-item>
<el-button type="primary" icon="el-icon-search" @click="fetchData()">查询</el-button>
<el-button type="default" @click="resetData()">清空</el-button>
</el-form>
<!-- 列表 -->
<el-table
v-loading="listLoading"
:data="list"
stripe
style="width: 100%">
<el-table-column
label="序号"
width="70"
align="center">
<template slot-scope="scope">
{{ (page - 1) * limit + scope.$index + 1 }}
</template>
</el-table-column>
<el-table-column prop="name" label="姓名"/>
<el-table-column prop="certificatesType" label="证件类型"/>
<el-table-column prop="certificatesNo" label="证件号"/>
<el-table-column prop="createTime" label="创建时间"/>
<el-table-column label="操作" width="250" align="center">
<template slot-scope="scope">
<router-link :to="'/user/userInfo/show/'+scope.row.id">
<el-button type="primary" size="mini">查看</el-button>
</router-link>
</template>
</el-table-column>
</el-table>
<!-- 分页组件 -->
<el-pagination
:current-page="page"
:total="total"
:page-size="limit"
:page-sizes="[5, 10, 20, 30, 40, 50, 100]"
style="padding: 30px 0; text-align: center;"
layout="sizes, prev, pager, next, jumper, ->, total, slot"
@current-change="fetchData"
@size-change="changeSize"
/>
</div>
</template>
<script>
import userInfoApi from '@/api/userinfo'
export default {
// 定义数据
data() {
return {
listLoading: true, // 数据是否正在加载
list: null, // banner列表
total: 0, // 数据库中的总记录数
page: 1, // 默认页码
limit: 10, // 每页记录数
searchObj: {
authStatus: 1
} // 查询表单对象
}
},
// 当页面加载时获取数据
created() {
this.fetchData()
},
methods: {
// 调用api层获取数据库中的数据
fetchData(page = 1) {
console.log('翻页。。。' + page)
// 异步获取远程数据(ajax)
this.page = page
userInfoApi.getPageList(this.page, this.limit, this.searchObj).then(
response => {
this.list = response.data.list
this.total = response.data.total
// 数据加载并绑定成功
this.listLoading = false
}
)
},
// 当页码发生改变的时候
changeSize(size) {
console.log(size)
this.limit = size
this.fetchData(1)
},
// 重置查询表单
resetData() {
console.log('重置查询表单')
this.searchObj = {}
this.fetchData()
}
}
}
</script>
七、用户认证审批![在这里插入图片描述](https://img-blog.csdnimg.cn/375e9cdb8d9c4ee7aca9f7c3355c2333.png)
1、用户认证审批接口
(1)添加UserInfoService接口
java"> void approval(Long userId, Integer authStatus);
(2)添加UserInfoServiceImpl实现
java"> //认证审批 2通过 -1不通过
@Override
public void approval(Long userId, Integer authStatus) {
if(authStatus.intValue()==2 || authStatus.intValue()==-1) {
UserInfo userInfo = baseMapper.selectById(userId);
userInfo.setAuthStatus(authStatus);
baseMapper.updateById(userInfo);
}
}
(3)添加UserController方法
java"> //认证审批
@GetMapping("approval/{userId}/{authStatus}")
public R approval(@PathVariable Long userId,@PathVariable Integer authStatus) {
userInfoService.approval(userId,authStatus);
return R.ok();
}
2、用户认证审批前端
(1)封装api方法
java"> //认证审批
approval(id, authStatus) {
return request({
url: `${api_name}/approval/${id}/${authStatus}`,
method: 'get'
})
}
(2)用户认证列表页面添加审批按钮
java"> <el-button type="primary" size="mini" @click="approval(scope.row.id, 2)">通过</el-button>
<el-button type="danger" size="mini" @click="approval(scope.row.id, -1)">不通过</el-button>
(3)添加调用方法
java"> // 审批
approval(id, authStatus) {
// debugger
this.$confirm("确定该操作吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning",
}).then(resp => {
userInfoApi.approval(id, authStatus).then((resp) => {
this.$message.success("操作成功");
this.fetchData();
})
})
},