feat: 首页按后台配置展示订单提醒,挂号详情支持自行改期
首页金刚区和订单提醒样式走配置下发,消息页改为四入口宫格;挂号详情可改期并展示轨迹,取消态展示与支付取值统一按 xk-api 的 code/result。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -112,8 +112,9 @@ export default {
|
||||
method: 'post',
|
||||
data: { register_id: registerId },
|
||||
})
|
||||
if (res.data && (res.data.errcode == 0 || res.data.errcode === '0')) {
|
||||
const data = res.data.data || {}
|
||||
// registePay 为 xk-api:按 code/result/message 取值
|
||||
if (res.data && (res.data.code == 0 || res.data.code === '0')) {
|
||||
const data = res.data.result || {}
|
||||
if (data.is_paid == 1 || data.is_pay == 1) {
|
||||
uni.showToast({ title: '认领成功', icon: 'success' })
|
||||
return
|
||||
@@ -134,7 +135,7 @@ export default {
|
||||
})
|
||||
} else {
|
||||
uni.showToast({
|
||||
title: (res.data && (res.data.message || res.data.msg)) || '获取支付参数失败',
|
||||
title: (res.data && res.data.message) || '获取支付参数失败',
|
||||
icon: 'none',
|
||||
})
|
||||
}
|
||||
|
||||
@@ -54,7 +54,15 @@
|
||||
<view v-if="homeZonesInitialLoading" class="zone-wrapper">
|
||||
<ListSkeleton type="zone" :rows="5" />
|
||||
</view>
|
||||
<view v-else-if="homeZones.length > 0" class="zone-wrapper" :class="zoneLayoutMode === 'scroll' ? 'zone-scroll-mode' : 'zone-wrap-mode'">
|
||||
<view
|
||||
v-else-if="homeZones.length > 0"
|
||||
class="zone-wrapper"
|
||||
:class="{
|
||||
'zone-scroll-mode': zoneLayoutMode === 'scroll',
|
||||
'zone-wrap-mode': zoneLayoutMode === 'wrap',
|
||||
'zone-wrap2-mode': zoneLayoutMode === 'wrap2'
|
||||
}"
|
||||
>
|
||||
<view v-for="(item, index) in homeZones" :key="index" class="zone-item" @click="goZoneList(item)">
|
||||
<view class="zone-icon-box">
|
||||
<image
|
||||
@@ -105,24 +113,59 @@
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 待支付挂号提醒 -->
|
||||
<!-- 订单提醒:后台可配一行两列卡片 / 金刚区图标 -->
|
||||
<view
|
||||
v-if="unpaidRegisterCount > 0"
|
||||
class="unpaid-banner unpaid-banner--register"
|
||||
@click="onUnpaidRegisterBannerClick"
|
||||
v-if="visibleOrderReminds.length > 0 && orderRemindStyle === 'grid'"
|
||||
class="order-remind-grid"
|
||||
>
|
||||
<text class="unpaid-banner-text">您有 {{ unpaidRegisterCount }} 个待支付挂号订单,点击前往查看</text>
|
||||
<text class="iconfont icon-jiantou1 unpaid-banner-arrow"></text>
|
||||
<view
|
||||
v-for="item in visibleOrderReminds"
|
||||
:key="item.key"
|
||||
class="order-remind-card"
|
||||
:class="{
|
||||
'order-remind-card--register': item.key === 'unpaid_register',
|
||||
'order-remind-card--product': item.key === 'unpaid_product',
|
||||
'order-remind-card--shipped': item.key === 'shipped',
|
||||
'order-remind-card--arrived': item.key === 'arrived'
|
||||
}"
|
||||
@click="onOrderRemindTap(item)"
|
||||
>
|
||||
<view class="order-remind-card-main">
|
||||
<text class="order-remind-card-title">{{ item.title }}</text>
|
||||
<text class="order-remind-card-count">{{ item.count }}</text>
|
||||
</view>
|
||||
<text class="iconfont icon-jiantou1 order-remind-card-arrow"></text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 待支付商品订单提醒 -->
|
||||
<view
|
||||
v-if="unpaidProductOrderCount > 0"
|
||||
class="unpaid-banner unpaid-banner--product"
|
||||
@click="onUnpaidProductOrderBannerClick"
|
||||
v-else-if="visibleOrderReminds.length > 0"
|
||||
class="zone-wrapper order-remind-zone"
|
||||
:class="{
|
||||
'zone-scroll-mode': zoneLayoutMode === 'scroll',
|
||||
'zone-wrap-mode': zoneLayoutMode === 'wrap',
|
||||
'zone-wrap2-mode': zoneLayoutMode === 'wrap2'
|
||||
}"
|
||||
>
|
||||
<text class="unpaid-banner-text">您有 {{ unpaidProductOrderCount }} 个待支付商品订单,点击前往查看</text>
|
||||
<text class="iconfont icon-jiantou1 unpaid-banner-arrow"></text>
|
||||
<view
|
||||
v-for="item in visibleOrderReminds"
|
||||
:key="item.key"
|
||||
class="zone-item"
|
||||
@click="onOrderRemindTap(item)"
|
||||
>
|
||||
<view
|
||||
class="zone-icon-box order-remind-zone-icon"
|
||||
:class="{
|
||||
'order-remind-zone-icon--register': item.key === 'unpaid_register',
|
||||
'order-remind-zone-icon--product': item.key === 'unpaid_product',
|
||||
'order-remind-zone-icon--shipped': item.key === 'shipped',
|
||||
'order-remind-zone-icon--arrived': item.key === 'arrived'
|
||||
}"
|
||||
>
|
||||
<text :class="'iconfont ' + item.icon"></text>
|
||||
<text v-if="item.count > 0" class="order-remind-badge">{{ item.count }}</text>
|
||||
</view>
|
||||
<text class="zone-text">{{ item.title }}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 4. 诊所模式内容:特色药方 -->
|
||||
@@ -324,12 +367,18 @@ import {
|
||||
storeChange,
|
||||
storeInfo,
|
||||
storeList,
|
||||
fetchUnpaidProductOrderListApi,
|
||||
} from '../../request/api/api'
|
||||
import { getPlatformQualificationsApi } from '../../request/api/platform'
|
||||
import { getStoreDrugListBySalespersonApi, getHomeTopProductsApi, getHomeZonesApi, checkOnlineConsultationConfigApi } from "@/request/api/product";
|
||||
import {
|
||||
getStoreDrugListBySalespersonApi,
|
||||
getHomeTopProductsApi,
|
||||
getHomeZonesApi,
|
||||
getHomeDisplayConfigApi,
|
||||
getHomeOrderRemindApi,
|
||||
checkOnlineConsultationConfigApi,
|
||||
} from "@/request/api/product";
|
||||
import { getSpecialPrescriptionHomeApi } from '@/request/api/specialPrescription';
|
||||
import { fetchUnpaidRegisterListApi } from '@/request/api/register';
|
||||
import { unwrapXkApi } from '@/utils/api-response.js';
|
||||
import request from "@/request/api/request";
|
||||
import MessageNotification from "@/components/MessageNotification/MessageNotification.vue";
|
||||
import ClaimPatientModal from "@/components/claim-patient-modal/claim-patient-modal.vue";
|
||||
@@ -375,13 +424,11 @@ export default {
|
||||
statusBarHeight: 20,
|
||||
isSticky: false,
|
||||
|
||||
// 控制金刚区布局模式: 'scroll' (滑动) 或 'wrap' (换行)
|
||||
// 金刚区布局:scroll 横滑 / wrap 一行五个 / wrap2 一行两个(后台可配)
|
||||
zoneLayoutMode: 'scroll',
|
||||
|
||||
unpaidRegisterCount: 0,
|
||||
unpaidRegisterList: [],
|
||||
unpaidProductOrderCount: 0,
|
||||
unpaidProductOrderList: [],
|
||||
// 订单提醒:grid 一行两列 / zone 金刚区(后台可配)
|
||||
orderRemindStyle: 'grid',
|
||||
orderRemindItems: [],
|
||||
|
||||
// 特色药方(API)
|
||||
specialPrescription: {
|
||||
@@ -402,7 +449,11 @@ export default {
|
||||
// 判断是否为guest模式(用于模板)
|
||||
isGuestMode() {
|
||||
return isGuestMode;
|
||||
}
|
||||
},
|
||||
// 只展示有数量的订单提醒,避免空宫格占位
|
||||
visibleOrderReminds() {
|
||||
return (this.orderRemindItems || []).filter((item) => item && item.count > 0);
|
||||
},
|
||||
},
|
||||
onLoad() {
|
||||
|
||||
@@ -458,53 +509,85 @@ export default {
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
async fetchUnpaidCounts() {
|
||||
/**
|
||||
* 拉取首页展示样式(游客/登录都要,金刚区布局跟配置走)
|
||||
*/
|
||||
async fetchHomeDisplayConfig() {
|
||||
try {
|
||||
const res = await getHomeDisplayConfigApi();
|
||||
const { ok, payload } = unwrapXkApi(res);
|
||||
if (!ok || !payload) {
|
||||
return;
|
||||
}
|
||||
if (payload.zone_layout === 'scroll' || payload.zone_layout === 'wrap' || payload.zone_layout === 'wrap2') {
|
||||
this.zoneLayoutMode = payload.zone_layout;
|
||||
}
|
||||
if (payload.order_remind_style === 'grid' || payload.order_remind_style === 'zone') {
|
||||
this.orderRemindStyle = payload.order_remind_style;
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('fetchHomeDisplayConfig', e);
|
||||
}
|
||||
},
|
||||
/**
|
||||
* 首页订单提醒:待支付挂号/商品、已发货、已到货待确认
|
||||
* 未登录不请求,避免游客打到需登录接口
|
||||
*/
|
||||
async fetchOrderReminds() {
|
||||
if (!isLoggedIn()) {
|
||||
this.unpaidRegisterCount = 0;
|
||||
this.unpaidRegisterList = [];
|
||||
this.unpaidProductOrderCount = 0;
|
||||
this.unpaidProductOrderList = [];
|
||||
this.orderRemindItems = [];
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const [registerList, productList] = await Promise.all([
|
||||
fetchUnpaidRegisterListApi(),
|
||||
fetchUnpaidProductOrderListApi(),
|
||||
]);
|
||||
this.unpaidRegisterList = registerList;
|
||||
this.unpaidRegisterCount = registerList.length;
|
||||
this.unpaidProductOrderList = productList;
|
||||
this.unpaidProductOrderCount = productList.length;
|
||||
const res = await getHomeOrderRemindApi();
|
||||
const { ok, payload } = unwrapXkApi(res);
|
||||
if (!ok || !payload) {
|
||||
this.orderRemindItems = [];
|
||||
return;
|
||||
}
|
||||
if (payload.zone_layout === 'scroll' || payload.zone_layout === 'wrap' || payload.zone_layout === 'wrap2') {
|
||||
this.zoneLayoutMode = payload.zone_layout;
|
||||
}
|
||||
if (payload.order_remind_style === 'grid' || payload.order_remind_style === 'zone') {
|
||||
this.orderRemindStyle = payload.order_remind_style;
|
||||
}
|
||||
this.orderRemindItems = payload.items || [];
|
||||
} catch (e) {
|
||||
console.error('fetchUnpaidCounts', e);
|
||||
this.unpaidRegisterCount = 0;
|
||||
this.unpaidRegisterList = [];
|
||||
this.unpaidProductOrderCount = 0;
|
||||
this.unpaidProductOrderList = [];
|
||||
console.error('fetchOrderReminds', e);
|
||||
this.orderRemindItems = [];
|
||||
}
|
||||
},
|
||||
onUnpaidRegisterBannerClick() {
|
||||
if (this.unpaidRegisterCount === 1 && this.unpaidRegisterList[0]) {
|
||||
const id = this.unpaidRegisterList[0].id;
|
||||
/**
|
||||
* 订单提醒点击:1 条进详情,多条进对应列表
|
||||
* 已发货/待确认都落在商品订单「待收货」tab
|
||||
*/
|
||||
onOrderRemindTap(item) {
|
||||
if (!item) {
|
||||
return;
|
||||
}
|
||||
const count = Number(item.count) || 0;
|
||||
const firstId = Number(item.first_id) || 0;
|
||||
if (item.key === 'unpaid_register') {
|
||||
if (count === 1 && firstId > 0) {
|
||||
uni.navigateTo({
|
||||
url: `/subPackages/doctor/doctor-userinfo?step=2®ister_id=${firstId}`,
|
||||
});
|
||||
return;
|
||||
}
|
||||
uni.navigateTo({
|
||||
url: `/subPackages/doctor/doctor-userinfo?step=2®ister_id=${id}`,
|
||||
url: '/subPackages/my/myappiont',
|
||||
});
|
||||
return;
|
||||
}
|
||||
uni.navigateTo({
|
||||
url: '/subPackages/my/myappiont',
|
||||
});
|
||||
},
|
||||
onUnpaidProductOrderBannerClick() {
|
||||
if (this.unpaidProductOrderCount === 1 && this.unpaidProductOrderList[0]) {
|
||||
const id = this.unpaidProductOrderList[0].id;
|
||||
if (count === 1 && firstId > 0) {
|
||||
uni.navigateTo({
|
||||
url: `/subPackages/my/my-drug/drug-info?id=${id}`,
|
||||
url: `/subPackages/my/my-drug/drug-info?id=${firstId}`,
|
||||
});
|
||||
return;
|
||||
}
|
||||
const tabIndex = item.key === 'unpaid_product' ? 1 : 3;
|
||||
uni.navigateTo({
|
||||
url: '/subPackages/my/my-drug/drug-list?index=1',
|
||||
url: `/subPackages/my/my-drug/drug-list?index=${tabIndex}`,
|
||||
});
|
||||
},
|
||||
// 处理购物车按钮点击
|
||||
@@ -834,6 +917,8 @@ export default {
|
||||
this._productFetchDone = 0;
|
||||
return Promise.all([
|
||||
this.getHomeZones(),
|
||||
this.fetchHomeDisplayConfig(),
|
||||
this.fetchOrderReminds(),
|
||||
this.getList(),
|
||||
this.getProductList(),
|
||||
this.getHomeTopProducts(),
|
||||
@@ -963,7 +1048,8 @@ export default {
|
||||
this.getHomeZones();
|
||||
this.getPlatformQualifications(); // 已补回
|
||||
this.getDefaultDoctorId();
|
||||
this.fetchUnpaidCounts();
|
||||
this.fetchHomeDisplayConfig();
|
||||
this.fetchOrderReminds();
|
||||
this.fetchSpecialPrescriptionHome();
|
||||
this.openClaimPatientModal();
|
||||
this.openProxyPayConfirmModal();
|
||||
@@ -1050,13 +1136,20 @@ $card-shadow: 0 8rpx 20rpx rgba(0, 0, 0, 0.04);
|
||||
.zone-item { width: 140rpx; margin-right: 10rpx; }
|
||||
}
|
||||
|
||||
/* 模式2: 换行 */
|
||||
/* 模式2: 换行(一行五个) */
|
||||
&.zone-wrap-mode {
|
||||
flex-wrap: wrap;
|
||||
justify-content: flex-start;
|
||||
.zone-item { width: 20%; margin-bottom: 24rpx; }
|
||||
}
|
||||
|
||||
/* 模式3: 一行两个 */
|
||||
&.zone-wrap2-mode {
|
||||
flex-wrap: wrap;
|
||||
justify-content: flex-start;
|
||||
.zone-item { width: 50%; margin-bottom: 24rpx; }
|
||||
}
|
||||
|
||||
.zone-item {
|
||||
flex-shrink: 0; text-align: center; display: flex; flex-direction: column; align-items: center;
|
||||
&:active { transform: scale(0.95); }
|
||||
@@ -1089,44 +1182,77 @@ $card-shadow: 0 8rpx 20rpx rgba(0, 0, 0, 0.04);
|
||||
}
|
||||
}
|
||||
|
||||
.unpaid-banner {
|
||||
.order-remind-grid {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
padding: 0 32rpx 8rpx;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.order-remind-card {
|
||||
width: calc(50% - 10rpx);
|
||||
margin: 0 20rpx 16rpx 0;
|
||||
padding: 22rpx 20rpx;
|
||||
border-radius: 16rpx;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
margin: 16rpx 32rpx 0;
|
||||
padding: 24rpx 28rpx;
|
||||
border-radius: 16rpx;
|
||||
|
||||
&:nth-child(2n) { margin-right: 0; }
|
||||
&:active { transform: scale(0.98); }
|
||||
&--register {
|
||||
background: linear-gradient(90deg, rgba(65, 117, 238, 0.08) 0%, rgba(65, 117, 238, 0.04) 100%);
|
||||
border: 1rpx solid rgba(65, 117, 238, 0.2);
|
||||
|
||||
.unpaid-banner-text,
|
||||
.unpaid-banner-arrow {
|
||||
color: #4175EE;
|
||||
}
|
||||
border: 1rpx solid rgba(65, 117, 238, 0.3);
|
||||
box-shadow: 0 0 12rpx rgba(65, 117, 238, 0.18);
|
||||
background: rgba(65, 117, 238, 0.06);
|
||||
.order-remind-card-title, .order-remind-card-count, .order-remind-card-arrow { color: #4175EE; }
|
||||
}
|
||||
|
||||
&--product {
|
||||
background: linear-gradient(90deg, rgba(0, 181, 120, 0.08) 0%, rgba(0, 181, 120, 0.04) 100%);
|
||||
border: 1rpx solid rgba(0, 181, 120, 0.25);
|
||||
|
||||
.unpaid-banner-text,
|
||||
.unpaid-banner-arrow {
|
||||
color: #00B578;
|
||||
border: 1rpx solid rgba(0, 181, 120, 0.3);
|
||||
box-shadow: 0 0 12rpx rgba(0, 181, 120, 0.18);
|
||||
background: rgba(0, 181, 120, 0.06);
|
||||
.order-remind-card-title, .order-remind-card-count, .order-remind-card-arrow { color: #00B578; }
|
||||
}
|
||||
&--shipped {
|
||||
border: 1rpx solid rgba(255, 140, 0, 0.3);
|
||||
box-shadow: 0 0 12rpx rgba(255, 140, 0, 0.18);
|
||||
background: rgba(255, 140, 0, 0.06);
|
||||
.order-remind-card-title, .order-remind-card-count, .order-remind-card-arrow { color: #E67E00; }
|
||||
}
|
||||
&--arrived {
|
||||
border: 1rpx solid rgba(139, 92, 246, 0.3);
|
||||
box-shadow: 0 0 12rpx rgba(139, 92, 246, 0.18);
|
||||
background: rgba(139, 92, 246, 0.06);
|
||||
.order-remind-card-title, .order-remind-card-count, .order-remind-card-arrow { color: #7C3AED; }
|
||||
}
|
||||
.order-remind-card-main { flex: 1; min-width: 0; }
|
||||
.order-remind-card-title { display: block; font-size: 24rpx; font-weight: 500; }
|
||||
.order-remind-card-count { display: block; margin-top: 6rpx; font-size: 36rpx; font-weight: 800; line-height: 1.1; }
|
||||
.order-remind-card-arrow { font-size: 22rpx; margin-left: 8rpx; }
|
||||
}
|
||||
.order-remind-zone {
|
||||
padding-top: 8rpx;
|
||||
.order-remind-zone-icon {
|
||||
position: relative;
|
||||
&--register { color: #4175EE; }
|
||||
&--product { color: #00B578; }
|
||||
&--shipped { color: #E67E00; }
|
||||
&--arrived { color: #7C3AED; }
|
||||
.iconfont { font-size: 48rpx; }
|
||||
.order-remind-badge {
|
||||
position: absolute;
|
||||
top: -8rpx;
|
||||
right: -8rpx;
|
||||
min-width: 28rpx;
|
||||
height: 28rpx;
|
||||
padding: 0 8rpx;
|
||||
border-radius: 14rpx;
|
||||
background: #FF4D4F;
|
||||
color: #fff;
|
||||
font-size: 18rpx;
|
||||
line-height: 28rpx;
|
||||
text-align: center;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
}
|
||||
|
||||
.unpaid-banner-text {
|
||||
flex: 1;
|
||||
font-size: 26rpx;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.unpaid-banner-arrow {
|
||||
font-size: 24rpx;
|
||||
margin-left: 12rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.section-header {
|
||||
|
||||
@@ -12,107 +12,43 @@
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 首次加载:四条固定入口用骨架,避免 num 未定义时闪「暂无新消息」 -->
|
||||
<ListSkeleton v-if="noticeInitialLoading" type="message" :rows="4" />
|
||||
<template v-else>
|
||||
<!-- 消息列表 -->
|
||||
<view class="list" @click="goSystem">
|
||||
<!-- 头像 -->
|
||||
<view class="avator">
|
||||
<view class="img">
|
||||
<image src="https://xiaokang88.oss-cn-hangzhou.aliyuncs.com/xk-client-wx/static/xx/xt.png" mode=""></image>
|
||||
</view>
|
||||
<u-badge size="default" v-if="system.num>=0" :count="system.num" :is-dot="system.num==0?true:false"
|
||||
type="error" :offset="system.num>0?[-4,-8]:[0,0]"></u-badge>
|
||||
</view>
|
||||
<!-- 描述 -->
|
||||
<view class="info">
|
||||
<view class="infos_title">
|
||||
<text class="infos">系统消息</text>
|
||||
<text class="time">{{ system.time }}</text>
|
||||
</view>
|
||||
<view class="preview" v-if="system.num >0">
|
||||
您有{{ system.num }}条未读信息
|
||||
</view>
|
||||
<view class="preview" v-if="system.num==undefined">
|
||||
暂无新消息
|
||||
</view>
|
||||
<!-- 首次加载:宫格骨架,避免 num 未定义时闪「暂无新消息」 -->
|
||||
<view v-if="noticeInitialLoading" class="notice-grid">
|
||||
<view v-for="i in 4" :key="i" class="notice-card notice-card--sk">
|
||||
<view class="notice-sk-icon"></view>
|
||||
<view class="notice-card__body">
|
||||
<view class="notice-sk-line notice-sk-line--title"></view>
|
||||
<view class="notice-sk-line"></view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="list" @click="goOrder">
|
||||
<!-- 头像 -->
|
||||
<view class="avator">
|
||||
<view class="img">
|
||||
<image src="https://xiaokang88.oss-cn-hangzhou.aliyuncs.com/xk-client-wx/static/xx/cp.png" mode=""></image>
|
||||
</view>
|
||||
<u-badge size="default" v-if="order.num>=0" :count="order.num" :is-dot="order.num==0?true:false"
|
||||
type="error" :offset="order.num>0?[-4,-8]:[0,0]"></u-badge>
|
||||
</view>
|
||||
<!-- 四条固定入口:一行两列宫格,会话列表仍走下方长条 -->
|
||||
<view v-else class="notice-grid">
|
||||
<view
|
||||
v-for="item in noticeEntries"
|
||||
:key="item.key"
|
||||
class="notice-card"
|
||||
hover-class="notice-card-hover"
|
||||
@click="onNoticeTap(item.key)"
|
||||
>
|
||||
<view class="notice-card__icon">
|
||||
<image :src="item.icon" mode="aspectFit"></image>
|
||||
<u-badge
|
||||
size="mini"
|
||||
v-if="item.showBadge"
|
||||
:count="item.num"
|
||||
:is-dot="item.isDot"
|
||||
type="error"
|
||||
:offset="item.num > 0 ? [-4, -4] : [0, 0]"
|
||||
></u-badge>
|
||||
</view>
|
||||
<!-- 描述 -->
|
||||
<view class="info">
|
||||
<view class="infos_title">
|
||||
<text class="infos">产品订单</text>
|
||||
<text class="time">{{ order.time }}</text>
|
||||
</view>
|
||||
<view class="preview" v-if="order.num>0">
|
||||
您有{{ order.num }}条未读信息
|
||||
</view>
|
||||
<view class="preview" v-if="order.num==undefined">
|
||||
暂无新消息
|
||||
</view>
|
||||
<view class="notice-card__body">
|
||||
<text class="notice-card__title">{{ item.title }}</text>
|
||||
<text class="notice-card__preview">{{ item.preview }}</text>
|
||||
<text v-if="item.time" class="notice-card__time">{{ item.time }}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="list" @click="goDoctor">
|
||||
<!-- 头像 -->
|
||||
<view class="avator">
|
||||
<view class="img">
|
||||
<image src="https://xiaokang88.oss-cn-hangzhou.aliyuncs.com/xk-client-wx/static/xx/ysxx.png" mode=""></image>
|
||||
</view>
|
||||
<u-badge size="default" v-if="doctor.num>=0" :count="doctor.num" :is-dot="doctor.num==0?true:false"
|
||||
type="error" :offset="doctor.num>0?[-4,-8]:[0,0]"></u-badge>
|
||||
</view>
|
||||
<!-- 描述 -->
|
||||
<view class="info">
|
||||
<view class="infos_title">
|
||||
<text class="infos">医生消息</text>
|
||||
<text class="time">{{ doctor.time }}</text>
|
||||
</view>
|
||||
<view class="preview" v-if="doctor.num>0">
|
||||
您有{{ doctor.num }}条新的消息
|
||||
</view>
|
||||
<view class="preview" v-if="doctor.num==undefined">
|
||||
暂无新消息
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 转诊消息 -->
|
||||
<view class="list" @click="goTransfer">
|
||||
<!-- 头像 -->
|
||||
<view class="avator">
|
||||
<view class="img">
|
||||
<image src="https://xiaokang88.oss-cn-hangzhou.aliyuncs.com/xk-client-wx/static/xx/ysxx.png" mode=""></image>
|
||||
</view>
|
||||
<u-badge size="default" v-if="transfer.num>=0" :count="transfer.num" :is-dot="transfer.num==0?true:false"
|
||||
type="error" :offset="transfer.num>0?[-4,-8]:[0,0]"></u-badge>
|
||||
</view>
|
||||
<!-- 描述 -->
|
||||
<view class="info">
|
||||
<view class="infos_title">
|
||||
<text class="infos">转诊消息</text>
|
||||
<text class="time">{{ transfer.time }}</text>
|
||||
</view>
|
||||
<view class="preview" v-if="transfer.num>0">
|
||||
您有{{ transfer.num }}条转诊消息待处理
|
||||
</view>
|
||||
<view class="preview" v-if="transfer.num==undefined || transfer.num==0">
|
||||
暂无转诊消息
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
</view>
|
||||
|
||||
<!-- 标题 - 在线咨询 -->
|
||||
<view v-if="checkDev('open-im') && onlineConsultationList.length > 0" class="title">
|
||||
@@ -183,6 +119,9 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
/**
|
||||
* 患者端消息首页:顶部四入口宫格(系统/订单/医生/转诊)+ 下方 IM 会话列表
|
||||
*/
|
||||
import {
|
||||
getseesionRead
|
||||
} from '../../request/api/api'
|
||||
@@ -214,6 +153,19 @@ export default {
|
||||
chatInitialLoading: true
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
/**
|
||||
* 顶部宫格入口:文案/角标在这里算好,模板禁止方法调用和 ?.
|
||||
*/
|
||||
noticeEntries() {
|
||||
return [
|
||||
this.buildNoticeEntry('system', '系统消息', 'https://xiaokang88.oss-cn-hangzhou.aliyuncs.com/xk-client-wx/static/xx/xt.png', this.system, '条未读信息', '暂无新消息'),
|
||||
this.buildNoticeEntry('order', '产品订单', 'https://xiaokang88.oss-cn-hangzhou.aliyuncs.com/xk-client-wx/static/xx/cp.png', this.order, '条未读信息', '暂无新消息'),
|
||||
this.buildNoticeEntry('doctor', '医生消息', 'https://xiaokang88.oss-cn-hangzhou.aliyuncs.com/xk-client-wx/static/xx/ysxx.png', this.doctor, '条新的消息', '暂无新消息'),
|
||||
this.buildNoticeEntry('transfer', '转诊消息', 'https://xiaokang88.oss-cn-hangzhou.aliyuncs.com/xk-client-wx/static/xx/ysxx.png', this.transfer, '条转诊消息待处理', '暂无转诊消息')
|
||||
]
|
||||
}
|
||||
},
|
||||
onLoad() {
|
||||
// 监听聊天列表更新事件
|
||||
uni.$on('chat-list-update', this.handleChatListUpdate);
|
||||
@@ -225,7 +177,35 @@ export default {
|
||||
},
|
||||
methods: {
|
||||
checkDev,
|
||||
|
||||
/**
|
||||
* 组装单条宫格入口(未读数未回来时不展示角标,避免闪 0)
|
||||
*/
|
||||
buildNoticeEntry(key, title, icon, raw, unreadSuffix, emptyText) {
|
||||
const num = raw && raw.num
|
||||
const hasNum = num !== undefined && num !== null
|
||||
const unread = Number(num) || 0
|
||||
let preview = emptyText
|
||||
if (hasNum && unread > 0) {
|
||||
preview = '您有' + unread + unreadSuffix
|
||||
}
|
||||
return {
|
||||
key,
|
||||
title,
|
||||
icon,
|
||||
num: unread,
|
||||
time: (raw && raw.time) || '',
|
||||
preview,
|
||||
showBadge: hasNum,
|
||||
isDot: unread === 0
|
||||
}
|
||||
},
|
||||
/** 宫格点击:按 key 走原来的四个跳转 */
|
||||
onNoticeTap(key) {
|
||||
if (key === 'system') this.goSystem()
|
||||
else if (key === 'order') this.goOrder()
|
||||
else if (key === 'doctor') this.goDoctor()
|
||||
else if (key === 'transfer') this.goTransfer()
|
||||
},
|
||||
/**
|
||||
* 处理聊天列表更新事件
|
||||
* 收到新消息时自动刷新列表
|
||||
@@ -437,6 +417,108 @@ export default {
|
||||
}
|
||||
}
|
||||
|
||||
/* 顶部四入口:一行两列,卡片用同色细边框+微光(不用左侧色条) */
|
||||
.notice-grid {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
padding: 0 24rpx 8rpx;
|
||||
}
|
||||
|
||||
.notice-card {
|
||||
width: 343rpx;
|
||||
margin: 0 16rpx 16rpx 0;
|
||||
padding: 24rpx 20rpx;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: flex-start;
|
||||
background: #fff;
|
||||
border-radius: 20rpx;
|
||||
border: 1px solid rgba(83, 109, 254, 0.28);
|
||||
box-shadow: 0 0 6px rgba(83, 109, 254, 0.16);
|
||||
}
|
||||
|
||||
.notice-card:nth-child(2n) {
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
.notice-card-hover {
|
||||
opacity: 0.88;
|
||||
}
|
||||
|
||||
.notice-card__icon {
|
||||
position: relative;
|
||||
flex-shrink: 0;
|
||||
width: 72rpx;
|
||||
height: 72rpx;
|
||||
border-radius: 50%;
|
||||
background: #E6EAFF;
|
||||
overflow: visible;
|
||||
|
||||
image {
|
||||
width: 72rpx;
|
||||
height: 72rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.notice-card__body {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
margin-left: 16rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.notice-card__title {
|
||||
font-size: 28rpx;
|
||||
font-weight: 600;
|
||||
color: #1E293B;
|
||||
line-height: 40rpx;
|
||||
}
|
||||
|
||||
.notice-card__preview {
|
||||
margin-top: 4rpx;
|
||||
font-size: 22rpx;
|
||||
color: #64748B;
|
||||
line-height: 32rpx;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.notice-card__time {
|
||||
margin-top: 4rpx;
|
||||
font-size: 20rpx;
|
||||
color: #94A3B8;
|
||||
line-height: 28rpx;
|
||||
}
|
||||
|
||||
.notice-card--sk {
|
||||
min-height: 140rpx;
|
||||
}
|
||||
|
||||
.notice-sk-icon {
|
||||
width: 72rpx;
|
||||
height: 72rpx;
|
||||
border-radius: 50%;
|
||||
background: #EEF2FF;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.notice-sk-line {
|
||||
height: 20rpx;
|
||||
margin-top: 12rpx;
|
||||
border-radius: 8rpx;
|
||||
background: #F1F5F9;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.notice-sk-line--title {
|
||||
height: 28rpx;
|
||||
width: 140rpx;
|
||||
flex: none;
|
||||
}
|
||||
|
||||
.list {
|
||||
width: 750rpx;
|
||||
display: flex;
|
||||
|
||||
@@ -532,12 +532,6 @@ export async function confirmAccept(params) {
|
||||
let data = await http('/xkApi/product-order/receive', params)
|
||||
return normalizeXkApiResponse(data)
|
||||
}
|
||||
//清空购物车
|
||||
export async function clearAll(params) {
|
||||
let data = await http('/newApi/cart/clearAll', params)
|
||||
return data
|
||||
}
|
||||
|
||||
export async function getVersion(params) {
|
||||
let data = await http('/v1/other/xcx-version?store_id=11001', params)
|
||||
return data
|
||||
|
||||
@@ -26,3 +26,11 @@ export async function getCartCountsApi(params) {
|
||||
export async function saveCartApi(params) {
|
||||
return await post(`${prefix}/save-cart`, params, 3)
|
||||
}
|
||||
/**
|
||||
* 清空购物车(当前用户+门店维度,迁自老 Yii /v1/cart/clear-all) xk-api POST /cart/clear-cart
|
||||
* @param params { store_id: number }
|
||||
* @returns {Promise<*>}
|
||||
*/
|
||||
export async function clearCartApi(params) {
|
||||
return await post(`${prefix}/clear-cart`, params, 3)
|
||||
}
|
||||
|
||||
@@ -40,6 +40,20 @@ export async function getHomeTopProductsApi(params) {
|
||||
export async function getHomeZonesApi(params) {
|
||||
return await get('/product/home-zones', params, 3)
|
||||
}
|
||||
/**
|
||||
* 首页展示样式(金刚区布局 + 订单提醒样式)
|
||||
* xk-api GET /product/home-display-config;游客态 request.js 会改写到 guest
|
||||
*/
|
||||
export async function getHomeDisplayConfigApi() {
|
||||
return await get('/product/home-display-config', {}, 3)
|
||||
}
|
||||
/**
|
||||
* 首页订单提醒(待支付挂号/商品、已发货、待确认收货)
|
||||
* xk-api GET /product-order/home-remind;取值 unwrapXkApi → code / result / message
|
||||
*/
|
||||
export async function getHomeOrderRemindApi() {
|
||||
return await get('/product-order/home-remind', {}, 3)
|
||||
}
|
||||
/**
|
||||
* 更新商品介绍图
|
||||
* @param params
|
||||
|
||||
@@ -10,19 +10,6 @@ import { unwrapXkApi } from '@/utils/api-response.js'
|
||||
* 老签名不动,避免改动全部调用方的传参结构;新增接口请用 post(url, params, 3) 新封装。
|
||||
*/
|
||||
|
||||
/**
|
||||
* 存量页面兼容:把 xk-api 的 code/result 抹成旧版 errcode/data
|
||||
* @deprecated 仅供 registePay 的存量调用方(读 res.data.errcode/data)过渡使用,
|
||||
* 新代码一律直接按 code/result 取值或用 unwrapXkApi,禁止再新增本函数的调用
|
||||
*/
|
||||
function normalizeXkApiResponse(res) {
|
||||
if (res && res.data && (res.data.code === 0 || res.data.code === '0')) {
|
||||
res.data.errcode = 0;
|
||||
res.data.data = res.data.result;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取挂号记录列表 xk-api POST /register/list
|
||||
* @param params { patient_id: number, store_id: number, page: number }
|
||||
@@ -95,11 +82,12 @@ export async function registeInfo(params) {
|
||||
|
||||
/**
|
||||
* 挂号支付 xk-api POST /register/pay(易票联)
|
||||
* 存量调用方读 errcode/data,这里保留 normalize 过渡;0 元单返回 data.is_paid=1
|
||||
* 返回原生 xk-api 形态:res.data.code == 0 → res.data.result;0 元单 result.is_paid=1
|
||||
* (原 normalize 成 errcode/data 的兼容层已删除,调用方一律按 code/result/message 取值)
|
||||
*/
|
||||
export async function registePay(params) {
|
||||
let data = await http('/xkApi/register/pay', params)
|
||||
return normalizeXkApiResponse(data)
|
||||
return data
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -118,3 +106,19 @@ export async function registeCancle(params) {
|
||||
let data = await http('/xkApi/register/refund', params)
|
||||
return data
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改预约时间(患者本人改期) xk-api POST /register/reschedule
|
||||
* 参数 { register_id, visit_date: 'Y-m-d', slot_id };就诊当天后端会拦截(提示联系医生/诊所)
|
||||
*/
|
||||
export async function registerReschedule(params = {}) {
|
||||
return await post('/register/reschedule', params, 3)
|
||||
}
|
||||
|
||||
/**
|
||||
* 挂号改期记录 xk-api POST /register/reschedule-logs
|
||||
* 返回 result 数组:谁在什么时候把预约从哪个时段改到哪个时段(详情页溯源展示)
|
||||
*/
|
||||
export async function registerRescheduleLogs(params = {}) {
|
||||
return await post('/register/reschedule-logs', params, 3)
|
||||
}
|
||||
|
||||
@@ -135,6 +135,9 @@ function request(url, params, method = 0) {
|
||||
} else if (url.indexOf('/xkApi/product/home-zones') !== -1) {
|
||||
url = url.replace('/xkApi/product/home-zones', '/guest/guest-product/home-zones');
|
||||
baseURL = envUrls.xkApi;
|
||||
} else if (url.indexOf('/xkApi/product/home-display-config') !== -1) {
|
||||
url = url.replace('/xkApi/product/home-display-config', '/guest/guest-product/home-display-config');
|
||||
baseURL = envUrls.xkApi;
|
||||
} else if (url.indexOf('/xkApi/platform/config') !== -1) {
|
||||
url = url.replace('/xkApi/platform/config', '/guest/guest-platform/config');
|
||||
baseURL = envUrls.xkApi;
|
||||
|
||||
@@ -1135,7 +1135,7 @@ export default {
|
||||
},
|
||||
|
||||
getStatusText(status) { const map = { 0: '待审核', 1: '已审核', 2: '未通过' }; return map[status] || '未知状态'; },
|
||||
getRegisterStatusText(status) { const map = { 0: '待就诊', 1: '已缴费', 2: '已就诊', 3: '已取消', 4: '已退费' }; return map[status] || '未知状态'; },
|
||||
getRegisterStatusText(status) { const map = { 0: '待支付', 1: '待接诊', 2: '接诊中', 3: '已结束', 4: '已取消', 5: '待评价', 6: '已评价', 7: '已拒诊' }; 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-info?id=${id}&type=1` }); },
|
||||
|
||||
@@ -409,7 +409,7 @@ export default {
|
||||
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] || '状态未知'; },
|
||||
getRegisterStatusText(status) { const map = { 0: '待支付', 1: '待接诊', 2: '接诊中', 3: '已结束', 4: '已取消', 5: '待评价', 6: '已评价', 7: '已拒诊' }; return map[status] || '状态未知'; },
|
||||
// 处理转诊同意
|
||||
handleTransferAgree(messageData) {
|
||||
if (!messageData || !messageData.transfer_id) {
|
||||
|
||||
@@ -28,8 +28,8 @@
|
||||
<view class="list" v-for="(item,index) in infoList" :key="item.id">
|
||||
<view class="li_title">
|
||||
<text>{{item.created_at}}</text>
|
||||
<text class="text" v-if="item.status<4">{{ statusText(item.status) }}</text>
|
||||
<text class="txt" v-if="item.status>=4">{{ statusText(item.status) }}</text>
|
||||
<text class="text" v-if="item.is_cancel!=1 && item.status<4">{{ statusText(item) }}</text>
|
||||
<text class="txt" v-if="item.is_cancel==1 || item.status>=4">{{ statusText(item) }}</text>
|
||||
</view>
|
||||
<view class="info">
|
||||
<view class="list_name">患者姓名</view>
|
||||
@@ -86,7 +86,10 @@
|
||||
components: { TransferPrescriptionCard },
|
||||
mixins: [patientTabList],
|
||||
methods: {
|
||||
statusText(status) {
|
||||
statusText(item) {
|
||||
// 取消优先于完结:未支付取消以前可能只写 is_cancel 或只写 status=4,避免误显示「已结束」
|
||||
if (item && item.is_cancel == 1 && item.status != 7) return '已取消'
|
||||
const status = item && item.status
|
||||
if (status == 0) return '待支付'
|
||||
if (status == 1) return '待接诊'
|
||||
if (status == 2) return '接诊中'
|
||||
|
||||
@@ -187,8 +187,7 @@
|
||||
</view>
|
||||
<view class="info">
|
||||
<text>发药人</text>
|
||||
<!-- <text class="name">{{rpList.name || ' '}}</text> -->
|
||||
<image :src="checkImageUrl(data.Pharmacist_sign_image)" mode="aspectFit"></image>
|
||||
<image v-if="data.sender_sign_image" :src="checkImageUrl(data.sender_sign_image)" mode="aspectFit"></image>
|
||||
</view>
|
||||
<view class="info">
|
||||
<text>核对人</text>
|
||||
@@ -196,7 +195,7 @@
|
||||
</view>
|
||||
<view class="info">
|
||||
<text>调配人</text>
|
||||
<image :src="checkImageUrl(data.Pharmacist_sign_image)" mode="aspectFit"></image>
|
||||
<image v-if="data.dispenser_sign_image" :src="checkImageUrl(data.dispenser_sign_image)" mode="aspectFit"></image>
|
||||
</view>
|
||||
<!-- <view class="info">
|
||||
<text>复审药师</text>
|
||||
|
||||
@@ -1,11 +1,15 @@
|
||||
<template>
|
||||
<view class="container safe-area-inset-bottom" style="padding-bottom: 100rpx">
|
||||
<!-- #ifdef MP-WEIXIN -->
|
||||
<!-- 仅作返回拦截:空 page-container 默认是底部白底浮层,会把预约信息整块盖住只剩步骤条和底栏 -->
|
||||
<!-- pageGuard 与 show 拆开:先 show=false 播完离场再卸节点,避免原生滚动锁残留 -->
|
||||
<page-container
|
||||
v-if="pageBackGuardShow"
|
||||
v-if="pageGuard"
|
||||
:show="pageBackGuardShow"
|
||||
:overlay="false"
|
||||
custom-style="height:1px;width:1px;overflow:hidden;opacity:0;background:transparent;"
|
||||
@leave="onPageBackGuardLeave"
|
||||
@afterleave="releasePageGuard"
|
||||
/>
|
||||
<!-- #endif -->
|
||||
<!-- 预约信息 -->
|
||||
@@ -161,7 +165,6 @@
|
||||
} from '@/request/api/register.js';
|
||||
import { createRoomByDoctorIdApi, sendToUserApi } from '@/request/api/im';
|
||||
import { checkDev } from '@/utils/utils';
|
||||
import { genOrderApi } from '@/request/api/order';
|
||||
import request from '@/request/api/request';
|
||||
import {
|
||||
CLINIC_POST_REGISTER_STORAGE_KEY,
|
||||
@@ -207,6 +210,9 @@
|
||||
_urlDoctorId: '',
|
||||
_getInfoPromise: null,
|
||||
pageBackGuardShow: false,
|
||||
// 原生容器挂载开关:关闭时先关 show,afterleave/超时后再卸
|
||||
pageGuard: false,
|
||||
releaseTimer: null,
|
||||
_suppressPageBackGuardLeave: false,
|
||||
};
|
||||
},
|
||||
@@ -246,6 +252,9 @@
|
||||
const uid = uni.getStorageSync('user_id');
|
||||
this.currentUserId = 'user-' + (uid !== '' && uid !== undefined && uid !== null ? uid : '2512');
|
||||
},
|
||||
beforeDestroy() {
|
||||
this.clearReleaseTimer();
|
||||
},
|
||||
methods: {
|
||||
bootstrapFromProps() {
|
||||
this.register_id = this.registerId;
|
||||
@@ -310,9 +319,34 @@
|
||||
setPageBackGuardShow(show, { suppressLeave = false } = {}) {
|
||||
// #ifdef MP-WEIXIN
|
||||
if (suppressLeave) this._suppressPageBackGuardLeave = true;
|
||||
this.pageBackGuardShow = !!show;
|
||||
if (show) {
|
||||
this.pageGuard = true;
|
||||
this.$nextTick(() => {
|
||||
this.pageBackGuardShow = true;
|
||||
});
|
||||
} else {
|
||||
this.pageBackGuardShow = false;
|
||||
this.scheduleReleaseGuard();
|
||||
}
|
||||
// #endif
|
||||
},
|
||||
releasePageGuard() {
|
||||
this.clearReleaseTimer();
|
||||
this.pageGuard = false;
|
||||
},
|
||||
scheduleReleaseGuard() {
|
||||
this.clearReleaseTimer();
|
||||
this.releaseTimer = setTimeout(() => {
|
||||
this.pageGuard = false;
|
||||
this.releaseTimer = null;
|
||||
}, 350);
|
||||
},
|
||||
clearReleaseTimer() {
|
||||
if (this.releaseTimer) {
|
||||
clearTimeout(this.releaseTimer);
|
||||
this.releaseTimer = null;
|
||||
}
|
||||
},
|
||||
syncPageBackGuard() {
|
||||
// #ifdef MP-WEIXIN
|
||||
this.$nextTick(() => {
|
||||
@@ -605,15 +639,9 @@
|
||||
that.disableBackGuardBeforeLeave();
|
||||
uni.navigateTo({ url: chatUrl });
|
||||
};
|
||||
genOrderApi({
|
||||
register_id: that.register_id,
|
||||
register_info: typeof that.rInfo === 'string' ? that.rInfo : JSON.stringify(that.rInfo),
|
||||
}).then(() => {
|
||||
goAfterGenOrder();
|
||||
}).catch((error) => {
|
||||
console.error('生成订单失败:', error);
|
||||
goAfterGenOrder();
|
||||
});
|
||||
// 历史遗留的 genOrderApi 调用已删除:genOrder 是购药下单专用接口,
|
||||
// 传挂号参数必然失败、结果又被 catch 吞掉照样跳转,纯属无效请求,直接进入复诊后续流程
|
||||
goAfterGenOrder();
|
||||
} catch (error) {
|
||||
uni.hideLoading();
|
||||
console.error('处理在线复诊流程失败:', error);
|
||||
@@ -636,11 +664,12 @@
|
||||
}).then(async (res) => {
|
||||
uni.showLoading({ title: '加载中' });
|
||||
|
||||
if (!(res.data && (res.data.errcode == 0 || res.data.errcode === '0'))) {
|
||||
// registePay 为 xk-api:按 code/result/message 取值
|
||||
if (!(res.data && (res.data.code == 0 || res.data.code === '0'))) {
|
||||
that.flag = true;
|
||||
uni.hideLoading();
|
||||
that.$refs.uToast && that.$refs.uToast.show({
|
||||
title: (res.data && (res.data.message || res.data.msg)) || '获取支付参数失败',
|
||||
title: (res.data && res.data.message) || '获取支付参数失败',
|
||||
type: 'default',
|
||||
icon: false
|
||||
});
|
||||
@@ -665,7 +694,7 @@
|
||||
});
|
||||
}
|
||||
|
||||
if (res.data.data && res.data.data.is_paid == 1) {
|
||||
if (res.data.result && res.data.result.is_paid == 1) {
|
||||
await that.waitForRegisterDetail();
|
||||
if (that.registList && (that.registList.register_type === 2 || that.registList.register_type === 3)) {
|
||||
await that.handleOnlineConsultationAfterPayment();
|
||||
@@ -682,12 +711,12 @@
|
||||
}
|
||||
|
||||
uni.requestPayment({
|
||||
provider: res.data.data.appId,
|
||||
timeStamp: res.data.data.timestamp,
|
||||
nonceStr: res.data.data.nonceStr,
|
||||
package: res.data.data.package,
|
||||
signType: res.data.data.signType,
|
||||
paySign: res.data.data.paySign,
|
||||
provider: res.data.result.appId,
|
||||
timeStamp: res.data.result.timestamp,
|
||||
nonceStr: res.data.result.nonceStr,
|
||||
package: res.data.result.package,
|
||||
signType: res.data.result.signType,
|
||||
paySign: res.data.result.paySign,
|
||||
success: async () => {
|
||||
await that.waitForRegisterDetail();
|
||||
that.flag = false;
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
<MessageNotification />
|
||||
<u-navbar class="navbar" :is-back="true" title="挂号详情" :custom-back="customBack" title-color="#000">
|
||||
</u-navbar>
|
||||
<!-- 已预约 -->
|
||||
<view class="appoined" v-if="registList.is_cancel==0 && registList.status>0">
|
||||
<!-- 已预约:排除已取消(4)/已拒诊(7),避免取消后仍显示「已挂号成功」 -->
|
||||
<view class="appoined" v-if="registList.is_cancel==0 && registList.status>0 && registList.status!=4 && registList.status!=7">
|
||||
<view class="appoin">
|
||||
<text class="iconfont icon-ys-xuanzhong"></text>
|
||||
已挂号成功
|
||||
@@ -14,8 +14,8 @@
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 已取消 -->
|
||||
<view class="appoined" v-if="registList.is_cancel==1&®istList.status==4">
|
||||
<!-- 已取消:status=4 或 is_cancel=1(未支付取消以前只软删不写 is_cancel,这里按状态兜底) -->
|
||||
<view class="appoined" v-if="registList.status==4 || (registList.is_cancel==1 && registList.status!=7)">
|
||||
<view class="unappoin">
|
||||
<text class="iconfont icon-xianshi_quxiao"></text>
|
||||
已取消成功
|
||||
@@ -107,6 +107,17 @@
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 改期记录:有过改期的单展示轨迹(谁在什么时候改到什么时段),便于患者对账溯源 -->
|
||||
<view class="title" v-if="rescheduleLogList.length > 0">
|
||||
改期记录
|
||||
</view>
|
||||
<view class="card log-card" v-if="rescheduleLogList.length > 0">
|
||||
<view class="log-item" v-for="log in rescheduleLogList" :key="log.id">
|
||||
<view class="log-line">{{log.old_visit_date}} {{log.old_slot_name}} → {{log.new_visit_date}} {{log.new_slot_name}}</view>
|
||||
<view class="log-meta">{{log.operator_label}}{{log.operator_name ? '·' + log.operator_name : ''}} {{log.created_at}}</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 就诊人 -->
|
||||
<view class="title">
|
||||
就诊人
|
||||
@@ -159,8 +170,60 @@
|
||||
<view class="isbtn" @click="opened" v-if="registList.is_cancel==0 && registList.status==0">
|
||||
去支付
|
||||
</view>
|
||||
<!-- 修改时间:仅已支付待接诊且未到就诊日可见(就诊当天不可自行改期,后端双重拦截) -->
|
||||
<view class="isbtn" @click="openReschedule" v-if="canReschedule">
|
||||
修改时间
|
||||
</view>
|
||||
<view class="btn" @click="goHome" v-if="registList.status>=1">返回首页</view>
|
||||
</view>
|
||||
|
||||
<!-- 改期抽屉:page-container 防误退(微信手势返回先关抽屉),日历+时段选择复用挂号日历接口 -->
|
||||
<page-container v-if="rescheduleGuard" :show="rescheduleShow" position="bottom" round overlay
|
||||
custom-style="height:76%;" @clickoverlay="closeReschedule" @afterleave="releaseRescheduleGuard">
|
||||
<view class="reschedule-popup">
|
||||
<view class="popup-header">
|
||||
<text class="popup-title">修改预约时间</text>
|
||||
<text class="popup-close" @click="closeReschedule">×</text>
|
||||
</view>
|
||||
<view class="popup-current" v-if="appointmentText">当前预约:{{appointmentText}}</view>
|
||||
<scroll-view scroll-y class="popup-body">
|
||||
<view v-if="calendarLoading" class="popup-loading">号源加载中...</view>
|
||||
<block v-else>
|
||||
<view v-if="calendarDays.length > 0">
|
||||
<scroll-view scroll-x class="day-scroll" :show-scrollbar="false">
|
||||
<view class="day-strip">
|
||||
<view class="day-item" v-for="(day, idx) in calendarDays" :key="day.date"
|
||||
:class="{ active: idx === selectedDayIndex, disabled: !day.is_work || day.is_full }"
|
||||
@click="selectDay(idx)">
|
||||
<view class="day-week">{{day.week}}</view>
|
||||
<view class="day-date">{{day.date_text}}</view>
|
||||
<view class="day-state" :class="{ rest: !day.is_work, full: day.is_work && day.is_full }">{{day.state_text}}</view>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
<view class="slot-list" v-if="selectedDay && selectedDay.is_work && selectedDay.slots.length > 1">
|
||||
<view class="slot-item" v-for="slot in selectedDay.slots" :key="slot.slot_id"
|
||||
:class="{ active: slot.slot_id === selectedSlotId, disabled: slot.is_full || slot.is_expired }"
|
||||
@click="selectSlot(slot)">
|
||||
<view class="slot-name">{{slot.slot_name}}</view>
|
||||
<view class="slot-time">{{slot.start_time}}-{{slot.end_time}}</view>
|
||||
<view class="slot-left" :class="{ full: slot.is_full || slot.is_expired }">{{slot.state_text}}</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="rest-tip" v-if="selectedDay && !selectedDay.is_work">该日医生休诊,请选择其他日期</view>
|
||||
</view>
|
||||
<view class="rest-tip" v-else>该医生暂无可约号源</view>
|
||||
</block>
|
||||
<view class="reschedule-tip">温馨提示:就诊当天不可自行改期,如需当天调整请联系医生或诊所</view>
|
||||
</scroll-view>
|
||||
<view class="popup-footer">
|
||||
<view class="popup-selected" v-if="rescheduleSlotLabel">改期至:{{rescheduleSlotLabel}}</view>
|
||||
<view class="popup-btn" :class="{ disabled: !canConfirmReschedule || rescheduleSubmitting }" @click="confirmReschedule">
|
||||
{{rescheduleSubmitting ? '提交中...' : '确认修改'}}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</page-container>
|
||||
<!-- 消息提醒中 -->
|
||||
<u-toast ref="uToast" />
|
||||
</view>
|
||||
@@ -176,7 +239,10 @@
|
||||
registeCancle,
|
||||
registeInfo,
|
||||
registePay,
|
||||
registeUnpay
|
||||
registeUnpay,
|
||||
registerCalendar,
|
||||
registerReschedule,
|
||||
registerRescheduleLogs
|
||||
} from '../../request/api/register.js';
|
||||
export default {
|
||||
data() {
|
||||
@@ -187,6 +253,18 @@
|
||||
register_id: uni.getStorageSync('register_id'),
|
||||
registList: [],
|
||||
type: 0,
|
||||
// 改期记录(xk-api reschedule-logs,空数组不渲染区块)
|
||||
rescheduleLogList: [],
|
||||
// 改期抽屉状态:pageGuard 与 show 拆开,关抽屉先离场再卸
|
||||
rescheduleShow: false,
|
||||
rescheduleGuard: false,
|
||||
rescheduleReleaseTimer: null,
|
||||
rescheduleSubmitting: false,
|
||||
calendarLoading: false,
|
||||
// 号源日历(与医生详情页同一接口/同一预处理逻辑)
|
||||
calendarDays: [],
|
||||
selectedDayIndex: 0,
|
||||
selectedSlotId: -1,
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
@@ -200,6 +278,58 @@
|
||||
}
|
||||
return text;
|
||||
},
|
||||
/** 今天日期字符串 Y-m-d(本地时区,用于「未到就诊日」判断,ISO 字符串可直接比大小) */
|
||||
todayStr() {
|
||||
const d = new Date();
|
||||
const m = d.getMonth() + 1;
|
||||
const day = d.getDate();
|
||||
return d.getFullYear() + '-' + (m < 10 ? '0' + m : m) + '-' + (day < 10 ? '0' + day : day);
|
||||
},
|
||||
/**
|
||||
* 是否展示「修改时间」:已支付 + 待接诊 + 未取消 + 有占号信息 + 未到就诊日。
|
||||
* 就诊当天入口直接隐藏(当天号源已进入医生叫号安排,需联系医生/诊所调整),后端也会拦截
|
||||
*/
|
||||
canReschedule() {
|
||||
const r = this.registList || {};
|
||||
const appt = r.appointment;
|
||||
if (!appt || !appt.visit_date) return false;
|
||||
if (r.is_cancel != 0 || r.status != 1 || r.is_pay != 1) return false;
|
||||
return appt.visit_date > this.todayStr;
|
||||
},
|
||||
/** 当前选中的日期对象 */
|
||||
selectedDay() {
|
||||
return this.calendarDays[this.selectedDayIndex] || null;
|
||||
},
|
||||
/** 当前选中的时段对象 */
|
||||
selectedSlot() {
|
||||
if (!this.selectedDay || this.selectedSlotId < 0) return null;
|
||||
const list = this.selectedDay.slots || [];
|
||||
for (let i = 0; i < list.length; i++) {
|
||||
if (list[i].slot_id === this.selectedSlotId) return list[i];
|
||||
}
|
||||
return null;
|
||||
},
|
||||
/** 改期目标文案(底部确认条展示) */
|
||||
rescheduleSlotLabel() {
|
||||
if (!this.selectedDay || !this.selectedSlot) return '';
|
||||
let label = this.selectedDay.date + ' ' + (this.selectedSlot.slot_name || '');
|
||||
const s = this.selectedSlot;
|
||||
if (s.start_time && s.end_time && !(s.start_time === '00:00' && s.end_time === '23:59')) {
|
||||
label += ' ' + s.start_time + '-' + s.end_time;
|
||||
}
|
||||
return label;
|
||||
},
|
||||
/** 是否可提交:选中了出诊日的可约时段 */
|
||||
canConfirmReschedule() {
|
||||
return !!(this.selectedDay && this.selectedDay.is_work && this.selectedSlot
|
||||
&& !this.selectedSlot.is_full && !this.selectedSlot.is_expired);
|
||||
},
|
||||
},
|
||||
onUnload() {
|
||||
if (this.rescheduleReleaseTimer) {
|
||||
clearTimeout(this.rescheduleReleaseTimer)
|
||||
this.rescheduleReleaseTimer = null
|
||||
}
|
||||
},
|
||||
onLoad(e) {
|
||||
this.register_id = e.id
|
||||
@@ -283,17 +413,18 @@
|
||||
title: "加载中"
|
||||
});
|
||||
|
||||
if (!(res.data && (res.data.errcode == 0 || res.data.errcode === '0'))) {
|
||||
// registePay 为 xk-api:按 code/result/message 取值
|
||||
if (!(res.data && (res.data.code == 0 || res.data.code === '0'))) {
|
||||
uni.hideLoading();
|
||||
that.$refs.uToast.show({
|
||||
title: (res.data && (res.data.message || res.data.msg)) || '支付失败',
|
||||
title: (res.data && res.data.message) || '支付失败',
|
||||
type: 'default',
|
||||
icon: false
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (res.data.data.is_paid == 1) {
|
||||
if (res.data.result.is_paid == 1) {
|
||||
uni.hideLoading();
|
||||
setTimeout(() => {
|
||||
uni.showToast({
|
||||
@@ -310,12 +441,12 @@
|
||||
}
|
||||
|
||||
uni.requestPayment({
|
||||
provider: res.data.data.appId,
|
||||
timeStamp: res.data.data.timestamp,
|
||||
nonceStr: res.data.data.nonceStr,
|
||||
package: res.data.data.package,
|
||||
signType: res.data.data.signType,
|
||||
paySign: res.data.data.paySign,
|
||||
provider: res.data.result.appId,
|
||||
timeStamp: res.data.result.timestamp,
|
||||
nonceStr: res.data.result.nonceStr,
|
||||
package: res.data.result.package,
|
||||
signType: res.data.result.signType,
|
||||
paySign: res.data.result.paySign,
|
||||
success: () => {
|
||||
uni.hideLoading();
|
||||
setTimeout(() => {
|
||||
@@ -369,10 +500,168 @@
|
||||
}).then((res) => {
|
||||
if (res.data.code == 0 && res.data.result) {
|
||||
this.registList = res.data.result
|
||||
this.getRescheduleLogs()
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
// 改期记录(xk-api,没有记录时不渲染区块;失败静默,不影响详情主流程)
|
||||
getRescheduleLogs() {
|
||||
registerRescheduleLogs({
|
||||
register_id: this.register_id
|
||||
}).then((res) => {
|
||||
if (res.data.code == 0 && res.data.result) {
|
||||
this.rescheduleLogList = res.data.result
|
||||
}
|
||||
}).catch(() => {})
|
||||
},
|
||||
|
||||
// 打开改期抽屉并拉取该单医生的号源日历(用挂号单自己的 store_id,跨店单不能用登录门店)
|
||||
openReschedule() {
|
||||
this.rescheduleGuard = true
|
||||
this.rescheduleShow = true
|
||||
this.calendarLoading = true
|
||||
this.calendarDays = []
|
||||
this.selectedSlotId = -1
|
||||
registerCalendar({
|
||||
method: "get",
|
||||
data: {
|
||||
doctor_id: this.registList.service_user_id,
|
||||
store_id: this.registList.store_id || uni.getStorageSync('store_id') || '11001',
|
||||
}
|
||||
}).then((res) => {
|
||||
this.calendarLoading = false
|
||||
if (res.data.code === 0 || res.data.code === '0') {
|
||||
const responseData = res.data.result || {}
|
||||
if (responseData.register_status == 0) {
|
||||
this.$refs.uToast.show({
|
||||
title: '该医生暂未开放挂号',
|
||||
type: 'default',
|
||||
icon: false
|
||||
})
|
||||
return
|
||||
}
|
||||
this.applyCalendar(responseData)
|
||||
}
|
||||
}).catch(() => {
|
||||
this.calendarLoading = false
|
||||
})
|
||||
},
|
||||
// 关闭改期抽屉
|
||||
closeReschedule() {
|
||||
this.rescheduleShow = false
|
||||
this.scheduleRescheduleRelease()
|
||||
},
|
||||
releaseRescheduleGuard() {
|
||||
if (this.rescheduleReleaseTimer) {
|
||||
clearTimeout(this.rescheduleReleaseTimer)
|
||||
this.rescheduleReleaseTimer = null
|
||||
}
|
||||
this.rescheduleGuard = false
|
||||
},
|
||||
scheduleRescheduleRelease() {
|
||||
if (this.rescheduleReleaseTimer) {
|
||||
clearTimeout(this.rescheduleReleaseTimer)
|
||||
}
|
||||
this.rescheduleReleaseTimer = setTimeout(() => {
|
||||
this.rescheduleGuard = false
|
||||
this.rescheduleReleaseTimer = null
|
||||
}, 350)
|
||||
},
|
||||
/**
|
||||
* 预处理日历数据:补充展示文案(MM-DD、余号/约满/休诊/当前),
|
||||
* 文案预计算是因为小程序模板禁止 :class/插值调方法;与医生详情页逻辑保持一致,
|
||||
* 额外把「当前预约时段」标记出来方便用户对照
|
||||
*/
|
||||
applyCalendar(calendar) {
|
||||
const appt = (this.registList && this.registList.appointment) || {}
|
||||
const days = (calendar && calendar.days) || []
|
||||
const processed = days.map((day) => {
|
||||
const dateParts = (day.date || '').split('-')
|
||||
const dateText = dateParts.length === 3 ? dateParts[1] + '-' + dateParts[2] : day.date
|
||||
let stateText = '休诊'
|
||||
if (day.is_work) {
|
||||
stateText = day.is_full ? '约满' : '余' + day.left
|
||||
}
|
||||
const slots = (day.slots || []).map((slot) => {
|
||||
let slotState = '余' + slot.left
|
||||
if (slot.is_expired) slotState = '已过时'
|
||||
else if (slot.is_full) slotState = '约满'
|
||||
if (day.date === appt.visit_date && slot.slot_id === appt.slot_id) slotState = '当前'
|
||||
return Object.assign({}, slot, { state_text: slotState })
|
||||
})
|
||||
return Object.assign({}, day, { date_text: dateText, state_text: stateText, slots: slots })
|
||||
})
|
||||
this.calendarDays = processed
|
||||
// 默认选第一个可约日期(出诊且未约满),都不可约时停在今天
|
||||
let idx = 0
|
||||
for (let i = 0; i < processed.length; i++) {
|
||||
if (processed[i].is_work && !processed[i].is_full) {
|
||||
idx = i
|
||||
break
|
||||
}
|
||||
}
|
||||
this.selectedDayIndex = idx
|
||||
this.autoSelectSlot()
|
||||
},
|
||||
// 选择改期日期:切换后默认选中该日第一个可约时段
|
||||
selectDay(idx) {
|
||||
this.selectedDayIndex = idx
|
||||
this.autoSelectSlot()
|
||||
},
|
||||
// 选择时段:约满/已过时的不可选
|
||||
selectSlot(slot) {
|
||||
if (slot.is_full || slot.is_expired) return
|
||||
this.selectedSlotId = slot.slot_id
|
||||
},
|
||||
// 自动选中当日第一个可约时段(全天单时段直接选中)
|
||||
autoSelectSlot() {
|
||||
this.selectedSlotId = -1
|
||||
const day = this.calendarDays[this.selectedDayIndex]
|
||||
if (!day || !day.is_work) return
|
||||
const list = day.slots || []
|
||||
for (let i = 0; i < list.length; i++) {
|
||||
if (!list[i].is_full && !list[i].is_expired) {
|
||||
this.selectedSlotId = list[i].slot_id
|
||||
return
|
||||
}
|
||||
}
|
||||
},
|
||||
// 提交改期:成功后刷新详情与改期记录(新时间即时回显)
|
||||
confirmReschedule() {
|
||||
if (!this.canConfirmReschedule || this.rescheduleSubmitting) return
|
||||
this.rescheduleSubmitting = true
|
||||
registerReschedule({
|
||||
register_id: this.register_id,
|
||||
visit_date: this.selectedDay.date,
|
||||
slot_id: this.selectedSlotId,
|
||||
}).then((res) => {
|
||||
this.rescheduleSubmitting = false
|
||||
if (res.data.code == 0) {
|
||||
this.closeReschedule()
|
||||
uni.showToast({
|
||||
title: '改期成功',
|
||||
duration: 1500,
|
||||
icon: 'success'
|
||||
})
|
||||
this.getInfo()
|
||||
} else {
|
||||
this.$refs.uToast.show({
|
||||
title: res.data.message || '改期失败',
|
||||
type: 'default',
|
||||
icon: false
|
||||
})
|
||||
}
|
||||
}).catch(() => {
|
||||
this.rescheduleSubmitting = false
|
||||
this.$refs.uToast.show({
|
||||
title: '改期失败,请稍后重试',
|
||||
type: 'default',
|
||||
icon: false
|
||||
})
|
||||
})
|
||||
},
|
||||
|
||||
},
|
||||
mounted() {
|
||||
|
||||
@@ -540,7 +829,7 @@
|
||||
|
||||
.isbtn {
|
||||
text-align: center;
|
||||
width: 328rpx;
|
||||
flex: 1;
|
||||
height: 86rpx;
|
||||
line-height: 86rpx;
|
||||
font-size: 32rpx;
|
||||
@@ -577,5 +866,234 @@
|
||||
font-family: PingFang SC-Medium, PingFang SC;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
// 改期记录卡片:轨迹行 + 操作人/时间(次要信息灰字)
|
||||
.log-card {
|
||||
.log-item {
|
||||
padding: 20rpx 0;
|
||||
border-bottom: 2rpx solid #F1F5F9;
|
||||
|
||||
&:first-child {
|
||||
padding-top: 0;
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
border-bottom: none;
|
||||
padding-bottom: 0;
|
||||
}
|
||||
|
||||
.log-line {
|
||||
font-size: 28rpx;
|
||||
font-weight: 600;
|
||||
color: #1E293B;
|
||||
line-height: 40rpx;
|
||||
}
|
||||
|
||||
.log-meta {
|
||||
margin-top: 8rpx;
|
||||
font-size: 24rpx;
|
||||
color: #94A3B8;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 改期抽屉(page-container 内容区):头部 + 当前预约 + 日历/时段 + 底部确认
|
||||
.reschedule-popup {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
background: #FFFFFF;
|
||||
border-radius: 32rpx 32rpx 0 0;
|
||||
overflow: hidden;
|
||||
|
||||
.popup-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 32rpx 32rpx 16rpx;
|
||||
|
||||
.popup-title {
|
||||
font-size: 34rpx;
|
||||
font-weight: 600;
|
||||
color: #1E293B;
|
||||
}
|
||||
|
||||
.popup-close {
|
||||
font-size: 48rpx;
|
||||
line-height: 48rpx;
|
||||
color: #94A3B8;
|
||||
padding: 0 8rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.popup-current {
|
||||
margin: 0 32rpx 8rpx;
|
||||
font-size: 26rpx;
|
||||
color: #64748B;
|
||||
}
|
||||
|
||||
.popup-body {
|
||||
flex: 1;
|
||||
height: 0;
|
||||
padding: 16rpx 32rpx 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.popup-loading {
|
||||
padding: 60rpx 0;
|
||||
text-align: center;
|
||||
font-size: 26rpx;
|
||||
color: #94A3B8;
|
||||
}
|
||||
|
||||
.reschedule-tip {
|
||||
margin: 24rpx 0 32rpx;
|
||||
font-size: 24rpx;
|
||||
color: #94A3B8;
|
||||
line-height: 36rpx;
|
||||
}
|
||||
|
||||
.popup-footer {
|
||||
padding: 16rpx 32rpx;
|
||||
padding-bottom: calc(16rpx + env(safe-area-inset-bottom));
|
||||
border-top: 2rpx solid #F1F5F9;
|
||||
|
||||
.popup-selected {
|
||||
font-size: 26rpx;
|
||||
color: #4175EE;
|
||||
margin-bottom: 12rpx;
|
||||
}
|
||||
|
||||
.popup-btn {
|
||||
height: 86rpx;
|
||||
line-height: 86rpx;
|
||||
text-align: center;
|
||||
font-size: 32rpx;
|
||||
font-weight: 500;
|
||||
color: #FFFFFF;
|
||||
background: #4175EE;
|
||||
border-radius: 64rpx;
|
||||
|
||||
&.disabled {
|
||||
opacity: 0.5;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 日期横条/时段卡片:与医生详情页(doctor-detail)同款交互样式,保持体验一致
|
||||
.day-scroll {
|
||||
width: 100%;
|
||||
white-space: nowrap;
|
||||
|
||||
.day-strip {
|
||||
display: inline-flex;
|
||||
}
|
||||
|
||||
.day-item {
|
||||
display: inline-flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 128rpx;
|
||||
padding: 16rpx 0;
|
||||
margin-right: 16rpx;
|
||||
border-radius: 12rpx;
|
||||
border: 2rpx solid #E2E8F0;
|
||||
background: #FFFFFF;
|
||||
|
||||
.day-week {
|
||||
font-size: 26rpx;
|
||||
font-weight: 600;
|
||||
color: #1E293B;
|
||||
}
|
||||
|
||||
.day-date {
|
||||
font-size: 24rpx;
|
||||
color: #64748B;
|
||||
margin: 6rpx 0;
|
||||
}
|
||||
|
||||
.day-state {
|
||||
font-size: 22rpx;
|
||||
color: #4175EE;
|
||||
|
||||
&.rest {
|
||||
color: #94A3B8;
|
||||
}
|
||||
|
||||
&.full {
|
||||
color: #F44336;
|
||||
}
|
||||
}
|
||||
|
||||
&.active {
|
||||
border-color: #4175EE;
|
||||
background: rgba(65, 117, 238, 0.08);
|
||||
box-shadow: 0 0 6px rgba(65, 117, 238, 0.18);
|
||||
}
|
||||
|
||||
&.disabled {
|
||||
opacity: 0.55;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.slot-list {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
margin-top: 20rpx;
|
||||
|
||||
.slot-item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
width: 208rpx;
|
||||
padding: 14rpx 0;
|
||||
margin: 0 16rpx 16rpx 0;
|
||||
border-radius: 12rpx;
|
||||
border: 2rpx solid #E2E8F0;
|
||||
background: #FFFFFF;
|
||||
|
||||
.slot-name {
|
||||
font-size: 26rpx;
|
||||
font-weight: 600;
|
||||
color: #1E293B;
|
||||
}
|
||||
|
||||
.slot-time {
|
||||
font-size: 22rpx;
|
||||
color: #64748B;
|
||||
margin: 4rpx 0;
|
||||
}
|
||||
|
||||
.slot-left {
|
||||
font-size: 22rpx;
|
||||
color: #4175EE;
|
||||
|
||||
&.full {
|
||||
color: #94A3B8;
|
||||
}
|
||||
}
|
||||
|
||||
&.active {
|
||||
border-color: #4175EE;
|
||||
background: rgba(65, 117, 238, 0.08);
|
||||
box-shadow: 0 0 6px rgba(65, 117, 238, 0.18);
|
||||
}
|
||||
|
||||
&.disabled {
|
||||
opacity: 0.55;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.rest-tip {
|
||||
margin-top: 20rpx;
|
||||
font-size: 26rpx;
|
||||
color: #94A3B8;
|
||||
text-align: center;
|
||||
padding: 24rpx 0;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -76,13 +76,8 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
// 引入API接口
|
||||
import {
|
||||
CartList,
|
||||
addCart,
|
||||
clearAll
|
||||
} from '../../request/api/api'
|
||||
import {getCartListApi, saveCartApi} from "@/request/api/cart";
|
||||
// 引入API接口(购物车域已全量迁 xk-api cart 模块;原 api.js 的 CartList/addCart/clearAll 均为死引用已删)
|
||||
import {getCartListApi, saveCartApi, clearCartApi} from "@/request/api/cart";
|
||||
import {genOrderByCartApi} from "@/request/api/order";
|
||||
|
||||
export default {
|
||||
@@ -253,13 +248,10 @@ export default {
|
||||
})
|
||||
},
|
||||
|
||||
// 调用API清空购物车
|
||||
// 调用API清空购物车(xk-api POST /cart/clear-cart,按当前用户+门店硬删)
|
||||
clearAll() {
|
||||
clearAll({
|
||||
method: "post",
|
||||
data: {
|
||||
store_id: uni.getStorageSync('store_id') || '11001',
|
||||
}
|
||||
clearCartApi({
|
||||
store_id: uni.getStorageSync('store_id') || '11001',
|
||||
}).then((res) => {
|
||||
if (res.data.code == 0) {
|
||||
uni.showToast({
|
||||
|
||||
Reference in New Issue
Block a user