hn-hlw-app/pages/record/consult-record.vue

530 lines
14 KiB
Vue
Raw Normal View History

2026-07-27 11:26:39 +08:00
<template>
<full-page mainStyle="background:#f0f0f0" @reachBottom="loadMore" :class="{ 'elder-mode': elderMode }">
<template #header>
<view v-if="logined" class="status-bar">
<text v-for="(tab, index) in tabs" :key="index"
:class="['tab', { active: activeTab === index, 'tab--elder': elderMode }]" @click="switchTab(index, tab)">
{{ tab }}
</text>
</view>
</template>
<view v-if="logined" style="padding: 20rpx 0">
<empty-data v-if="switchList.length === 0" />
<view v-for="item in switchList" class="card" :class="{ 'card--elder': elderMode }" @click="toRecord(item)">
<view class="card_head info-row" :class="{ 'card_head--elder': elderMode }">
<view class="doctor-info" :class="{ 'doctor-info--elder': elderMode }">
<text>{{ item.doctorName }}</text>
<text class="dept" :class="{ 'dept--elder': elderMode }">{{ item.deptName }}</text>
</view>
<view :style="'color:' + item.color" class="flex-shrink-0" :class="{ 'status-text--elder': elderMode }">{{
item.text }}</view>
</view>
<view class="card_body" :class="{ 'card_body--elder': elderMode }">
<view>
<text class="label" :class="{ 'label--elder': elderMode }">线下确诊疾病</text>
<text :class="{ 'body-text--elder': elderMode }">{{ item.diseases.join("、") }}</text>
</view>
<view class="desc" :class="{ 'desc--elder': elderMode }">
<text class="label" :class="{ 'label--elder': elderMode }">病情描述</text>
<text :class="{ 'body-text--elder': elderMode }">{{ item.description }}</text>
</view>
<view class="info-row" :class="{ 'info-row--elder': elderMode }">
<view>
<text class="label" :class="{ 'label--elder': elderMode }">问诊人</text>
<text :class="{ 'body-text--elder': elderMode }">{{ item.name }} {{ item.sex }}
{{ item.age ? item.age + "岁" : "" }}</text>
</view>
<view :class="{ 'body-text--elder': elderMode }">
{{
item.createTime
? dayjs(item.createTime).format("YYYY-MM-DD HH:mm")
: ""
}}
</view>
</view>
</view>
<view class="card_footer info-row-end" :class="{ 'card_footer--elder': elderMode }">
<view :class="{ 'footer-type--elder': elderMode }">
{{ item.consultType == 'onlineMedicinePurchase' ? "在线配药" : "在线复诊" }}
</view>
<view v-if="item.showFooter" class="footer-item">
<view v-if="item.showRefund" class="import-btn" :class="{ 'import-btn--elder': elderMode }"
@click.stop="toRefundPage(item)">
{{ item.refundText }}
</view>
<view v-if="item.canCancel" class="import-btn" :class="{ 'import-btn--elder': elderMode }"
@click.stop="cancelOrder(item)">
取消订单
</view>
<view v-if="item.canPay" class="import-btn" :class="{ 'import-btn--elder': elderMode }"
@click.stop="pay(item)">
去支付</view>
<view v-if="item.enterRoom" class="import-btn" :class="{ 'import-btn--elder': elderMode }"
@click.stop="enterRoom(item)">{{ item.enterRoomText }}</view>
</view>
</view>
</view>
</view>
<re-login v-else height="80vh" />
<view v-if="!more" style="height: 200rpx"></view>
</full-page>
<refresh-icon v-if="!loading" @refresh="refresh()" />
</template>
<script setup>
import { ref, watch, computed, onMounted } from "vue";
import { onShow } from "@dcloudio/uni-app";
import dayjs from "dayjs";
import useUser from "@/hooks/useUser";
import useYbPay from "@/hooks/useYbPay";
import { getConsultOrder, cancelConsultOrder, checkRxUploadStatus } from "@/utils/api.js";
import { getOrderStatus } from "@/utils";
import fullPage from "@/components/full-page.vue";
import reLogin from "@/components/re-login.vue";
import emptyData from "@/components/empty.vue";
import refreshIcon from '@/components/refresh-icon.vue';
import {
toast,
loading as uniLoading,
hideLoading as unHideLoading,
} from "@/utils/widget";
import { useIMStore } from "@/store/tim";
const OrderSource = process.env.ORDER_SOURCE;
const { userInfo, logined, myProfile } = useUser();
const page = ref(1);
const list = ref([]);
const more = ref(false);
const loading = ref(false);
// 定义状态栏的选项
const tabs = ["全部", "待支付", "处理中", "已结束", "已取消"];
const activeTab = ref(0); // 当前选中的选项卡
const pay = useYbPay(null, reload);
// 适老化模式状态
const elderMode = ref(false);
onMounted(() => {
// 从本地存储读取适老化模式状态
const savedElderMode = uni.getStorageSync('elderMode')
if (savedElderMode !== null && savedElderMode !== undefined) {
elderMode.value = savedElderMode
}
});
function loadMore() {
if (more.value && !loading.value) {
page.value++;
getList();
}
}
function reload() {
page.value = 1;
getList();
}
async function getList() {
if (loading.value) return;
loading.value = true;
const { data, succes, pages } = await getConsultOrder({
page: page.value,
pageSize: 20,
// patientId: myProfile.value.patientid,
accountId: userInfo.value.userId,
showPassdiagnostic: true,
orderSource: OrderSource
});
const listData = Array.isArray(data)
? data.map((item) => {
const res = getOrderStatus(item, true);
return { ...item, ...res };
})
: [];
list.value = page.value === 1 ? listData : [...list.value, ...listData];
more.value = pages > page.value;
loading.value = false;
}
async function cancelOrder(item) {
uni.showModal({
title: "取消订单",
content: "确定取消订单吗?",
success: async (res) => {
if (res.confirm) {
uniLoading("取消中...");
const { success, message } = await cancelConsultOrder({
orderId: item.orderId,
});
unHideLoading();
if (success) {
uni.showToast({
title: "取消成功",
icon: "success",
});
page.value = 1;
getList();
} else {
uni.showToast({
title: message,
icon: "none",
});
}
}
},
});
}
// async function enterRoom(item) {
// const { doctorCode, orderId } = item;
// const imStore = useIMStore();
// const res = await imStore.login(orderId);
// const conversationID = `C2C${doctorCode}`;
// if (res) {
// uni.navigateTo({
// url: `/pages/chat/index?conversationID=${conversationID}&orderId=${orderId}`,
// });
// }
// }
async function enterRoom(item) {
const { doctorCode, orderId } = item;
if (!doctorCode) {
toast("进入视频间错误,医生视频账号不存在 ");
return;
}
if (!orderId) {
toast("进入视频间错误,用户视频账号不存在 ");
return;
}
uniLoading("正在进入视频间, 请稍后等待");
const imStore = useIMStore();
try {
// 登录 IM
const res = await imStore.login(orderId);
if (!res) {
unHideLoading();
toast("IM 登录失败");
return;
}
// 等待 SDK 准备好
await new Promise((resolve) => {
if (imStore.isSDKReady) {
resolve();
} else {
const timer = setInterval(() => {
if (imStore.isSDKReady) {
clearInterval(timer);
resolve();
}
}, 300);
}
});
// 准备进入会话
const conversationID = `C2C${doctorCode}`;
unHideLoading();
// 导航到聊天页面
uni.navigateTo({
url: `/pages/chat/index?conversationID=${conversationID}&orderId=${orderId}`,
});
} catch (error) {
unHideLoading();
console.error("进入会话失败:", error);
toast(`进入会话失败: ${error.message || "未知错误"}`);
}
}
function toRecord(item) {
uni.navigateTo({
url: "/pages/record/order-detail?orderId=" + item.orderId,
});
}
async function toRefundPage(item) {
if (!item.refundInfo) {
const { success, message } = await checkRxUploadStatus({
orderId: item.orderId,
registerId: item.registerId,
patientId: item.patientId
});
if (!success) {
toast(message || "获取处方状态失败");
return
}
}
uni.setStorageSync('refund-order', item)
uni.navigateTo({
url: '/pages/record/order-refund'
})
}
function refresh() {
if (loading.value) return;
page.value = 1;
list.value = [];
getList();
}
watch(logined, (n) => {
if (n) {
page.value = 1;
getList();
}
});
const tab = ref("全部");
const switchList = computed(() => {
return list.value.filter((item) => {
if (tab.value === "全部") {
return true;
}
return item.text === tab.value;
});
});
// 切换选项卡
const switchTab = (index, item) => {
activeTab.value = index;
tab.value = item;
};
onShow(() => {
if (logined.value) {
page.value = 1;
getList();
}
});
</script>
<style lang="scss" scoped>
.footer-item {
display: flex;
justify-content: flex-end; // 按钮右对齐
align-items: center; // 垂直居中对齐
gap: 20rpx; // 按钮间距
flex-wrap: wrap; // 允许换行
}
.container {
padding: 20px;
}
.status-bar {
display: flex;
justify-content: space-around;
}
.tab {
padding: 10px;
cursor: pointer;
color: #666;
font-size: 28rpx;
@at-root &--elder {
font-size: 39rpx; // 28 * 1.4
font-weight: bold;
}
}
.tab.active {
color: $theme-brown-primary;
/* 选中时的颜色 */
border-bottom: 2px solid $theme-brown-primary;
/* 选中时的下划线 */
font-weight: bold;
}
.card {
background: white;
@at-root &+& {
margin-top: 20rpx;
}
// 适老化模式:卡片整体变大
@at-root &--elder {
margin: 30rpx 20rpx;
border-radius: 16rpx;
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.1);
}
.info-row {
display: flex;
align-items: center;
justify-content: space-between;
// 适老化模式:元素各占一行
@at-root &--elder {
flex-direction: column;
align-items: flex-start;
gap: 16rpx;
}
}
.info-row-end {
display: flex;
align-items: center;
justify-content: space-between;
// 适老化模式:元素各占一行
@at-root &--elder {
flex-direction: column;
align-items: flex-start;
gap: 20rpx;
}
}
&_head {
padding: 24rpx 30rpx;
font-size: 28rpx;
color: #333;
border-bottom: 1px solid #e5e5e5;
// 适老化模式:头部内边距增加,字体放大
@at-root &--elder {
padding: 36rpx 40rpx;
font-size: 39rpx; // 28 * 1.4
font-weight: bold;
}
}
&_footer {
padding: 24rpx 30rpx;
font-size: 28rpx;
color: $theme-brown-primary;
border-top: 1px solid #e5e5e5;
// 适老化模式:底部内边距增加,字体放大
@at-root &--elder {
padding: 36rpx 40rpx;
font-size: 39rpx; // 28 * 1.4
font-weight: bold;
}
.import-btn {
padding: 6rpx 30rpx;
border: 1px solid;
border-radius: 30rpx;
display: inline-flex;
align-items: center;
justify-content: center;
height: 60rpx; // 统一按钮高度
line-height: 1; // 重置行高
box-sizing: border-box;
// 适老化模式:按钮变大
@at-root &--elder {
padding: 12rpx 40rpx;
font-size: 35rpx; // 25 * 1.4 (按钮字体稍小)
border-radius: 40rpx;
font-weight: bold;
width: auto; // 按钮宽度自适应内容
white-space: nowrap; // 防止文字换行
height: 80rpx; // 适老化模式按钮高度
}
}
}
.doctor-info {
font-weight: bold;
max-width: 400rpx;
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
line-height: 48rpx;
font-size: 30rpx;
// 适老化模式:医生信息字体放大
@at-root &--elder {
max-width: 100%;
white-space: normal; // 允许换行
text-overflow: unset;
overflow: visible;
line-height: 60rpx;
font-size: 42rpx; // 30 * 1.4
font-weight: bold;
}
}
.dept {
margin-left: 10rpx;
color: #666;
font-weight: normal;
font-size: 28rpx;
// 适老化模式:科室字体放大
@at-root &--elder {
margin-left: 20; // 科室左边距
font-size: 39rpx; // 28 * 1.4
font-weight: 500;
margin-top: 8rpx;
}
}
&_body {
padding: 24rpx 30rpx;
font-size: 28rpx;
line-height: 48rpx;
color: #333;
// 适老化模式:内容区域内边距增加,字体和行高放大
@at-root &--elder {
padding: 36rpx 40rpx;
font-size: 39rpx; // 28 * 1.4
line-height: 67rpx; // 48 * 1.4
font-weight: 500;
}
.label {
color: #666;
// 适老化模式:标签字体放大
@at-root &--elder {
font-size: 39rpx; // 28 * 1.4
// font-weight: bold;
}
}
.desc {
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
line-clamp: 2;
overflow: hidden;
// 适老化模式:描述区域行数增加,便于阅读
@at-root &--elder {
-webkit-line-clamp: 4;
line-clamp: 4;
}
}
// 适老化模式:每个信息块单独占一行
@at-root &--elder>view {
margin-bottom: 16rpx;
}
}
}
// 适老化模式额外样式类
.status-text--elder {
font-size: 39rpx !important; // 28 * 1.4
font-weight: bold;
}
.body-text--elder {
font-size: 39rpx !important; // 28 * 1.4
font-weight: 500;
}
.footer-type--elder {
font-size: 39rpx !important; // 28 * 1.4
font-weight: bold;
}
.flex-shrink-0 {
flex-shrink: 0;
}
</style>