From a130f428b914f019d8115d0d0233a64492e9075c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E7=90=A6?= Date: Mon, 2 Feb 2026 16:10:46 +0800 Subject: [PATCH] =?UTF-8?q?UI=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pages/Inquiries/Inquiries.vue | 57 ++++- pages/home/home.vue | 45 +++- request/api/product.js | 14 ++ store/chat/chat.js | 3 + subPackages/chat/chat.vue | 4 +- subPackages/chat/components/MessageBubble.vue | 237 +++++++++++++++--- subPackages/doctor/doctor-userinfo.vue | 5 +- subPackages/register/register.vue | 33 ++- 8 files changed, 356 insertions(+), 42 deletions(-) diff --git a/pages/Inquiries/Inquiries.vue b/pages/Inquiries/Inquiries.vue index 913044b..535d611 100644 --- a/pages/Inquiries/Inquiries.vue +++ b/pages/Inquiries/Inquiries.vue @@ -172,9 +172,64 @@ type: "", } }, - onLoad(e) { + async onLoad(e) { this.type = e.type // console.log(e, 'idd'); + + // 当 type === 2 (诊所在线问诊) 时,直接获取委托诊所和医生信息并跳转到挂号页面 + if (this.type === '2') { + try { + const storeId = uni.getStorageSync('store_id') || '11001'; + const { getClinicOnlineConsultationInfoApi } = await import('@/request/api/product'); + const configRes = await getClinicOnlineConsultationInfoApi({ store_id: storeId }); + + if (configRes.data?.code === 0 || configRes.data?.code === '0') { + const result = configRes.data?.result; + + if (result?.can_use && result?.delegate_doctor_id) { + // 直接跳转到就诊人选择页面,传递医生ID和挂号类型 + uni.redirectTo({ + url: `/subPackages/doctor/doctor-userinfo?id=${result.delegate_doctor_id}&r_type=2&delegate_store_id=${result.delegate_store_id || storeId}` + }); + return; + } else { + uni.showToast({ + title: result?.message || '该门店暂不支持在线问诊功能', + icon: 'none', + duration: 2000 + }); + // 返回上一页 + setTimeout(() => { + uni.navigateBack(); + }, 2000); + return; + } + } else { + uni.showToast({ + title: configRes.data?.message || '获取在线问诊信息失败', + icon: 'none', + duration: 2000 + }); + // 返回上一页 + setTimeout(() => { + uni.navigateBack(); + }, 2000); + return; + } + } catch (error) { + console.error('获取在线问诊信息失败:', error); + uni.showToast({ + title: '获取在线问诊信息失败', + icon: 'none', + duration: 2000 + }); + // 返回上一页 + setTimeout(() => { + uni.navigateBack(); + }, 2000); + return; + } + } }, methods: { closeDropdown() { diff --git a/pages/home/home.vue b/pages/home/home.vue index e41e118..ac38280 100644 --- a/pages/home/home.vue +++ b/pages/home/home.vue @@ -72,7 +72,7 @@ - + 在线复诊 在线选药 极速达 @@ -317,6 +317,49 @@ export default { } }, async goYard(type) { + // 当 type === 2 (诊所在线问诊) 时,直接获取委托诊所和医生信息并跳转到挂号页面 + if (type === 2) { + try { + const storeId = uni.getStorageSync('store_id') || '11001'; + const { getClinicOnlineConsultationInfoApi } = await import('@/request/api/product'); + const configRes = await getClinicOnlineConsultationInfoApi({ store_id: storeId }); + + if (configRes.data?.code === 0 || configRes.data?.code === '0') { + const result = configRes.data?.result; + + if (result?.can_use && result?.delegate_doctor_id) { + // 直接跳转到就诊人选择页面,传递医生ID和挂号类型 + uni.navigateTo({ + url: `/subPackages/doctor/doctor-userinfo?id=${result.delegate_doctor_id}&r_type=2&delegate_store_id=${result.delegate_store_id || storeId}` + }); + return; + } else { + uni.showToast({ + title: result?.message || '该门店暂不支持在线问诊功能', + icon: 'none', + duration: 2000 + }); + return; + } + } else { + uni.showToast({ + title: configRes.data?.message || '获取在线问诊信息失败', + icon: 'none', + duration: 2000 + }); + return; + } + } catch (error) { + console.error('获取在线问诊信息失败:', error); + uni.showToast({ + title: '获取在线问诊信息失败', + icon: 'none', + duration: 2000 + }); + return; + } + } + // 当 type === 3 (在线复诊) 时,需要先检查门店是否支持在线问诊功能 if (type === 3) { try { diff --git a/request/api/product.js b/request/api/product.js index 3a807b7..9be65f2 100644 --- a/request/api/product.js +++ b/request/api/product.js @@ -63,6 +63,20 @@ export async function checkOnlineConsultationConfigApi(params) { return await get(url, restParams, 3) } +/** + * 获取诊所在线问诊信息(委托诊所和委托医生) + * @param params { store_id: number, guest?: number } - guest: 0=普通接口, 1=Guest接口 + * @returns {Promise<*>} + */ +export async function getClinicOnlineConsultationInfoApi(params) { + const { guest = 0, ...restParams } = params; + // guest=1 时调用 Guest 接口,guest=0 时调用普通接口 + const url = guest === 1 + ? '/guest/guest-platform/get-clinic-online-consultation-info' + : '/store/get-clinic-online-consultation-info'; + return await get(url, restParams, 3) +} + /** * 获取药品分类列表 * @param params { zone_type: string } diff --git a/store/chat/chat.js b/store/chat/chat.js index 14beae7..3b688d1 100644 --- a/store/chat/chat.js +++ b/store/chat/chat.js @@ -326,6 +326,9 @@ const ChatManager = { if (parsed.type === 'price_update') { return parsed.message || '[价格更新]'; } + if (parsed.type === 'price_adjust') { + return parsed.message || '[价格调整]'; + } return '[系统消息]'; } catch (e) { return '[系统消息]'; diff --git a/subPackages/chat/chat.vue b/subPackages/chat/chat.vue index 36808dd..739a967 100644 --- a/subPackages/chat/chat.vue +++ b/subPackages/chat/chat.vue @@ -79,6 +79,7 @@ @viewRegister="viewRegister" @viewPrescription="viewPrescription" @goToOrderMedicine="goToOrderMedicine" + @viewOrder="viewOrder" /> @@ -770,7 +771,8 @@ export default { getRegisterStatusText(status) { const map = { 0: '待就诊', 1: '已缴费', 2: '已就诊', 3: '已取消', 4: '已退费' }; return map[status] || '未知状态'; }, viewPrescription(id, orderNo) { uni.navigateTo({ url: "/subPackages/my/myrecord-detail?id=" + id + '&no=' + orderNo }); }, goToOrderMedicine(id, orderNo) { uni.navigateTo({ url: "/subPackages/my/my-drug/drug-info?id=" + id + '&order_type=prescription' }); }, - viewRegister(id, orderNo) { uni.navigateTo({ url: "/subPackages/register/register-detail?id=" + id + '&no=' + orderNo }); } + viewRegister(id, orderNo) { uni.navigateTo({ url: "/subPackages/register/register-detail?id=" + id + '&no=' + orderNo }); }, + viewOrder(orderId, orderNo) { uni.navigateTo({ url: "/subPackages/my/my-drug/drug-info?id=" + orderId }); } } }; diff --git a/subPackages/chat/components/MessageBubble.vue b/subPackages/chat/components/MessageBubble.vue index e6920bf..7d35ac0 100644 --- a/subPackages/chat/components/MessageBubble.vue +++ b/subPackages/chat/components/MessageBubble.vue @@ -7,7 +7,6 @@ - @@ -23,20 +22,28 @@ @click="$emit('previewImage', parsedContent)"> - - + + + + {{ msg.duration }}'' - - + + + + - - + + {{ msg.duration }}'' + @@ -46,20 +53,77 @@ class="media-content video"> - + - - - - - {{ parsedContent.message }} + + + + + {{ parsedContent.type === 'price_update' ? '订单改价通知' : '费用调整提醒' }} - - 订单号:{{ parsedContent.order_no }} - 应付金额:¥{{ parsedContent.total_pay_price }} + + + + + + + + 变动说明 + {{ parsedContent.message }} + + + 最新应付 + ¥{{ parsedContent.total_pay_price }} + + + 订单编号 + {{ parsedContent.order_no }} + + + + + + + 调整项目 + {{ parsedContent.drug_name || '医疗服务' }} + + + + 价格变动 + + ¥{{ parsedContent.old_price }} + + ¥{{ parsedContent.new_price }} + + + + + 变动金额 + + {{ parsedContent.adjust_amount >= 0 ? '增加' : '减少' }} ¥{{ Math.abs(parsedContent.adjust_amount) }} + + + + + 当前总额 + ¥{{ parsedContent.total_pay_price }} + + + + + + + + 查看详情 + - + + {{ msg.message_content }} @@ -88,19 +152,14 @@ 患者就诊经历 - 药品名称 {{ parsedContent.drug_name }} - - 症状描述 {{ parsedContent.illness_info }} - - 是否就诊过{{ parsedContent.has_visited === '1' ? '是' : '否' }} 是否使用过药品{{ parsedContent.has_used_drug === '1' ? '是' : '否' }} @@ -186,7 +245,7 @@ export default { }, // 是否是系统消息且为价格变动(需要独立卡片样式) isSystemPriceUpdate() { - return this.msg.message_type === 9 && this.parsedContent.type === 'price_update'; + return this.msg.message_type === 9 && (this.parsedContent.type === 'price_update' || this.parsedContent.type === 'price_adjust'); }, isCardType() { return [4, 10, 11, 12, 13].includes(this.msg.message_type); @@ -205,6 +264,14 @@ export default { } }, methods: { + // 计算语音条宽度 (Min: 100rpx, Max: 350rpx, Unit: 10rpx/sec) + getAudioWidth(duration) { + const min = 120; + const max = 350; + const unit = 12; + let w = min + (parseInt(duration) || 0) * unit; + return Math.min(w, max) + 'rpx'; + }, getStatusText(status) { const map = { 0: '待审核', 1: '已审核', 2: '未通过' }; return map[status] || '状态未知'; }, getRegisterStatusText(status) { const map = { 0: '待就诊', 1: '已缴费', 2: '已就诊', 3: '已取消', 4: '已退费' }; return map[status] || '状态未知'; }, } @@ -219,7 +286,8 @@ $bg-other: #FFFFFF; $text-main: #333333; $text-sub: #666666; $radius-bubble: 12rpx; -$max-width: 500rpx; +$price-color: #FF4D4F; // 价格红 +$success-color: #059669; .bubble-container { display: flex; @@ -306,13 +374,51 @@ $max-width: 500rpx; &.video { width: 300rpx; height: 170rpx; } } -// 语音 +// ========== 语音条样式 (Audio) ========== .audio-content { - display: flex; align-items: center; gap: 12rpx; min-width: 100rpx; - .duration { font-size: 28rpx; } + display: flex; align-items: center; + // 宽度由 style 动态控制,这里不要锁死 width + justify-content: space-between; + + .duration { + font-size: 26rpx; + white-space: nowrap; + } + + .voice-icon-wrap { + display: flex; align-items: center; justify-content: center; + width: 44rpx; height: 44rpx; + + // 对方发的消息,图标在左,波纹向右(默认) + &.other { + margin-right: 6rpx; + } + + // 我发的消息,图标在右,波纹需要转向左侧 (rotate 180) + &.mine { + margin-left: 6rpx; + transform: rotate(180deg); + } + + // 播放时的动画:呼吸/波动效果 + &.playing { + animation: voice-pulse 1.2s infinite ease-in-out; + } + } } -// ========== 卡片样式 ========== +// 语音播放动画关键帧 +@keyframes voice-pulse { + 0% { opacity: 1; transform: scale(1) rotate(var(--rotate-angle, 0deg)); } + 50% { opacity: 0.4; transform: scale(0.92) rotate(var(--rotate-angle, 0deg)); } + 100% { opacity: 1; transform: scale(1) rotate(var(--rotate-angle, 0deg)); } +} +// 为了解决 rotate 和 scale 同时作用的问题,分别定义 mine 和 other +.voice-icon-wrap.mine.playing { --rotate-angle: 180deg; animation: voice-pulse 1.2s infinite ease-in-out; } +.voice-icon-wrap.other.playing { --rotate-angle: 0deg; animation: voice-pulse 1.2s infinite ease-in-out; } + + +// ========== 卡片样式 (通用) ========== .card-content { background: #fff; border-radius: 16rpx; @@ -362,11 +468,76 @@ $max-width: 500rpx; } } -// 系统消息样式 -.system-message-card { - background: #FFFBEB; border: 1rpx solid #FEF3C7; border-radius: 16rpx; padding: 20rpx; width: 480rpx; - .price-update-notice { display: flex; align-items: center; gap: 10rpx; margin-bottom: 10rpx; .notice-text { color: #D97706; font-size: 26rpx; font-weight: 600; } } - .price-detail { display: flex; flex-direction: column; gap: 6rpx; font-size: 22rpx; color: #78350F; padding-left: 46rpx; } +// ========== 原生风格服务通知 (Service Notify Card) ========== +// 这是一个非常经典、耐看的布局,模仿微信/支付宝的服务通知 +.service-notify-card { + background: #FFFFFF; + border-radius: 12rpx; // 稍微调小圆角,更正式 + width: 480rpx; + border: 1rpx solid #eaeaea; // 纯粹的边框 + overflow: hidden; + position: relative; + + // 头部:极简 + .sn-header { + padding: 24rpx 24rpx 16rpx 24rpx; + border-bottom: 1rpx solid #f5f5f5; + .sn-title { + font-size: 30rpx; + font-weight: 600; + color: #333; + } + } + + // 内容区:标准的左key右value列表 + .sn-body { + padding: 20rpx 24rpx; + display: flex; flex-direction: column; gap: 16rpx; + + .sn-row { + display: flex; justify-content: space-between; align-items: flex-start; + line-height: 1.4; + + .sn-label { + font-size: 26rpx; color: #999; // 经典的标签灰 + min-width: 110rpx; // 保证对齐 + } + + .sn-value { + font-size: 26rpx; color: #333; text-align: right; flex: 1; + &.truncate { + white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 320rpx; + } + &.price { color: #333; font-weight: 600; font-size: 28rpx; } // 普通金额强调 + &.sub { color: #999; font-family: monospace; } + &.strong { color: #333; font-weight: bold; font-size: 30rpx; } + + // 涨跌颜色 + &.color-orange { color: #fa8c16; } + &.color-green { color: #52c41a; } + } + + // 价格变化组合 + .sn-value-group { + display: flex; align-items: center; justify-content: flex-end; + .old { color: #999; text-decoration: line-through; font-size: 24rpx; } + .new { color: #333; font-weight: 600; font-size: 26rpx; } + } + } + } + + // 底部:通用的查看详情 + .sn-footer { + border-top: 1rpx solid #f5f5f5; + padding: 18rpx 24rpx; + display: flex; justify-content: space-between; align-items: center; + font-size: 24rpx; color: #666; + background: #fff; + + &:active { + background: #f9f9f9; // 仅底栏有点击态 + } + } } .system-inner { diff --git a/subPackages/doctor/doctor-userinfo.vue b/subPackages/doctor/doctor-userinfo.vue index d89ccd6..f179860 100644 --- a/subPackages/doctor/doctor-userinfo.vue +++ b/subPackages/doctor/doctor-userinfo.vue @@ -342,9 +342,12 @@ export default { mask: true }); // 如果是购药类型(register_type=3)且有委托诊所ID,则使用委托诊所ID;否则使用当前门店ID - const storeId = (this.registerType === '3' && this.delegateStoreId) + const storeId = (this.registerType != '0' && this.delegateStoreId) ? this.delegateStoreId : (uni.getStorageSync('store_id') || '11001'); + // const storeId = ((this.registerType === '3' || this.registerType == '2') && this.delegateStoreId) + // ? this.delegateStoreId + // : (uni.getStorageSync('store_id') || '11001'); registe({ method: "post", data: { diff --git a/subPackages/register/register.vue b/subPackages/register/register.vue index e35aa9d..926bf51 100644 --- a/subPackages/register/register.vue +++ b/subPackages/register/register.vue @@ -172,7 +172,9 @@ // 原有逻辑:已有 register_id this.register_id = e.id; this.rInfo = e.r_info ? (typeof e.r_info === 'string' ? JSON.parse(decodeURIComponent(e.r_info)) : e.r_info) : {}; - this.currentDoctorId = e.doctor_id ? ('doctor-' + e.doctor_id.replace('doctor-', '')) : 'doctor-39'; + // 修复:如果 doctor_id 为空字符串,也使用默认值;如果 doctor_id 存在且不为空,则使用它 + const doctorId = e.doctor_id && e.doctor_id.trim() !== '' ? e.doctor_id : null; + this.currentDoctorId = doctorId ? ('doctor-' + doctorId.replace('doctor-', '')) : 'doctor-39'; uni.setStorageSync('register_id', this.register_id); // 获取挂号信息 @@ -195,6 +197,10 @@ if (res.data.errcode == 0) { that.registList = res.data.data.list[0] that.registerType = that.registerMap[that.registList.register_type]; + // 如果挂号信息中有医生ID,更新 currentDoctorId + if (that.registList.service_user_id) { + that.currentDoctorId = 'doctor-' + that.registList.service_user_id; + } } }) }, @@ -202,19 +208,36 @@ async handleOnlineConsultationAfterPayment() { let that = this; try { - // 1. 获取医生ID(从 currentDoctorId 中提取) - const doctorId = that.currentDoctorId.replace('doctor-', ''); + // 1. 获取医生ID(优先从挂号信息中获取,否则从 currentDoctorId 中提取) + let doctorId = ''; + if (that.registList && that.registList.service_user_id) { + doctorId = String(that.registList.service_user_id); + } else { + doctorId = that.currentDoctorId.replace('doctor-', ''); + } + + // 如果医生ID仍然为空,报错 + if (!doctorId || doctorId === '') { + uni.hideLoading(); + uni.showToast({ + title: '医生ID不能为空:' + doctorId, + icon: 'none' + }); + return; + } // 2. 获取患者ID const patientId = that.currentUserId.replace('user-', ''); - // 3. 创建或获取聊天房间 (type=3 表示在线复诊/购药) + // 3. 创建或获取聊天房间 + // type=2 表示诊所在线复诊,type=3 表示药店在线复诊/购药 + const roomType = (that.registList && that.registList.register_type === 2) ? 2 : 3; const roomRes = await request('/xkApi/online-consultation/get-or-create-chat-room', { method: 'POST', data: { doctor_id: doctorId, patient_id: patientId, - type: 3 + type: roomType } }, 1);