2026-07-27 11:26:39 +08:00

929 lines
20 KiB
Vue
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<full-page pageStyle="background:#FDFBF5">
<view class="page-container">
<view class="content-wrapper" :style="{ paddingTop: (statusBarHeight + 10) + 'px' }">
<image class="custom-header-logo" src="/static/_home/logo.png" mode="aspectFill" />
<view class="top-container">
<view v-if="logined" class="user-bar">
<image class="avatar" :src="userInfo.avatar" />
<view class="name">{{ userInfo.maskName }}</view>
<view class="login-btn login-btn--logout" @click="loginout">退出登录 </view>
</view>
<view v-else class="user-bar">
<image class="avatar" src="/static/avatar/user.svg" />
<view class="login-btn shadow-lg" @click="login">登录</view>
</view>
</view>
<view class="main-menu-list" :class="{ 'elder-main-menu': elderMode }">
<view v-for="(item, index) in mainMenuList" :key="item.key" class="menu-item"
@click="handleMainMenuClick(item)">
<image class="menu-card-bg"
:src="index === 0 ? '/static/home/design/card-bg-left-elder.png' : '/static/home/design/card-bg-right-elder.png'"
mode="scaleToFill" />
<!-- 统一垂直布局上图标中标题下描述 -->
<view class="menu-content-vertical" :class="{ 'elder-menu-content': elderMode }">
<image class="menu-icon-top" :class="{ 'elder-menu-icon': elderMode }" :src="item.icon" mode="aspectFit">
</image>
<view class="menu-title-center font-yanshi" :class="{ 'elder-menu-title': elderMode }">
{{ item.title }}
</view>
<view class="menu-desc-bottom" :class="{ 'elder-menu-desc': elderMode }">
{{ elderMode ? (item.elderDesc || item.desc) : item.desc }}</view>
</view>
</view>
</view>
<view class="section-title-bar">
<view class="section-title-text font-yanshi"><text class="diamond"></text> 院内服务</view>
</view>
<view :class="elderMode ? 'elder-service-list' : 'menu-list shadow-lg'">
<image v-if="!elderMode" class="section-bg" :src="'/static/home/design/section-bg.png'" mode="scaleToFill"
style="width: 100%; height: 100%; display: block;" />
<!-- 长辈版2x2卡片布局 -->
<template v-if="elderMode">
<view class="elder-service-item" v-for="item in menuList" :key="item.title" @click="gotoPage(item.url)">
<image class="elder-service-bg" :src="'/static/home/design/section-bg-elder.png'" mode="scaleToFill" />
<view class="elder-service-content">
<view class="elder-service-album relative">
<uni-badge :text="count[item.badgeKey]" absolute="rightTop" size="small"
:custom-style="item.badgeKey && count[item.badgeKey] > 0 ? {} : { opacity: 1 }">
<image class="elder-service-icon" :src="item.icon" mode="aspectFit"></image>
</uni-badge>
</view>
<view class="elder-service-title">{{ item.elderTitle || item.title }}</view>
</view>
</view>
</template>
<!-- 标准版横排布局 -->
<template v-else>
<view class="menu-item" v-for="item in menuList" :key="item.title" @click="gotoPage(item.url)">
<view class="menu-item-album relative">
<uni-badge :text="count[item.badgeKey]" absolute="rightTop" size="small"
:custom-style="item.badgeKey && count[item.badgeKey] > 0 ? {} : { opacity: 1 }">
<image class="menu-item-icon" :src="item.icon" mode="aspectFit"></image>
</uni-badge>
</view>
<view class="menu-item-title">{{ item.title }}</view>
</view>
</template>
</view>
</view>
</view>
</full-page>
<confirm-popup title="提示" content="您是否半年内在医院就诊过?" cancelText="" confirmText="" :visible="confirmVisible"
@confirm="handleConfirmYes" @cancel="handleConfirmNo" @close="confirmVisible = false" />
</template>
<script setup>
import { ref, watch, onUnmounted } from "vue";
import { onLoad, onShow, onHide } from "@dcloudio/uni-app";
import dayjs from 'dayjs';
// import useElder from "@/hooks/useElder";
import useUser from "@/hooks/useUser";
import { toast } from "@/utils/widget";
import { isDoctorOnline, getArticleCateList, getArticleList, getPatientHomeRxCount, autoAddHlwPatient } from '@/utils/api'
import fullPage from "@/components/full-page.vue";
import confirmPopup from "./confirm-popup.vue";
const mainMenuList = [
{
title: "医保处方",
desc: "医保结算到店取药",
key: 'YB',
icon: "/static/home/design/online-consult.png"
},
{
title: "自费处方",
desc: "全额自费到店取药",
key: 'ZF',
icon: "/static/home/design/online-drug.png"
}
]
const menuList = [
{
title: "处方记录",
elderTitle: "处方记录",
icon: "/static/home/design/rx-record.png",
url: "/pages/record/prescription-record",
badgeKey: 'rxUnpay'
},
{
title: "诊疗记录",
elderTitle: "诊疗记录",
icon: "/static/home/design/consult-record.png",
url: "/pages/record/consult-record",
},
{
title: "续方订单",
elderTitle: "续方订单",
icon: "/static/home/design/drug-order.png",
url: "/pages/consult/drug-purchase-list/drug-purchase-list",
badgeKey: 'deliveryUnpay'
},
{
title: "就诊人管理",
elderTitle: "就诊人管理",
icon: "/static/home/design/patient-mgr.png",
url: "/pages/member/list",
},
];
const { userInfo, logined, login, loginout } = useUser();
// const { elderMode, elderClass, elderVarStyle, toggle } = useElder();
const elderMode = true;
const visible = ref(false)
const statusBarHeight = ref(20)
const agreenmentPopupVisible = ref(false)
const count = ref({ rxUnpay: 0, deliveryUnpay: 0 })
const confirmVisible = ref(false)
const confirmResolve = ref(null)
const confirmReject = ref(null);
const feeType = ref('');
function confirmAuth() {
uni.navigateTo({
url: `/pages/consult/index?feeType=${feeType.value}`
})
}
async function checkLogin() {
if (logined.value) {
return true
}
await login();
return logined.value ? true : Promise.reject('login fail');
}
async function handleMainMenuClick(item) {
if (item.key === 'onlineMedicinePurchase') {
toast('功能建设中...')
return
}
await checkLogin();
// await checkCanBuy()
feeType.value = item.key
confirmVisible.value = true
}
function handleConfirmYes() {
confirmVisible.value = false
confirmAuth()
if (confirmResolve.value) {
confirmResolve.value()
cleanupConfirmPromise()
}
}
function handleConfirmNo() {
confirmVisible.value = false
if (confirmReject.value) {
confirmReject.value()
cleanupConfirmPromise()
}
}
// 清理确认弹窗的Promise状态
function cleanupConfirmPromise() {
confirmResolve.value = null
confirmReject.value = null
}
async function checkCanBuy() {
const res = await isDoctorOnline()
if (res.data === true) {
return
}
toast('很抱歉!互联网问诊医生因线下门诊等原因暂时不在线!请稍后再试!')
return Promise.reject('no online doctor')
}
async function gotoPage(url) {
if (url === '/pages/consult/drug-purchase-list/drug-purchase-list') {
toast('功能建设中...')
return
}
await checkLogin();
uni.navigateTo({
url,
});
}
async function insurePatient() {
const { userId, userName, certNo, mobile } = userInfo.value || {};
if (!userId || !userName || !certNo || !mobile) return false;
try {
const res = await autoAddHlwPatient({
accountId: userId,
name: userName,
certNo,
mobile,
});
if (!res || !res.success) {
console.error('确保当前用户就诊人信息失败', res && res.message);
return false;
}
return true;
} catch (error) {
console.error('确保当前用户就诊人信息失败', error);
return false;
}
}
onLoad(async () => {
const sys = uni.getSystemInfoSync()
statusBarHeight.value = sys.statusBarHeight || 20
})
// 页面隐藏时清理弹窗状态
onHide(() => {
// 如果有未完成的Promise先reject再清理
if (confirmReject.value) {
confirmReject.value()
}
cleanupConfirmPromise()
// 关闭所有弹窗
confirmVisible.value = false
agreenmentPopupVisible.value = false
visible.value = false
})
// 页面卸载时清理
onUnmounted(() => {
cleanupConfirmPromise()
})
</script>
<style lang="scss" scoped>
.page-container {
position: relative;
min-height: 100vh;
display: flex;
flex-direction: column;
}
.home-bg {
position: absolute;
top: 0;
left: 0;
width: 100%;
display: block;
/* Ensure it renders */
z-index: 0;
}
.content-wrapper {
position: relative;
z-index: 1;
padding: 30rpx;
box-sizing: border-box;
min-height: 100vh;
display: flex;
flex: 1;
flex-direction: column;
}
/* 顶部容器样式 */
@font-face {
font-family: 'YanShi';
src: url('/static/font/YanShiQiuHongKai-2-subset.woff2');
}
.custom-header {
margin-bottom: 20rpx;
// padding-left: 10rpx;
display: flex;
align-items: center;
}
.custom-header-logo {
margin-left: 30rpx;
width: 340rpx;
height: 66rpx;
}
.custom-header-title {
font-family: 'YanShi', sans-serif;
font-size: 48rpx;
color: #5a3d2b;
// letter-spacing: 2rpx;
}
.top-container {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 16rpx;
}
.work-time-notice {
width: calc(100% + 60rpx);
margin-left: -30rpx;
margin-right: -30rpx;
margin-bottom: 20rpx;
padding: 10rpx 30rpx;
box-sizing: border-box;
background: #f7e1d6;
color: #e60012;
font-size: 28rpx;
line-height: 36rpx;
font-weight: bold;
}
.user-bar {
flex-grow: 1;
margin-top: 24rpx;
display: flex;
align-items: center;
flex-wrap: nowrap;
}
.avatar {
width: 56rpx;
height: 56rpx;
border-radius: 28rpx;
margin-right: 16rpx;
@at-root &.caring-mode-active {
width: 80rpx;
height: 80rpx;
border-radius: 40rpx;
}
}
.name {
max-width: 180rpx;
font-size: var(--text-lg);
margin-right: 16rpx;
font-weight: 600;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.login-btn {
font-size: 24rpx;
padding: 6rpx 16rpx;
border-radius: 24rpx;
background: transparent;
border: 1px solid #8b6538;
color: #8b6538;
white-space: nowrap;
flex-shrink: 0;
margin-left: auto;
}
.elder-mode-btn {
font-size: 24rpx;
color: #8b6538;
background: #fdf5e6;
/* 浅米色 */
padding: 8rpx 20rpx;
border-radius: 30rpx;
border: none;
white-space: nowrap;
flex-shrink: 0;
display: flex;
align-items: center;
justify-content: center;
box-shadow: 0 2rpx 6rpx rgba(139, 101, 56, 0.2);
}
.elder-btn-icon {
width: 28rpx;
height: 28rpx;
margin-right: 8rpx;
@at-root &.caring-mode-active {
width: 32rpx;
height: 32rpx;
}
}
.main-menu-list {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
.menu-item {
width: 335rpx;
height: 300rpx;
position: relative;
overflow: hidden;
border-radius: 16rpx;
background: #fff;
box-shadow: 0 8rpx 16rpx rgba(0, 0, 0, 0.05);
display: flex;
align-items: center;
justify-content: center;
padding: 0;
margin-bottom: 20rpx;
}
.menu-card-bg {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 1;
}
/* 统一垂直布局样式 */
.menu-content-vertical {
position: relative;
z-index: 3;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
width: 100%;
height: 100%;
padding: 20rpx 20rpx 10rpx;
/* 继续向上移动 */
box-sizing: border-box;
}
.menu-icon-top {
width: 100rpx;
height: 100rpx;
margin-bottom: 8rpx;
/* 继续减少间距 */
}
.menu-title-center {
font-family: 'YanShi';
font-size: 52rpx;
color: #fffbdf;
margin-bottom: 10rpx;
/* 继续减少间距 */
text-align: center;
}
.menu-desc-bottom {
font-size: 28rpx;
color: #fffbdf;
text-align: center;
}
.menu-item:nth-child(1) {
background: transparent;
}
.menu-item:nth-child(2) {
background: transparent;
}
}
.section-title-bar {
display: flex;
align-items: center;
margin-bottom: 20rpx;
margin-top: 40rpx;
}
.section-title-text {
font-family: 'YanShi';
/* 特殊字体 */
font-size: 46rpx;
color: #333;
display: flex;
align-items: center;
}
.diamond {
/* CSS绘制双层菱形 - 外层 */
width: 24rpx;
height: 24rpx;
border: 1px solid #8b6538;
transform: rotate(45deg);
margin-right: 16rpx;
margin-left: 8rpx;
position: relative;
display: inline-block;
box-sizing: border-box;
}
.diamond::after {
/* 内层填充菱形 */
content: '';
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 50%;
height: 50%;
background-color: #8b6538;
}
.menu-list {
margin-top: 24rpx;
display: flex;
flex-wrap: nowrap;
border-radius: 16rpx;
overflow: hidden;
background: transparent;
position: relative;
.section-bg {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 0;
display: block;
}
.menu-item {
position: relative;
z-index: 1;
padding: 30rpx 0;
flex: 1;
text-align: center;
margin-bottom: 0;
background: transparent !important;
/* Force transparent to show bg */
}
.menu-item-album {
width: 88rpx;
height: 88rpx;
margin-bottom: 8rpx;
margin: 0 auto;
}
.menu-item-icon {
width: 88rpx;
height: 88rpx;
}
.menu-item-title {
font-family: 'YanShi';
/* 特殊字体 */
font-size: 28rpx;
color: #84492b;
font-weight: 500;
}
}
/* ==================== 长辈版样式 ==================== */
/* 长辈版主菜单样式 */
.elder-main-menu {
.menu-item {
width: 335rpx;
height: 300rpx;
border-radius: 16rpx;
box-shadow: 0 8rpx 24rpx rgba(139, 101, 56, 0.15);
background: transparent;
}
.menu-card-bg {
object-fit: cover;
}
.elder-menu-content {
padding: 20rpx 20rpx 10rpx;
/* 继续向上移动 */
}
.elder-menu-icon {
width: 100rpx;
height: 100rpx;
margin-bottom: 8rpx;
/* 继续减少间距 */
}
.elder-menu-title {
font-size: 52rpx;
margin-bottom: 10rpx;
/* 继续减少间距 */
color: #fffbdf;
}
.elder-menu-desc {
font-size: 28rpx;
color: #fffbdf;
}
}
/* 长辈版院内服务2x2卡片布局 */
.elder-service-list {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
margin-top: 24rpx;
.elder-service-item {
width: 335rpx;
height: 160rpx;
position: relative;
overflow: hidden;
border-radius: 16rpx;
margin-bottom: 20rpx;
box-shadow: 0 4rpx 16rpx rgba(139, 101, 56, 0.1);
}
.elder-service-bg {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 0;
object-fit: cover;
}
.elder-service-content {
position: relative;
z-index: 1;
display: flex;
align-items: center;
width: 100%;
height: 100%;
padding: 0 30rpx;
box-sizing: border-box;
}
.elder-service-album {
width: 80rpx;
height: 80rpx;
flex-shrink: 0;
margin-right: 24rpx;
}
.elder-service-icon {
width: 80rpx;
height: 80rpx;
}
.elder-service-title {
font-family: 'YanShi';
font-size: 38rpx;
color: #84492b;
font-weight: 500;
white-space: nowrap;
}
}
.article-list {
margin-top: 24rpx;
border-radius: 16rpx;
background: #fff;
overflow: hidden;
min-height: 500rpx;
flex: 1;
display: flex;
flex-direction: column;
}
.article-header {
display: flex;
align-items: center;
justify-content: space-between;
padding: 24rpx 30rpx;
}
.header-title {
color: #333;
font-weight: bold;
font-size: 32rpx;
}
.article-more {
display: flex;
align-items: center;
color: #999;
font-size: 26rpx;
.more-icon {
width: 14rpx;
height: 24rpx;
/* Slightly larger */
margin-left: 8rpx;
display: block;
}
}
.article-tags-scroll {
width: 100%;
white-space: nowrap;
}
.article-tags {
display: inline-flex;
align-items: center;
padding: 30rpx 30rpx 24rpx;
flex-wrap: nowrap;
}
.article-tag {
display: inline-block;
flex-shrink: 0;
padding: 10rpx 24rpx;
background: transparent;
border: 1px solid #834829;
border-radius: 8rpx;
font-size: 28rpx;
color: #834829;
@at-root &+& {
margin-left: 16rpx;
}
@at-root &.active {
background: #834829;
/* Fallback */
/* 实现选中状态下的四角内凹(缺口)效果 */
background:
radial-gradient(circle at 0 50%, transparent 6rpx, #834829 7rpx),
radial-gradient(circle at 100% 50%, transparent 6rpx, #834829 7rpx);
background-size: 51% 100%;
background-position: left, right;
background-repeat: no-repeat;
color: #fff;
border-color: transparent;
}
}
.article-item {
display: flex;
align-items: center;
padding: 24rpx 30rpx;
border-top: 1px solid #eee;
}
.article-body {
width: 0;
flex: 1;
}
.article-title {
font-size: 28rpx;
color: #333;
font-weight: 600;
margin-bottom: 16rpx;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
line-clamp: 2;
overflow: hidden;
text-overflow: ellipsis;
white-space: normal;
}
.article-content,
.article-time {
margin-top: 8rpx;
font-size: 28rpx;
color: #666;
margin-bottom: 16rpx;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.article-cover {
flex-shrink: 0;
width: 120rpx;
height: 120rpx;
border-radius: 12rpx;
background: #f5f5f5;
}
.article-empty {
padding: 0;
text-align: center;
color: #999;
font-size: 28rpx;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
flex: 1;
}
/* ==================== 长辈版文章样式 ==================== */
.elder-section-title {
margin-top: 40rpx !important;
}
.elder-title-text {
font-size: 52rpx !important;
}
.elder-article-list {
margin-top: 24rpx;
background: #fff;
border-radius: 16rpx;
overflow: hidden;
box-shadow: 0 4rpx 16rpx rgba(139, 101, 56, 0.1);
min-height: 500rpx;
flex: 1;
display: flex;
flex-direction: column;
}
.elder-article-tags {
display: flex;
align-items: center;
padding: 30rpx;
flex-wrap: no-wrap;
gap: 16rpx;
}
.elder-article-tag {
padding: 14rpx 32rpx;
background: transparent;
border: 2rpx solid #834829;
border-radius: 12rpx;
font-size: 32rpx;
color: #834829;
&.active {
background: #834829;
/* Fallback */
background:
radial-gradient(circle at 0 50%, transparent 6rpx, #834829 7rpx),
radial-gradient(circle at 100% 50%, transparent 6rpx, #834829 7rpx);
background-size: 51% 100%;
background-position: left, right;
background-repeat: no-repeat;
color: #fff;
border-color: transparent;
}
}
.elder-article-item {
display: flex;
align-items: center;
padding: 30rpx;
border-top: 1px solid #f0e6d8;
}
.elder-article-body {
flex: 1;
width: 0;
padding-right: 20rpx;
}
.elder-article-title {
font-size: 34rpx;
color: #333;
font-weight: 600;
line-height: 1.5;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
line-clamp: 2;
overflow: hidden;
margin-bottom: 16rpx;
}
.elder-article-time {
font-size: 28rpx;
color: #999;
}
.elder-article-cover {
flex-shrink: 0;
width: 180rpx;
height: 140rpx;
border-radius: 12rpx;
background: #f5f5f5;
object-fit: cover;
}
.elder-article-empty {
padding: 80rpx 0;
text-align: center;
color: #999;
font-size: 32rpx;
flex: 1;
display: flex;
align-items: center;
justify-content: center;
}
.service-icon {
width: 112rpx;
height: 144rpx;
position: fixed;
bottom: 120rpx;
right: 30rpx;
z-index: 3;
@at-root &.caring-mode-active {
width: 126rpx;
height: 162rpx;
}
}
</style>