Files
wxapp_escort/pages/escort/itemdetail.js
T
2026-10-18 22:14:49 +08:00

437 lines
12 KiB
JavaScript

const API = require('../../utils/api.js')
Page({
data: {
service: {
id: null,
title: '',
subtitle: '',
price: '0.00',
image: '',
tag: '',
description: '',
flow: [],
notices: []
},
totalPrice: '0.00',
showOrderPopup: false,
profiles: [], // 已保存的就诊人
selectedProfileId: '', // 必填:订单必须关联就诊人档案
patientName: '', // 只读展示,来自所选档案
patientPhone: '', // 只读展示,来自所选档案
// 选中档案的全部信息,下单时整体写入订单 patient 快照
selectedPatient: null,
// 默认北京:取值必须与 provinces[0] 完全一致('北京市' 而非 '北京'),
// 否则 picker 的 value=0 与显示文案会对不上
province: '北京市',
provinceIndex: 0,
provinces: ['北京市', '天津市', '河北省', '山西省', '内蒙古自治区', '辽宁省', '吉林省', '黑龙江省', '上海市', '江苏省', '浙江省', '安徽省', '福建省', '江西省', '山东省', '河南省', '湖北省', '湖南省', '广东省', '广西壮族自治区', '海南省', '重庆市', '四川省', '贵州省', '云南省', '西藏自治区', '陕西省', '甘肃省', '青海省', '宁夏回族自治区', '新疆维吾尔自治区', '台湾省', '香港特别行政区', '澳门特别行政区'],
hospital: '',
appointmentDate: '',
appointmentTime: '',
remark: '',
today: '',
gender: '不限',
genderIndex: 0,
genderOptions: ['不限', '男', '女'],
department: '',
departments: ['内科', '外科', '妇产科', '儿科', '骨科', '神经科', '心血管内科', '消化内科', '呼吸内科', '内分泌科', '皮肤科', '眼科', '耳鼻喉科', '口腔科', '急诊科', '肿瘤科', '康复医学科', '老年病科', '中医科', '针灸推拿科'],
hospitals: []
},
onLoad(options) {
const today = new Date()
const year = today.getFullYear()
const month = String(today.getMonth() + 1).padStart(2, '0')
const day = String(today.getDate()).padStart(2, '0')
const todayStr = `${year}-${month}-${day}`
this.setData({
today: todayStr
})
const serviceId = parseInt(options.id) || 1
this.loadServiceDetail(serviceId)
// 从列表页的「预约」进来(?book=1)时,直接把预约单弹出来;
// 未登录会由 openOrderPopup 拦下并提示登录
if (options.book === '1') {
this.openOrderPopup()
}
},
onShow() {
// 从"新增就诊人"页面返回时,弹窗还开着就刷新一次可选的就诊人
if (this.data.showOrderPopup) {
this.loadProfiles()
}
},
loadServiceDetail(id) {
const app = getApp()
let service = null
for (const item of app.globalData.services) {
if (item.id === id) {
service = item
break
}
}
if (!service) {
return
}
const totalPrice = this.calculateTotal(service.price, 1)
this.setData({
service: service,
serviceIcon: this.getServiceIcon(service.title),
totalPrice: totalPrice
})
},
// 弹窗服务标记:原占位图是全服务共用的一张白色线稿,落在浅橙面板上看不见,
// 改用暖橙 t-icon(名称均已核对 tdesign 图标表,写错不报错只会渲染为空)。
// 图标按服务名选:夜间→月亮,陪诊→时钟,其余(取报告/代取药品等代办)→人像
getServiceIcon(title) {
if (title.indexOf('夜间') > -1) {
return 'moon'
}
if (title.indexOf('陪诊') > -1) {
return 'time'
}
return 'user-business'
},
calculateTotal(price) {
return price
},
openOrderPopup() {
const app = getApp()
if (!app.globalData.user) {
wx.showToast({
title: '请先登录',
icon: 'none'
})
return
}
// 订单必须关联健康档案,就诊人不再手输:打开弹窗时清空,等用户选择就诊人后带入
this.setData({
patientName: '',
patientPhone: '',
selectedProfileId: '',
selectedPatient: null,
showOrderPopup: true
})
this.loadProfiles()
},
// 读取已保存的就诊人,供弹窗内一键选择
loadProfiles() {
API.healthProfile.getMyProfiles({
page: 1,
pageSize: 20
})
.then((res) => {
if (res.code !== 0) {
return
}
// 档案是 profile + health 两层嵌套,这里拍平成选人后可直接带入的字段
const list = ((res.data && res.data.list) || []).map((item) => {
const profile = item.profile || {}
const health = item.health || {}
return {
_id: item._id,
name: profile.name || '',
mobile: profile.mobile || '',
sex: profile.sex || '',
birth: profile.birth || '',
weight: health.weight || 0,
height: health.height || 0,
idnumber: profile.idnumber || ''
}
})
this.setData({
profiles: list
})
})
.catch((err) => {
console.log('获取就诊人列表失败', err)
})
},
// 选择就诊人:姓名/电话回填展示,其余字段存入 selectedPatient 供下单使用
onSelectProfile(e) {
const id = e.currentTarget.dataset.id
const profile = this.data.profiles.find((item) => item._id === id)
if (!profile) {
return
}
this.setData({
selectedProfileId: id,
// patientName / patientPhone 只用于弹窗内只读展示
patientName: profile.name,
patientPhone: profile.mobile,
// 订单 patient 快照的唯一来源:所选档案的名单字段(体征与证件号不进快照)
selectedPatient: {
name: profile.name,
mobile: profile.mobile,
sex: profile.sex,
birth: profile.birth
}
})
},
// 跳转到就诊人页新增
goToAddProfile() {
wx.navigateTo({
url: '/pages/health/profileedit'
})
},
closeOrderPopup() {
this.setData({
showOrderPopup: false
})
},
onProvinceChange(e) {
const index = e.detail.value
const province = this.data.provinces[index]
this.setData({
provinceIndex: index,
province: province
})
},
onHospitalChange(e) {
this.setData({
hospital: e.detail.value
})
},
onDepartmentChange(e) {
this.setData({
department: e.detail.value
})
},
onDateChange(e) {
this.setData({
appointmentDate: e.detail.value
})
},
onTimeChange(e) {
this.setData({
appointmentTime: e.detail.value
})
},
onGenderChange(e) {
const index = e.detail.value
const gender = this.data.genderOptions[index]
this.setData({
genderIndex: index,
gender: gender
})
},
onRemarkChange(e) {
this.setData({
remark: e.detail.value
})
},
submitOrder() {
const {
service,
selectedProfileId,
selectedPatient,
province,
hospital,
department,
appointmentDate,
appointmentTime,
gender,
remark
} = this.data
// 订单必须关联就诊人:没有档案就没有 patient 快照,不允许下单
if (!selectedProfileId || !selectedPatient) {
wx.showToast({
title: '请选择就诊人',
icon: 'none'
})
return
}
if (!hospital.trim()) {
wx.showToast({
title: '请输入就诊医院',
icon: 'none'
})
return
}
if (!department.trim()) {
wx.showToast({
title: '请输入就诊科室',
icon: 'none'
})
return
}
if (!appointmentDate) {
wx.showToast({
title: '请选择预约日期',
icon: 'none'
})
return
}
if (!appointmentTime) {
wx.showToast({
title: '请选择预约时间',
icon: 'none'
})
return
}
const phoneRegex = /^1[3-9]\d{9}$/
if (!phoneRegex.test(selectedPatient.mobile.trim())) {
wx.showToast({
title: '就诊人手机号有误,请到就诊人档案修改',
icon: 'none'
})
return
}
const app = getApp()
const user = app.globalData.user
let sex = "none"
if (gender == '男') sex = 'male'
else if (gender == '女') sex = 'female'
// 就诊人快照只取名单字段(schema 口径:name/mobile/sex/birth);
// sex 是 male/female 枚举,空值不写该字段
const patient = {
name: selectedPatient.name.trim(),
mobile: selectedPatient.mobile.trim(),
birth: selectedPatient.birth || ''
}
if (selectedPatient.sex) {
patient.sex = selectedPatient.sex
}
const orderData = {
userId: user._id,
// 订单与就诊人档案的关联,必填(patient 只是下单当刻的快照)
healthProfileId: selectedProfileId,
patient: patient,
escort: {
serviceId: service.id,
serviceName: service.title,
sexRequirement: sex
},
hospital: {
province: province,
name: hospital.trim(),
department: department.trim(),
},
schedule: {
date: appointmentDate,
startTime: appointmentTime
},
payment: {
totalFee: service.price
},
notes: {
patientNote: remark.trim()
}
}
wx.showLoading({
title: '提交中...'
})
API.escort.createRecord(orderData)
.then((data) => {
wx.hideLoading()
if (data.code === 0) {
wx.showToast({
title: '下单成功',
icon: 'success'
})
this.setData({
showOrderPopup: false
})
this.resetForm()
// 下单成功回到记录页,直接落到「进行中的」:新单是待确认,属未完成档
wx.navigateTo({url: '/pages/escort/recordlist?tab=ongoing'})
} else {
wx.showToast({
title: data.msg || '下单失败',
icon: 'none'
})
}
})
.catch((err) => {
wx.hideLoading()
wx.showToast({
title: '网络请求失败',
icon: 'none'
})
console.log('下单失败', err)
})
},
resetForm() {
this.setData({
selectedProfileId: '',
patientName: '',
patientPhone: '',
selectedPatient: null,
// 重置后仍回到默认北京,与 data 初值保持一致
province: '北京市',
provinceIndex: 0,
hospital: '',
department: '',
appointmentDate: '',
appointmentTime: '',
// 重置后回到默认「不限」,与 data 初值(gender: '不限' / genderIndex: 0)保持一致
gender: '不限',
genderIndex: 0,
remark: ''
})
const totalPrice = this.calculateTotal(this.data.service.price)
this.setData({
totalPrice: totalPrice
})
},
onShareAppMessage() {
const {
service
} = this.data
return {
title: `${service.title} - 专业陪诊服务`,
path: `/pages/escort/itemdetail?id=${service.id}`
}
},
// 朋友圈只能分享当前页,服务 id 只能靠 query 带上;
// 服务未加载完(service.id 为 null)时不带 query,落到默认项,避免拼出 id=null
onShareTimeline() {
const {
service
} = this.data
if (!service.id) {
return {
title: '暖橙陪诊 · 专业陪诊服务'
}
}
return {
title: `${service.title} - 专业陪诊服务`,
query: `id=${service.id}`
}
}
})