929 lines
20 KiB
Vue
Raw Permalink Normal View History

2026-07-27 11:26:39 +08:00
<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>