Browse Source

Merge pull request '增加性别、出生年份选择' (#13) from bug-rework-2025-0603 into master

Reviewed-on: kuaileadmin/acupuncture_register_system_uniapp#13
master
超级管理员 6 months ago
parent
commit
d9a28b0d94
  1. 119
      components/FormItem.vue
  2. 167
      components/SelectYear.vue
  3. 264
      components/SexPop.vue
  4. 9
      components/inputBox.vue
  5. 463
      pages/index/index.vue
  6. 197
      pages/modify_visitor/modify_visitor.vue
  7. 4
      pages/usercenter/usercenter.vue
  8. 13
      pages/visitors/visitors.vue

119
components/FormItem.vue

@ -0,0 +1,119 @@
<template>
<view class="form-item">
<!-- 左侧标签 + 必填提示 -->
<view class="label">
<!-- <text v-if="required" class="required">*</text> -->
<text>{{ label }}</text>
<image v-if="required" class="required" :src="cssUrl + 'required.svg'" />
</view>
<!-- 输入模式 -->
<input
v-if="type === 'input'"
class="input"
:placeholder="placeholder"
:value="value"
@input="handleInput"
:disabled="disabled"
/>
<!-- 点击选择模式如性别年份 -->
<view
v-else
class="picker"
@click="handleClick"
>
<text :class="{ 'placeholder': !value }">
{{ displayValue || placeholder }}
</text>
<image class="right_img" :src="cssUrl + 'input_ex.png'" />
<!-- <uni-icons type="arrowright" size="14" color="#999" /> -->
</view>
</view>
</template>
<script>
export default {
name: 'FormItem',
props: {
label: String, // ""
type: { // input picker
type: String,
default: 'input',
validator: (val) => ['input', 'picker'].includes(val),
},
value: [String, Number], //
placeholder: String, //
required: Boolean, //
disabled: Boolean, //
displayValue: String, // picker"/"
},
data(){
return{
cssUrl: this.cssUrl,
}
},
methods: {
handleInput(e) {
this.$emit('input', e.detail.value);
},
handleClick() {
if (!this.disabled) {
this.$emit('click'); //
}
},
},
};
</script>
<style scoped>
.form-item {
display: flex;
justify-content: space-between;
align-items: center;
padding: 36rpx 24rpx;
border-bottom: 1rpx solid #eee;
}
.right_img{
width: 26rpx;
height: 26rpx;
}
.label {
display: flex;
align-items: center;
font-family: PingFang SC;
font-size: 32rpx;
font-weight: 500;
line-height: 44rpx;
letter-spacing: 2rpx;
color: #222222;
}
.required {
margin-left: 8rpx;
color: #f56c6c;
font-size: 12px;
width: 16rpx;
height: 16rpx;
}
.input,
.picker {
flex: 1;
text-align: right;
padding-left: 20rpx;
color: #333;
}
.placeholder {
font-family: PingFang SC;
font-size: 32rpx;
font-weight: normal;
line-height: 44rpx;
text-align: right;
letter-spacing: 0.24rpx;
color: #999999;
}
</style>

167
components/SelectYear.vue

@ -0,0 +1,167 @@
<template>
<uni-popup ref="selectDate" :safe-area="false">
<view class="popup-container">
<view class="header">
<view class="title PfScMedium">出生年份</view>
<image class="close-icon" @tap="closePop" :src="cssUrl + 'close.svg'" />
</view>
<view class="date">请选择阳历出生年份</view>
<view class="yearPicker date-wraper">
<picker-view :value="value" @change="handleYearChange" class="picker-view">
<picker-view-column class="picker-column">
<view class="item" v-for="(item, index) in years" :key="index">{{ item }}</view>
</picker-view-column>
</picker-view>
</view>
<view class="confirm-button-wrapper btPadding">
<view class="confirm-button PfScMedium" @click="comfirmYear">
确认
</view>
</view>
</view>
</uni-popup>
</template>
<script>
export default {
data() {
const date = new Date()
const years = []
const year = date.getFullYear()
for (let i = 1990; i <= date.getFullYear(); i++) {
years.push(i)
}
return {
cssUrl:this.cssUrl,
years: years, //
currentYear: new Date().getFullYear(),
};
},
methods: {
handleYearChange(e) {
this.currentYear = this.years[e.detail.value];
},
comfirmYear(){
this.$emit('change', this.currentYear)
this.closePop()
},
show(){
this.$refs.selectDate.open('bottom')
},
closePop() {
this.$refs.selectDate.close()
},
},
};
</script>
<style lang="scss" scoped>
.yearPicker {
height: 470rpx;
background: #F7F7F7;
.picker-view {
height: 420rpx;
margin: 0 auto;
padding: 0 35rpx;
background: #F7F7F7;
}
.item {
line-height: 70rpx;
font-size: 28rpx;
font-weight: 600;
text-align: center;
}
}
.popup-container {
position: relative;
max-height: calc(100vh - 200rpx);
overflow-y: scroll;
background: #ffffff;
border-radius: 40rpx 40rpx 0px 0px;
padding: 42rpx 54rpx 16rpx;
.header {
position: relative;
text-align: center;
.title {
font-weight: 500;
font-size: 32rpx;
color: #000000;
line-height: 36rpx;
}
.close-icon {
width: 40rpx;
height: 40rpx;
position: absolute;
right: 0;
bottom: 0;
}
}
.content-container {
padding: 24rpx 0rpx 68rpx;
font-family: PingFang SC;
.content-item {
background: #FAFAFA;
&:first-child {
border-top: none;
padding: 25rpx 24rpx;
}
padding: 19rpx 24rpx;
border-top: 2rpx solid #F0F0F0;
span {}
.bold {
font-weight: 500;
font-size: 30rpx;
color: #000000;
}
.top {
margin-top: 12rpx;
margin-bottom: 12rpx;
}
.special {
color: #949699;
letter-spacing: 2rpx;
font-size: 30rpx;
.time {
margin: 0 6rpx;
}
}
}
}
.confirm-button {
font-weight: 500;
font-size: 32rpx;
color: #ffffff;
margin-top: 46rpx;
line-height: 92rpx;
text-align: center;
width: 100%;
height: 92rpx;
background: #39d067;
border-radius: 16rpx;
}
.date {
margin: 12rpx 36rpx 42rpx;
text-align: center;
color: #000000;
font-size: 26rpx;
font-family: PingFang SC;
}
}
</style>

264
components/SexPop.vue

@ -0,0 +1,264 @@
<template>
<uni-popup ref="sexWrap" :safe-area="false">
<view class="popup-container">
<view class="header">
<view class="title PfScMedium">性别</view>
<image class="close-icon" @tap="closePop" :src="cssUrl + 'close.svg'" />
</view>
<!-- <radio-group class="radio-group" @change="handleChange">
<label class="radio-item" v-for="item in options" :key="item.value">
<radio :value="item.value" :checked="value === item.value" />
<text>{{ item.label }}</text>
</label>
</radio-group> -->
<view>
<uni-data-checkbox mode="button" v-model="tempValue" :localdata="options"
@change="handleChange"></uni-data-checkbox>
</view>
<view class="confirm-button-wrapper btPadding">
<view class="confirm-button PfScMedium" @click="handleConfirm">
确认
</view>
</view>
</view>
</uni-popup>
</template>
<script>
export default {
name: 'MedicalInsuranceSelector',
options: { styleIsolation: "shared" },
props: {
value: { // 'yes' 'no'
type: String,
default: ''
}
},
data() {
return {
options: [
{ text: '男', value: 0 },
{ text: '女', value: 1 }
],
tempValue: this.value,//
cssUrl: this.cssUrl,
}
},
methods: {
show() {
this.$refs.sexWrap.open('bottom')
},
closePop() {
this.$refs.sexWrap.close()
},
handleChange(e) {
this.tempValue = e.detail.value
},
handleConfirm() {
// this.$emit('input', this.tempValue)
this.$emit('confirm', this.tempValue)
this.closePop()
}
}
}
</script>
<style lang="scss" scoped>
.medical-insurance-selector {
padding: 20rpx;
background-color: #fff;
border-radius: 12rpx;
}
.title {
margin-bottom: 30rpx;
}
.title text {
display: block;
font-size: 16px;
color: #333;
}
.subtitle {
font-size: 14px;
color: #999;
margin-top: 10rpx;
}
.radio-group {
display: flex;
flex-direction: column;
}
.radio-item {
display: flex;
align-items: center;
height: 90rpx;
border-bottom: 1rpx solid #f5f5f5;
}
.radio-item text {
margin-left: 20rpx;
font-size: 15px;
}
.popup-container {
position: relative;
max-height: calc(100vh - 200rpx);
overflow-y: scroll;
background: #ffffff;
border-radius: 40rpx 40rpx 0px 0px;
padding: 42rpx 54rpx 16rpx;
.header {
position: relative;
text-align: center;
.title {
font-weight: 500;
font-size: 32rpx;
color: #000000;
line-height: 36rpx;
}
.close-icon {
width: 40rpx;
height: 40rpx;
position: absolute;
right: 0;
bottom: 0;
}
}
.content-container {
padding: 24rpx 0rpx 68rpx;
font-family: PingFang SC;
.content-item {
background: #FAFAFA;
&:first-child {
border-top: none;
padding: 25rpx 24rpx;
}
padding: 19rpx 24rpx;
border-top: 2rpx solid #F0F0F0;
span {}
.bold {
font-weight: 500;
font-size: 30rpx;
color: #000000;
}
.top {
margin-top: 12rpx;
margin-bottom: 12rpx;
}
.special {
color: #949699;
letter-spacing: 2rpx;
font-size: 30rpx;
.time {
margin: 0 6rpx;
}
}
}
}
.confirm-button {
font-weight: 500;
font-size: 32rpx;
color: #ffffff;
margin-top: 46rpx;
line-height: 92rpx;
text-align: center;
width: 100%;
height: 92rpx;
background: #39d067;
border-radius: 16rpx;
}
.date {
margin: 12rpx 36rpx 42rpx;
text-align: center;
color: #000000;
font-size: 26rpx;
font-family: PingFang SC;
}
::v-deep .uni-data-checklist .checklist-group {
column-gap: 24rpx;
margin-bottom: 24rpx;
.checklist-box {
margin: 0;
width: calc(50% - 14rpx);
box-sizing: border-box;
display: flex;
justify-content: center;
align-items: center;
.checklist-content {
flex: none;
}
.checklist-content .checklist-text {
font-size: 30rpx;
font-weight: normal;
letter-spacing: 0.22rpx;
margin-left: 12rpx;
color: #666666;
}
.radio__inner {
width: 36rpx;
height: 36rpx;
border: 2rpx solid #BCBCBC;
border-radius: 36rpx;
}
&.is--button {
margin-right: 0rpx;
padding: 20rpx 42rpx 20rpx 24rpx;
box-sizing: border-box;
border: none;
min-height: 82rpx;
border-radius: 8rpx;
transition: border-color 0.2s;
background: #F8F8F8;
&.is-checked {
background: #F5FFF4;
.radio__inner {
border-color: #00C160;
}
.radio__inner-icon {
background: #00C160;
}
.checklist-text {
color: #333333;
}
}
}
}
}
}
</style>

9
components/inputBox.vue

@ -5,6 +5,7 @@
<view class="top-wrapper flex">
<view class="left PfScMedium">
<view>{{label}}</view>
<image v-if="required" class="required" :src="cssUrl + 'required.svg'" />
</view>
<view class="right">
<textarea class="textarea" v-if="autoHeight" :auto-height="true" :value="value" :placeholder="holder" @blur="handleBlur" @input="handleInput"></textarea>
@ -157,6 +158,7 @@ export default {
}
.left{
display: flex;
align-items: center;
min-width: 158rpx;
max-width: 238rpx;
text{
@ -209,6 +211,13 @@ export default {
}
}
}
.required {
margin-left: 8rpx;
color: #f56c6c;
font-size: 12px;
width: 16rpx;
height: 16rpx;
}
.errmsg{
margin: 0 auto;
width: 100%;

463
pages/index/index.vue

@ -3,16 +3,17 @@
<view class="header-wrapper flex">
<view class="left">
<view class="flex top PfScMedium">
<view class="ft50 over2">{{doctorInfo.doctor_info.doctor_name}}</view>
<view class="ft50 over2">{{ doctorInfo.doctor_info.doctor_name }}</view>
<view v-if="doctor_dept">
<view class="over2">{{doctor_dept}}</view>
<view class="over2">{{ doctor_dept }}</view>
</view>
</view>
<view class="bt over2" v-if="doctorInfo.doctor_info.doctor_desc">
{{doctorInfo.doctor_info.doctor_desc}}
{{ doctorInfo.doctor_info.doctor_desc }}
</view>
</view>
<img class="right" :src="doctorInfo.doctor_info.avator" alt="" @click="enlargePicture(doctorInfo.doctor_info.avator)" v-if="doctorInfo.doctor_info.avator">
<img class="right" :src="doctorInfo.doctor_info.avator" alt=""
@click="enlargePicture(doctorInfo.doctor_info.avator)" v-if="doctorInfo.doctor_info.avator">
</view>
<view class="block desc-wrapper" v-if="doctorInfo.doctor_info.doctor_detail">
@ -24,7 +25,7 @@
</view> -->
<view class="con">
{{doctorInfo.doctor_info.doctor_detail}}
{{ doctorInfo.doctor_info.doctor_detail }}
</view>
</view>
@ -36,21 +37,21 @@
<img :src="cssUrl+'right_bg.png'" alt="">
</view> -->
<view class="item" v-for="(item,key) in hospitals">
<view class="item" v-for="(item, key) in hospitals">
<view class="top flex">
<view class="left">
<view class="title flex">
<text class="over2 PfScMedium hospital_name">{{item.hospital_name}}</text>
<text class="over2 PfScMedium hospital_name">{{ item.hospital_name }}</text>
<view class="fixed_hospital" v-if="item.is_fixed == 1">医保定点</view>
</view>
<view class="date over2 over4" v-if="item.address">
{{item.address}}
{{ item.address }}
</view>
</view>
<view class="right">
<view class="flex right-wrapper" style="justify-content:center;" v-if="item.hospital_pos">
<view class="" @click="toLocation(item)">
<img :src="cssUrl+'index_nav.svg'" alt="">
<img :src="cssUrl + 'index_nav.svg'" alt="">
<view class="map-wrap">导航</view>
</view>
@ -64,13 +65,13 @@
<uni-collapse ref="collapse" v-model="collapseValue[key]" class="notice-collapse" v-if="item.notice">
<uni-collapse-item title="预约须知">
<view class=" content" >
<view class=" content">
<view class="text" v-html="item.notice"></view>
</view>
</uni-collapse-item>
</uni-collapse>
<view class="bot primary btn btn2" hover-class="hover" @click="toVisitors(item)" v-if="item.type==0">
<view class="bot primary btn btn2" hover-class="hover" @click="toVisitors(item)" v-if="item.type == 0">
开始预约
</view>
</view>
@ -82,50 +83,75 @@
<view class="title">
最近预约
</view>
<img :src="cssUrl+'right_bg.png'" alt="">
<img :src="cssUrl + 'right_bg.png'" alt="">
</view>
<view class="opt flex" @click="toPrebookList">
查看全部<img :src="cssUrl+'index_comback2.svg'" alt="">
查看全部<img :src="cssUrl + 'index_comback2.svg'" alt="">
</view>
</view>
</view>
<pre-book-list class="preg-books" :dataList="recentAppoint" :topnopadding="true" v-if="this.doctorInfo && !this.doctorInfo.is_all_card"></pre-book-list>
<pre-book-list class="preg-books" :dataList="recentAppoint" :topnopadding="true"
v-if="this.doctorInfo && !this.doctorInfo.is_all_card"></pre-book-list>
<tabbar current="1" leftButtonText="主页" v-if="!doctorInfo.is_all_card"></tabbar>
<!-- #ifdef MP-WEIXIN -->
<doctorImport v-if="user_type == '1' || user_type == '2'"></doctorImport>
<!-- #endif -->
<!-- #ifdef MP-WEIXIN -->
<button id="getPhoneBtn" open-type="getPhoneNumber" bindgetphonenumber="onGetPhoneNumber"
style="display: none;"></button>
<!-- #endif -->
<uni-popup ref="nameWrap" :safe-area="false">
<view class="popup-container">
<view class="header">
<view class="title PfScMedium">需要填写真实姓名来确保您账号的唯一性</view>
</view>
<view class="label">真实姓名</view>
<input type="text" class="realName" v-model="realName" placeholder-class="placeholder-style" placeholder="请填写">
<view class="confirm-button-wrapper btPadding">
<view class="confirm-button PfScMedium" @click="handleConfirm">
完成
</view>
</view>
</view>
</uni-popup>
</view>
</template>
<script>
import tabbar from '@/components/tabbar.vue'
import preBookList from '@/components/preBookList.vue'
// #ifdef MP-WEIXIN
import doctorImport from '@/components/doctorImport.vue'
// #endif
import tabbar from '@/components/tabbar.vue'
import preBookList from '@/components/preBookList.vue'
// #ifdef MP-WEIXIN
import doctorImport from '@/components/doctorImport.vue'
// #endif
export default {
export default {
data() {
return {
collapseValue:[],
cssUrl:this.cssUrl,
code:'',
pageShow:false,
doctor_id:'',
doctorInfo:false,
doctor_dept:false,
hospitals:false,
recentAppoint:[],
loginToken:false,
state:'',
workdate:[],
user_type:-1,
realName:'',
collapseValue: [],
cssUrl: this.cssUrl,
code: '',
pageShow: false,
doctor_id: '',
doctorInfo: false,
doctor_dept: false,
hospitals: false,
recentAppoint: [],
loginToken: false,
state: '',
workdate: [],
user_type: -1,
show_info:false,
showNameDialog: false,
userName: "",
hasRejectedPhone: false, //
}
},
components:{
components: {
tabbar,
preBookList,
// #ifdef MP-WEIXIN
@ -133,29 +159,95 @@
// #endif
},
onLoad(option) {
if(option.code && option.state) {
if (option.code && option.state) {
this.code = option.code
this.state = option.state
}
},
onReady() { // 使 onReady onLoad
// #ifdef MP-WEIXIN
// this.triggerGetPhone();
// #endif
},
async onShow() {
this.doctor_id = getApp().globalData.doctorId
if(!this.doctor_id) return
if (!this.doctor_id) return
var title = ''
if(this.code) title = '登录'
if (this.code) title = '登录'
uni.setNavigationBarTitle({
title:title
title: title
})
var token = this.$token.getToken()
if(this.code && this.state && !token) {
if (this.code && this.state && !token) {
this.login()
return
}
await this.getDoctorInfo()
},
methods: {
toLocation(hospital){
handleConfirm(){
if(!this.realName.trim()){
uni.showModal({
title:'提示',
content: '姓名不可为空',
})
return
}
this.$http.req('/api/user/set_realname', { realname:this.realName}, 'POST').then(data => {
if (data == -1) return
this.$refs.nameWrap.close()
});
},
//
triggerGetPhone() {
//
setTimeout(() => {
const query = uni.createSelectorQuery().in(this);
query.select('#getPhoneBtn')
.node()
.exec((res) => {
const node = res[0]?.node;
if (node) {
node.dispatchEvent(new CustomEvent('tap'));
} else {
console.error('节点未找到,请检查:', res);
//
wx.showModal({
title: '提示',
content: '请手动点击授权按钮',
});
}
});
}, 800);
},
//
onGetPhoneNumber(e) {
if (e.detail.errMsg === "getPhoneNumber:ok") {
const { code } = e.detail;
// code
wx.login({
success: (loginRes) => {
wx.request({
url: '/api/user/bind_phone',
data: { wxCode: loginRes.code, phoneCode: code },
success: (res) => {
const phone = res.data.phone;
this.setData({ phone });
//
this.setData({ showNameDialog: true });
},
});
},
});
} else {
//
this.setData({ hasRejectedPhone: true });
wx.showToast({ title: "需要手机号才能继续", icon: "none" });
}
},
toLocation(hospital) {
// #ifdef MP-WEIXIN
var lngLat = hospital.hospital_pos.toString().split(',')
@ -187,10 +279,10 @@
var baiduLngLat = that.qqMapTransBMap(lng, lat)
var mapList = [
'http://apis.map.qq.com/uri/v1/marker?marker=coord:'+ lat+','+lng+';addr:'+hospital.hospital_name,
'http://apis.map.qq.com/uri/v1/marker?marker=coord:' + lat + ',' + lng + ';addr:' + hospital.hospital_name,
// 'http://apis.map.qq.com/uri/v1/marker?marker=coord:'+ lat+','+lng+';title:'+hospital.hospital_name+ 'addr:'+hospital.address, // new title
'http://api.map.baidu.com/marker?location='+baiduLngLat.lat+','+baiduLngLat.lng+'&title='+hospital.hospital_name+'&content=即将前往目的地&output=html&src=webapp.baidu.openAPIdemo',
'https://m.amap.com/share/index/lnglat='+hospital.hospital_pos+'&name='+hospital.hospital_name+'&src=uriapi&innersrc=uriapi',
'http://api.map.baidu.com/marker?location=' + baiduLngLat.lat + ',' + baiduLngLat.lng + '&title=' + hospital.hospital_name + '&content=即将前往目的地&output=html&src=webapp.baidu.openAPIdemo',
'https://m.amap.com/share/index/lnglat=' + hospital.hospital_pos + '&name=' + hospital.hospital_name + '&src=uriapi&innersrc=uriapi',
]
location.href(mapList[res.tapIndex])
},
@ -199,7 +291,7 @@
});
// #endif
},
copyAddress(address){
copyAddress(address) {
uni.setClipboardData({
data: address,
success: () => {
@ -211,47 +303,53 @@
this.$setuinfo.setUinfo(JSON.stringify(info))
},
login() {
this.$http.req('api/common/get_user_info', {code:this.code,state:this.state}, 'POST').then(data=>{
if(data == -1) return
this.$http.req('api/common/get_user_info', { code: this.code, state: this.state }, 'POST').then(data => {
if (data == -1) return
this.$settoken.setToken(data.jwttoken)
this.setLoginUserInfo(data)
var stat_info = this.state.split('-');
if(stat_info.length > 2) {
if (stat_info.length > 2) {
uni.removeStorageSync('checkin_depart_id');
this.$nav.navToPath('/pages/visitors/visitors?type=3&depart_id='+stat_info[2])
this.$nav.navToPath('/pages/visitors/visitors?type=3&depart_id=' + stat_info[2])
return;
}
this.getDoctorInfo()
});
},
async getDoctorInfo() {
await this.$http.req('api/user/index_info', {}, 'GET').then(data=>{
if(data == -1) return
await this.$http.req('api/user/index_info', {}, 'GET').then(data => {
if (data == -1) return
// var data = JSON.parse(uni.getStorageSync('doctor_info'));
var checkin_depart_id = uni.getStorageSync('checkin_depart_id');
if(checkin_depart_id){
if (checkin_depart_id) {
uni.removeStorageSync('checkin_depart_id');
this.$nav.navToPath('/pages/visitors/visitors?type=3&depart_id='+checkin_depart_id)
this.$nav.navToPath('/pages/visitors/visitors?type=3&depart_id=' + checkin_depart_id)
return;
}
this.pageShow = true;
this.$nextTick(() => {
console.log(this.$refs, 'this.$refs.nameWrap');
this.$refs.nameWrap.open('bottom')
})
let visitFlag = true;
this.doctorInfo = data;
this.user_type = this.doctorInfo.user_type;
var title = this.doctorInfo.doctor_info.doctor_name+'主页'
var title = this.doctorInfo.doctor_info.doctor_name + '主页'
uni.setNavigationBarTitle({
title:title
title: title
})
if(this.doctorInfo.doctor_info && this.doctorInfo.doctor_info.depart_name && this.doctorInfo.doctor_info.depart_name.length>0){
if (this.doctorInfo.doctor_info && this.doctorInfo.doctor_info.depart_name && this.doctorInfo.doctor_info.depart_name.length > 0) {
this.doctor_dept = this.doctorInfo.doctor_info.depart_name;
}
if(this.doctorInfo.hospital_departs && this.doctorInfo.hospital_departs.length>0){
if (this.doctorInfo.hospital_departs && this.doctorInfo.hospital_departs.length > 0) {
this.hospitals = this.doctorInfo.hospital_departs;
this.doctor_dept = this.doctorInfo.hospital_departs[0]['depart_name'];
this.doctorInfo.doctor_info.depart_name = this.doctor_dept;
@ -259,20 +357,20 @@
for (var index = 0; index < this.hospitals.length; index++) {
this.collapseValue[index] = []
}
}else{
} else {
visitFlag = false;
}
if(this.doctorInfo.visit_list && this.doctorInfo.visit_list.length>0){
if (this.doctorInfo.visit_list && this.doctorInfo.visit_list.length > 0) {
this.recentAppoint = this.doctorInfo.visit_list;
}
if(this.doctorInfo.workdate && Object.keys(this.doctorInfo.workdate).length > 0){
if (this.doctorInfo.workdate && Object.keys(this.doctorInfo.workdate).length > 0) {
this.workdate = this.doctorInfo.workdate;
}else{
} else {
visitFlag = false;
}
this.hospital_departs = this.doctorInfo.hospital_departs.map((item,index)=>{
if(this.doctorInfo.workdate_desc) item.workdate_desc = this.doctorInfo.workdate_desc[item.depart_id]
this.hospital_departs = this.doctorInfo.hospital_departs.map((item, index) => {
if (this.doctorInfo.workdate_desc) item.workdate_desc = this.doctorInfo.workdate_desc[item.depart_id]
return item
})
});
@ -285,17 +383,17 @@
urls: list
});
},
toVisitors(hospital){
toVisitors(hospital) {
uni.setStorageSync('depart_id', hospital.depart_id)
uni.setStorageSync('depart', JSON.stringify(hospital))
uni.setStorageSync('doctor_info', JSON.stringify(this.doctorInfo))
this.$nav.navToPath("/pages/visitors/visitors?type=1&is_preview=1")
},
toPrebookList(){
toPrebookList() {
this.$nav.navToPath("/pages/prebook_list/prebook_list")
},
toPrebookDetail(){
toPrebookDetail() {
this.$nav.navToPath("/pages/visit_detail/visit_detail")
},
qqMapTransBMap(lng, lat) {
@ -315,32 +413,36 @@
onShareAppMessage() {
return {
title: this.doctorInfo.doctor_info.doctor_name + '的预约挂号',
path: '/pages/index/index?did='+this.doctor_id
}
path: '/pages/index/index?did=' + this.doctor_id
}
}
}
</script>
<style lang="scss" scoped>
.index-page{
.header-wrapper{
.index-page {
.header-wrapper {
min-height: 208rpx;
padding: 27rpx 40rpx 24rpx;
box-sizing: border-box;
.left{
.left {
width: 510rpx;
.top{
.top {
overflow: hidden;
margin-top: 31rpx;
& view:first-of-type{
& view:first-of-type {
color: #333;
letter-spacing: 1.32rpx;
margin-right: 27rpx;
max-width: 250rpx;
font-weight: 500;
}
& view:last-of-type{
view{
& view:last-of-type {
view {
width: auto;
padding: 0 15rpx;
margin-top: 5rpx;
@ -349,13 +451,14 @@
align-items: center;
height: 42rpx;
font-size: 28rpx;
background: linear-gradient( 288deg, #FFEED2 0%, #FED9A6 100%);
background: linear-gradient(288deg, #FFEED2 0%, #FED9A6 100%);
border-radius: 8rpx;
color: #7D501F;
}
}
}
.bt{
.bt {
width: 480rpx;
line-height: 40rpx;
font-size: 28rpx;
@ -363,7 +466,8 @@
margin-top: 21rpx;
}
}
.right{
.right {
flex-grow: 1;
display: block;
border-radius: 100%;
@ -371,7 +475,8 @@
width: 160rpx;
}
}
.block{
.block {
background: #FFFFFF;
border-radius: 8rpx;
padding: 36rpx 24rpx;
@ -380,16 +485,19 @@
width: 714rpx;
margin-bottom: 20rpx;
}
.desc-wrapper{
box-shadow: 0rpx 2rpx 24rpx 0rpx rgba(0,0,0,0.03);
.desc-wrapper {
box-shadow: 0rpx 2rpx 24rpx 0rpx rgba(0, 0, 0, 0.03);
color: #949699;
font-size: 30rpx;
line-height: 50rpx;
.con{
.con {
overflow-y: auto;
max-height: 200rpx;
color: #666666;
}
.con::-webkit-scrollbar {
display: none;
width: 0;
@ -397,8 +505,9 @@
color: transparent;
}
}
.title-wrapper{
.title{
.title-wrapper {
.title {
width: 117rpx;
height: 42rpx;
padding-left: 13rpx;
@ -408,47 +517,55 @@
line-height: 42rpx;
text-align: center;
border-radius: 8rpx 0rpx 0rpx 8rpx;
background: linear-gradient( 98deg, #53C184 0%, #5CD378 100%);
background: linear-gradient(98deg, #53C184 0%, #5CD378 100%);
}
&.booklist .title{
&.booklist .title {
margin-bottom: 0rpx;
}
img{
img {
width: 48rpx;
height: 42rpx;
}
}
.hospital-wrapper{
.item{
.hospital-wrapper {
.item {
min-height: 207rpx;
width: 100%;
margin-bottom: 36rpx;
border-bottom: 2rpx solid #F1F1F1;
padding-bottom: 36rpx;
&:last-child{
&:last-child {
margin-bottom: 0rpx;
padding-bottom: 0rpx;
border-bottom:none !important;
border-bottom: none !important;
}
.top{
.left{
.top {
.left {
flex-grow: 1;
.title{
.title {
align-items: center;
flex-wrap: wrap;
column-gap: 20rpx;
row-gap: 12rpx;
.hospital_name{
.hospital_name {
color: #333;
font-size: 32rpx;
}
img{
img {
width: 20rpx;
height: 32rpx;
}
.fixed_hospital{
.fixed_hospital {
border-radius: 6rpx;
background: #F7FCFF;
border: 2rpx solid rgba(9, 131, 208, 0.6);
@ -464,21 +581,24 @@
}
}
.date{
.date {
line-height: 40rpx;
font-size: 28rpx;
color: #949699;
margin-top: 22rpx;
}
}
.right{
.right {
width: 172rpx;
flex-shrink: 0;
height: 100%;
color: #666666;
display: flex;
justify-content: flex-end;
.map-wrap{
.map-wrap {
font-size: 26rpx;
font-weight: normal;
line-height: normal;
@ -486,11 +606,13 @@
color: #666666;
margin-top: 4rpx;
}
img{
img {
width: 52rpx;
height: 52rpx;
}
.copy_btn{
.copy_btn {
display: block;
line-height: normal;
text-align: center;
@ -500,7 +622,8 @@
}
}
}
.center{
.center {
justify-content: flex-start;
align-items: center;
width: 100%;
@ -517,10 +640,12 @@
margin-bottom: 24rpx;
word-break: break-all;
}
.notice-collapse {
margin-top: 24rpx;
::v-deep {
.uni-collapse-item__title-box{
.uni-collapse-item__title-box {
padding: 0;
display: flex;
justify-content: flex-start;
@ -531,37 +656,46 @@
font-weight: normal;
margin-top: 0rpx;
}
.uni-collapse-item__title{
.uni-collapse-item__title {
border: none !important;
}
.uni-collapse-item__title-arrow{
.uni-collapse-item__title-arrow {
width: 32rpx;
height: 32rpx;
margin-left: 12rpx;
}
.uni-icons{
.uni-icons {
width: 32rpx;
height: 32rpx;
}
.uni-collapse-item__title-text{
.uni-collapse-item__title-text {
font-size: 28rpx;
letter-spacing: 0.22rpx;
color: #949699;
}
.uni-collapse-item__title-wrap{
.uni-collapse-item__title-wrap {
width: auto;
flex: unset;
}
.content{
color:red !important;
.content {
color: red !important;
}
.uni-collapse-item__wrap-content{
.uni-collapse-item__wrap-content {
border: none !important;
}
.uni-collapse-item__title.is-open{
.uni-collapse-item__title.is-open {
margin-bottom: 24rpx;
}
.content{
.content {
width: 100%;
height: auto;
padding: 24rpx;
@ -569,7 +703,8 @@
background: #F8F6F9;
border-radius: 12rpx;
}
.content .text{
.content .text {
font-size: 28rpx;
font-weight: normal;
line-height: 40rpx;
@ -580,22 +715,26 @@
}
}
.bot{
.bot {
margin-top: 16rpx;
font-size: 32rpx;
}
}
}
.visit-wrapper{
.visit-wrapper {
margin-bottom: 0;
.header{
.header {
justify-content: space-between;
.opt{
.opt {
align-items: center;
overflow: hidden;
font-size: 26rpx;
color: #949699;
img{
img {
width: 20rpx;
height: 32rpx;
margin-left: 8rpx;
@ -603,11 +742,95 @@
}
}
}
.preg-books{
.preg-books {
width: 714rpx;
margin: 0 auto;
}
}
.popup-container {
position: relative;
max-height: calc(100vh - 200rpx);
overflow-y: scroll;
background: #ffffff;
border-radius: 40rpx 40rpx 0px 0px;
padding: 42rpx 48rpx 16rpx;
.header {
position: relative;
text-align: left;
.title {
font-size: 30rpx;
font-weight: 500;
line-height: 42rpx;
letter-spacing: normal;
color: #000000;
}
}
.label {
margin-top: 54rpx;
font-family: PingFang SC;
font-size: 34rpx;
font-weight: 500;
line-height: 47.6rpx;
letter-spacing: normal;
color: #000000;
}
.realName {
color: #000000;
font-size: 34rpx;
line-height: 40rpx;
font-family: PingFang SC;
font-weight: normal;
letter-spacing: normal;
padding: 22rpx 0;
border-bottom: 2rpx solid rgba(0, 0, 0, 0.1);
margin-bottom: 160rpx;
margin-top: 22rpx;
&::placeholder {
opacity: 0.3;
}
}
.placeholder-style {
opacity: 0.3;
}
.confirm-button-wrapper {
display: flex;
align-items: center;
justify-content: center;
.confirm-button {
justify-content: center;
display: flex;
align-items: center;
font-weight: 600;
font-size: 34rpx;
color: #ffffff;
text-align: center;
width: 368rpx;
height: 80rpx;
border-radius: 8rpx;
background: #07C160;
}
}
.date {
margin: 12rpx 36rpx 42rpx;
text-align: center;
color: #000000;
font-size: 26rpx;
font-family: PingFang SC;
}
}
</style>

197
pages/modify_visitor/modify_visitor.vue

@ -1,16 +1,26 @@
<template>
<view class="visitor-form-page">
<view class="block">
<input-box class="inputcom-wrapper" v-model="name" holder="填写姓名" label="患者姓名" @blurEvent="nameBlurEvent"></input-box>
<input-box class="inputcom-wrapper" v-model="idcard" holder="填写身份证号码" label="身份证号" @blurEvent="idCardBlurEvent" rule="idcard"></input-box>
<input-box class="inputcom-wrapper" v-model="phone" holder="填写患者手机号" label="患者手机号" @blurEvent="phoneBlurEvent" rule="phone"></input-box>
<input-box class="inputcom-wrapper" v-model="name" holder="必填项" label="姓名"
@blurEvent="nameBlurEvent" required></input-box>
<!-- <input-box class="inputcom-wrapper" v-model="idcard" holder="填写身份证号码" label="身份证号" @blurEvent="idCardBlurEvent" rule="idcard"></input-box> -->
<!-- <input-box class="inputcom-wrapper" v-model="phone" holder="方便预约后联系,非必填" label="手机号"
@blurEvent="phoneBlurEvent" rule="phone"></input-box> -->
<!-- <FormItem label="姓名" type="input" v-model="name" placeholder="必填项" required /> -->
<FormItem label="性别" type="picker" :display-value="genders[sex] || ''" placeholder="必选" required
@click="showGenderPicker" />
<FormItem label="出生年份" type="picker" :display-value="year ? `${year}` : ''" placeholder="必选"
required @click="showYearPicker" />
<FormItem label="手机号" type="input" v-model="phone" rule="phone" placeholder="方便预约后联系,非必填" />
</view>
<view class="submit-wrapper btPadding" v-if="!vid">
<view :class="'btn btn3 PfScMedium submit'+(canSubmit?' primary':' noclick')" :hover-class="(canSubmit?'hover':'')" @click="submit" v-if="!vid">
<view :class="'btn btn3 PfScMedium submit' + (canSubmit ? ' primary' : ' noclick')"
:hover-class="(canSubmit ? 'hover' : '')" @click="submit" v-if="!vid">
确认新增
</view>
<view :class="'btn btn3 PfScMedium submit'+(canSubmit?' primary':' noclick')" :hover-class="(canSubmit?'hover':'')" @click="submit" v-else>
<view :class="'btn btn3 PfScMedium submit' + (canSubmit ? ' primary' : ' noclick')"
:hover-class="(canSubmit ? 'hover' : '')" @click="submit" v-else>
确认修改
</view>
</view>
@ -20,75 +30,114 @@
<view class="btn primary btn1" hover-class="hover" @click="submit">确认</view>
</view>
</view>
<SelectYear ref="yearPicker" @change="handleYearChange" />
<SexPop ref="genderPopup" v-model="sex" @confirm="handleConfirm" />
</view>
</template>
<script>
import InputBox from '@/components/inputBox.vue';
import InputBox from '@/components/inputBox.vue';
import FormItem from '@/components/FormItem.vue';
import SelectYear from '@/components/SelectYear.vue';
import SexPop from '@/components/SexPop.vue';
export default {
export default {
data() {
return {
canSubmit:false,
name:'',
nameRule:false,
idcard:'',
idcardExtRule:false,
phone:'',
phoneRule:false,
type:1,
adding:false,
vid:false,
visitor_info:{}
canSubmit: false,
cssUrl: this.cssUrl,
year: '',
name: '',
// form: {
// year: '',
// name: '',
// sex: '',
// phone: ''
// },
sex:'',
nameRule: false,
idcard: '',
idcardExtRule: false,
phone: '',
phoneRule: false,
type: 1,
adding: false,
vid: false,
visitor_info: {},
genders: {
0:'男',
1:'女'
},
}
},
components:{
InputBox
components: {
InputBox,
FormItem,
SexPop,
SelectYear
},
onLoad(option) {
if(option.type) this.type = option.type
if(option.vid) {
if (option.type) this.type = option.type
if (option.vid) {
this.vid = option.vid
uni.setNavigationBarTitle({
title: '修改预约人'
});
}else{
} else {
uni.setNavigationBarTitle({
title: '新增预约人'
});
}
},
onShow() {
if(this.vid) this.getVisitorInfo()
if (this.vid) this.getVisitorInfo()
},
methods: {
handleConfirm(sex){
this.sex = sex;
this.checkSubmit()
},
handleYearChange(year) {
this.year = year;
this.checkSubmit()
},
showYearPicker() {
this.$refs.yearPicker.show()
},
showGenderPicker() {
this.$refs.genderPopup.show();
},
add() {
if(this.adding) return
if (this.adding) return
this.adding = true
var param = new Object()
param.name = this.name
param.idcard = this.idcard
param.sex = this.sex
param.birth_year = this.year
param.phone = this.phone
// param.idcard = this.idcard
var that = this
var addtimer = setTimeout(function() {
var addtimer = setTimeout(function () {
that.adding = false
}, 5000);
var req = 'api/user/add_visitor'
var method = 'POST'
if(this.vid){
if (this.vid) {
param.id = this.vid
param.get_idcard = 1
req = 'api/user/update_visitor'
}
this.$http.req(req, param, method).then(data=>{
if(data == -1) return
this.$http.req(req, param, method).then(data => {
if (data == -1) return
clearTimeout(addtimer)
this.adding = false
if(this.vid){
uni.removeStorageSync('visitor_info_'+ this.vid)
if (this.vid) {
uni.removeStorageSync('visitor_info_' + this.vid)
}
uni.navigateBack()
@ -98,69 +147,76 @@
var param = new Object()
param.vid = this.vid
this.$http.req('api/user/get_modify_visitor', param, 'POST').then(data=>{
if(data == -1) return
this.$http.req('api/user/get_modify_visitor', param, 'POST').then(data => {
if (data == -1) return
this.name = data.name
this.idcard = data.idcard
this.year = data.birth_year
this.sex = data.sex
// this.idcard = data.idcard
this.phone = data.phone
this.nameRule = true
this.idcardExtRule = true
this.phoneRule = true
// this.idcardExtRule = true
this.phoneRule = false
this.checkSubmit()
});
},
nameBlurEvent(value, res){
nameBlurEvent(value, res) {
this.name = value
this.nameRule = res
this.checkSubmit()
},
idCardBlurEvent(value, res){
this.idcard = value
this.idcardExtRule = res
this.checkSubmit()
},
phoneBlurEvent(value, res){
this.phone = value
this.phoneRule = res
this.checkSubmit()
},
// idCardBlurEvent(value, res) {
// this.idcard = value
// this.idcardExtRule = res
// this.checkSubmit()
// },
// phoneBlurEvent(value, res) {
// this.phone = value
// this.phoneRule = res
// this.checkSubmit()
// },
checkSubmit() {
this.canSubmit = false
if(!this.nameRule || !this.idcardExtRule || !this.phoneRule) return
if (!this.name || !this.sex || !this.year) return
this.canSubmit = true
},
reback(){
if(this.vid){
uni.removeStorageSync('visitor_info_'+ this.vid)
reback() {
if (this.vid) {
uni.removeStorageSync('visitor_info_' + this.vid)
}
this.$func.toPage('/pages/visitors_new/visitors_new')
},
submit(){
submit() {
this.checkSubmit()
if(!this.canSubmit) return
if (!this.canSubmit) return
this.add()
}
}
}
}
</script>
<style lang="scss" scoped>
.visitor-form-page{
background: #F8F8F8;
.visitor-form-page {
// background: #F8F8F8;
background: #FFFFFF;
height: 100vh;
overflow-y: scroll;
.block{
background: #FFFFFF;
box-shadow: 0rpx 2rpx 24rpx 0rpx rgba(0,0,0,0.03);
.block {
// background: #FFFFFF;
box-shadow: 0rpx 2rpx 24rpx 0rpx rgba(0, 0, 0, 0.03);
border-radius: 8rpx;
width: 714rpx;
margin: 20rpx auto 0rpx;
overflow: hidden;
&:nth-child(3){
&:nth-child(3) {
border: none !important;
}
.title{
.title {
font-size: 32rpx;
color: #000000;
width: 666rpx;
@ -170,7 +226,8 @@
margin: 36rpx 0 36rpx 24rpx;
}
}
.submit-wrapper{
.submit-wrapper {
overflow: hidden;
position: fixed;
top: 88vh;
@ -178,20 +235,23 @@
left: 50%;
transform: translateX(-50%);
}
.submit{
.submit {
margin: 0 auto;
}
.fixedBot{
.fixedBot {
position: fixed;
bottom: 0;
left: 0;
width: 100%;
height: 124rpx;
background: #FFFFFF;
box-shadow: 0rpx -2rpx 6rpx 0rpx rgba(181,181,181,0.13);
box-shadow: 0rpx -2rpx 6rpx 0rpx rgba(181, 181, 181, 0.13);
backdrop-filter: blur(20rpx);
display: flex;
.submit{
.submit {
width: 100%;
display: flex;
justify-content: center;
@ -199,6 +259,5 @@
column-gap: 50rpx;
}
}
}
}
</style>

4
pages/usercenter/usercenter.vue

@ -9,12 +9,12 @@
<view class="menu">
<view class="item" @click="toVisitors">
<img :src="cssUrl+'user_icon.svg'" alt="">
<view>预约</view>
<view>就诊</view>
</view>
<view class="item" @click="toPrebookList">
<img :src="cssUrl+'message.svg'" alt="">
<view>预约记录</view>
<view>就诊记录</view>
</view>
</view>

13
pages/visitors/visitors.vue

@ -14,8 +14,11 @@
<view class="name PfScSemibold over2">{{item.name}}</view>
<view class="book-date" v-if="type == 0 && item.visit_time && !is_preview">已预约今日 {{ item.visit_time.split('-')[0] }} 预约</view>
</view>
<view class="bot line36">
身份证号{{item.idcard_txt}}
<view class="bot line36 flex">
<!-- <view class="flex"> <view class="gap">|</view> 25</view>
<view v-if="item.phone" class="flex"><view class="gap">|</view> 手机号1778989678</view> -->
<view class="flex">{{item.sex}}<view class="gap">|</view> {{ item.age }}</view>
<view v-if="item.phone" class="flex"><view class="gap">|</view>手机号{{ item.phone }}</view>
</view>
<img class="status" :src="cssUrl+'visitor_select_active.svg'">
<img class="bg" :src="cssUrl+'visitor_list__bg.svg'">
@ -427,7 +430,11 @@
.bot{
margin-top: 32rpx;
font-size: 30rpx;
color: #949699;
color: #333333;
}
.gap{
margin: 0 23rpx;
color: #DBDBDB;
}
img{
position: absolute;

Loading…
Cancel
Save