haomingming 36cda41b14 Merge branch 'develop'
# Conflicts:
#	pages/my/my.vue
2025-09-25 10:31:52 +08:00

869 lines
21 KiB
Vue
Raw 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>
<uni-nav-bar title="我的" fixed color="#8B2316" height="140rpx" :border="false"
backgroundColor="#eeeeee"></uni-nav-bar>
<view class="page">
<!-- 用户信息卡片 -->
<view class="user-card"
:style="{'background-image': `url(${myInfoBackGround || '/static/big_background_my.png'})`, 'background-size':'cover','background-repeat':'no-repeat'}">
<view class="user-info" @click="goToPage('myInfo')">
<image class="avatar" :src="avatar" mode="aspectFill"></image>
<view class="user-info-content">
<text class="username">{{username}}</text>
<scroll-view class="honor_box" scroll-x="true" show-scrollbar="false">
<view class="honor_wrap">
<view class="honor_item" v-for="item in honor_list" :key="item.id">
<image class="honor_image" src="/static/wdsc.png" mode="aspectFill"></image>
<text class="honor_text">{{ item.nick_name }}</text>
</view>
</view>
</scroll-view>
</view>
</view>
<!-- 统计数据 -->
<view class="stats-section">
<view class="stats-item" @click="onStatsClick('followup')">
<text class="stats-number">{{followupCount}}</text>
<text class="stats-label">随访患者数</text>
</view>
<view class="stats-item" @click="onStatsClick('consult')">
<text class="stats-number">{{consultCount}}</text>
<text class="stats-label">公益咨询数</text>
</view>
<view class="stats-item" @click="onStatsClick('flower')">
<text class="stats-number">{{flowerCount}}</text>
<text class="stats-label">患者送花数</text>
</view>
<view class="divder"></view>
<view class="signbox" v-if="sign_in == 0" @click="onSignClick">
<view class="sign">签到</view>
</view>
<view class="signbox_1" v-else @click="goToPage('pointMall')">
<view class="sign">{{ formatToChineseUnit(totalPoints) }}</view>
</view>
</view>
</view>
<!-- 随访服务 -->
<view class="section">
<view class="section-title">随访服务</view>
<up-scroll-list indicatorActiveColor="#8B2316" indicatorWidth="40rpx" indicatorBarWidth="20rpx"
class="service-grid">
<view class="service-item" @click="goToPage('patientAudit')">
<up-image :src="hzshImg" width="48rpx" height="48rpx"></up-image>
<text>患者审核</text>
</view>
<view class="service-item" @click="goToPage('patientGroup')">
<up-image :src="hzfzImg" width="48rpx" height="48rpx"></up-image>
<text>患者分组</text>
</view>
<view class="service-item" @click="goToPage('groupMessage')">
<up-image :src="qfxxImg" width="48rpx" height="48rpx"></up-image>
<text>群发消息</text>
</view>
<view class="service-item" @click="goToPage('qrcode')">
<up-image :src="sfImg" width="48rpx" height="48rpx"></up-image>
<text>随访二维码</text>
</view>
<view class="service-item" @click="goToPage('plan')">
<up-image :src="czjhImg" width="48rpx" height="48rpx"></up-image>
<text>出诊计划</text>
</view>
</up-scroll-list>
</view>
<!-- 学习进步 -->
<view class="section">
<view class="section-title">学习进步</view>
<view class="learning-grid">
<view class="learning-item" @click="goToPage('myVideos')">
<up-image :src="wdspImg" width="48rpx" height="48rpx"></up-image>
<text>我的视频</text>
</view>
<view class="learning-item" @click="goToPage('myCourses')">
<up-image :src="wdkcImg" width="48rpx" height="48rpx"></up-image>
<text>我的课程</text>
</view>
<view class="learning-item" @click="goToPage('myDownloads')">
<up-image :src="wdxzImg" width="48rpx" height="48rpx"></up-image>
<text>我的下载</text>
</view>
<view class="learning-item" @click="goToPage('myFavorites')">
<up-image :src="wdscImg" width="48rpx" height="48rpx"></up-image>
<text>我的收藏</text>
</view>
</view>
</view>
<!-- 账户明细 -->
<view class="section">
<view class="section-title">账户明细</view>
<up-scroll-list indicatorActiveColor="#8B2316" indicatorWidth="40rpx" indicatorBarWidth="20rpx"
class="account-grid">
<view class="account-item" @click="goToPage('myAccount')">
<up-image :src="wdzzImg" width="48rpx" height="48rpx"></up-image>
<text>我的账户</text>
</view>
<view class="account-item" @click="goToPage('myPoints')">
<up-image :src="wdjfImg" width="48rpx" height="48rpx"></up-image>
<text>我的积分</text>
</view>
<view class="account-item" @click="goToPage('myBenefits')">
<up-image :src="wdflImg" width="48rpx" height="48rpx"></up-image>
<text>我的福利</text>
</view>
<view class="account-item" @click="goToPage('myFlower')">
<up-image :src="wdxhImg" width="48rpx" height="48rpx"></up-image>
<text>我的鲜花</text>
</view>
<view class="account-item" @click="goToPage('pptDetail')">
<up-image :src="kjmxImg" width="48rpx" height="48rpx"></up-image>
<text>课件明细</text>
</view>
<view class="account-item" @click="goToPage('couseDetail')">
<up-image :src="kcmxImg" width="48rpx" height="48rpx"></up-image>
<text>课程明细</text>
</view>
</up-scroll-list>
</view>
<!-- #ifdef APP -->
<!-- 常用操作 -->
<view class="section">
<view class="section-title">常用操作</view>
<view class="operation-grid">
<view class="operation-item" @click="goToPage('wechatUnbind')">
<up-image :src="wxjbImg" width="48rpx" height="48rpx"></up-image>
<text v-if="isBoundWechat">微信解绑</text>
<text v-else>微信绑定</text>
</view>
<view class="operation-item" @click="goToPage('changePhone')">
<up-image :src="ghsjhImg" width="48rpx" height="48rpx"></up-image>
<text>更换手机号</text>
</view>
<view class="operation-item" @click="goToPage('notifications')">
<up-image :src="tzykImg" width="48rpx" height="48rpx"></up-image>
<text>通知已开</text>
</view>
<view class="operation-item" @click="showVersion">
<up-image :src="versionImg" width="48rpx" height="48rpx"></up-image>
<text>V{{version}}</text>
</view>
</view>
</view>
<!-- #endif -->
<view class="setbox">
<!-- 福利卡兑换 -->
<view class="sectioncell benefit-section">
<view class="benefit-item" @click="goToPage('benefitExchange')">
<view class="benefit-icon">
<up-image :src="fulicard" width="48rpx" height="48rpx"></up-image>
</view>
<view class="benefit-content">
<text class="benefit-title">福利卡兑换</text>
</view>
<view class="benefit-arrow">
<uni-icons type="forward" size="16" color="#ccc"></uni-icons>
</view>
</view>
</view>
<!-- 常用银行卡 -->
<view class="sectioncell bank-section">
<view class="bank-item" @click="goToPage('bankCard')">
<view class="bank-icon">
<up-image :src="cyyhk" width="48rpx" height="48rpx"></up-image>
</view>
<view class="bank-content">
<text class="bank-title">常用银行卡</text>
</view>
<view class="bank-arrow">
<uni-icons type="forward" size="16" color="#ccc"></uni-icons>
</view>
</view>
</view>
<!-- 设置与帮助 -->
<view class="sectioncell settings-section">
<view class="settings-item" @click="goToPage('settings')">
<view class="settings-icon">
<up-image :src="settingImg" width="48rpx" height="48rpx"></up-image>
</view>
<view class="settings-content">
<text class="settings-title">设置与帮助</text>
</view>
<view class="settings-arrow">
<uni-icons type="forward" size="16" color="#ccc"></uni-icons>
</view>
</view>
</view>
</view>
<!-- 年度总结悬浮按钮 -->
<view class="year-summary-btn" @click="showYearSummary">
<view class="year-text">2024</view>
<view class="summary-text">年度总结</view>
</view>
<!-- 底部导航栏 -->
<CustomTabbar></CustomTabbar>
</view>
</template>
<script setup>
import CustomTabbar from '@/components/tabBar/tabBar.vue';
import {
ref
} from 'vue';
import {
onShow
} from "@dcloudio/uni-app";
import version from '@/utils/version.js'
import hzshImg from "@/static/hzsh.png"
import hzfzImg from "@/static/hzfz.png"
import qfxxImg from "@/static/qfxz.png"
import sfImg from "@/static/sfewm.png"
import czjhImg from "@/static/czjh.png"
import wdspImg from "@/static/wdsp.png"
import wdkcImg from "@/static/wdkc.png"
import wdxzImg from "@/static/wdxz.png"
import wdscImg from "@/static/wdsc.png"
import wdzzImg from "@/static/wdzh.png"
import wdjfImg from "@/static/wdjf.png"
import wdflImg from "@/static/wdfl.png"
import wdxhImg from "@/static/wdxh.png"
import kjmxImg from "@/static/kjmx.png"
import kcmxImg from "@/static/kcmx.png"
import sxyImg from "@/static/sxy.png"
import wxjbImg from "@/static/wxjb.png"
import ghsjhImg from "@/static/ghsjh.png"
import tzykImg from "@/static/xxtx.png"
import versionImg from "@/static/fxxbb.png"
import fulicard from "@/static/fulicard.png"
import fpgl from "@/static/fpgl.png"
import cyyhk from "@/static/cyhhk.png"
import settingImg from "@/static/setting.png"
import api from '@/api/api.js'
import my_api from '@/api/my_api.js'
import navTo from "@/utils/navTo"
import linkUrl from "@/utils/docUrl"
// 响应式数据
const isLargeFont = ref(false);
// 新增:我的信息数据
const avatar = ref('')
const username = ref('')
const followupCount = ref(0)
const consultCount = ref(0)
const flowerCount = ref(0)
const myInfoBackGround = ref('')
const totalPoints = ref(0)
const sign_in = ref(0)
const honor_list = ref([])
// 从storage获取用户信息
const getUserInfoFromStorage = () => {
try {
const userInfo = uni.getStorageSync('userInfo')
if (userInfo) {
avatar.value = linkUrl+userInfo.photo
username.value = userInfo.realName
}
} catch (e) {
console.error('从storage获取用户信息失败', e)
}
}
// 签到点击事件
const onSignClick = async () => {
try {
// 调用添加积分接口
const res = await api.addBonusPointsN({
score_type:1
});
if (res && res.code ==1) {
// 签到成功
sign_in.value = 1;
uni.showToast({
title: '签到成功,获得'+res.bonuspoints+'积分',
icon: 'none'
});
} else {
uni.showToast({
title: res?.msg || '签到失败',
icon: 'none'
});
}
} catch (error) {
console.error('签到失败:', error);
uni.showToast({
title: '签到失败,请重试',
icon: 'none'
});
}
};
const fetchMyInfo = async () => {
try {
const res = await api.getMyInfo({})
if (res && res.code === 200 && res.data) {
const data = res.data
myInfoBackGround.value = data.myInfoBackGround;
followupCount.value = data.expert_apply_num || 0
consultCount.value = data.consult_total_num || 0
flowerCount.value = data.ping_flowewr_num || 0
totalPoints.value = data.total_points || 0
sign_in.value = data.sign_in || 0
honor_list.value = data.honor_list || []
}
} catch (e) {
console.error('获取我的信息失败', e)
}
}
// 数字格式化为中文单位(万/亿)
const formatToChineseUnit = (value, fractionDigits = 1) => {
if (value == null || value === '' || isNaN(Number(value))) return value;
const num = Number(value);
const sign = num < 0 ? '-' : '';
const abs = Math.abs(num);
if (abs < 10000) {
return sign + String(abs);
}
if (abs < 100000000) {
const v = (abs / 10000).toFixed(fractionDigits);
return sign + (v.indexOf('.') > -1 ? v.replace(/\.0+$/, '').replace(/(\.\d*?)0+$/, '$1') : v) + '万';
}
const v = (abs / 100000000).toFixed(fractionDigits);
return sign + (v.indexOf('.') > -1 ? v.replace(/\.0+$/, '').replace(/(\.\d*?)0+$/, '$1') : v) + '亿';
}
// 方法
const toggleFontSize = () => {
isLargeFont.value = !isLargeFont.value;
console.log('切换字体大小:', isLargeFont.value ? '大字版' : '普通版');
};
const goToPage = (page) => {
console.log('跳转到页面:', page);
let url="";
// 根据页面名称进行跳转
switch (page) {
case 'patientAudit':
url="/pages_app/myPatient/myPatient"
break;
case 'patientGroup':
url="/pages_app/patientGroup/patientGroup"
break;
case 'groupMessage':
url="/pages_chat/groupMessage/groupMessage"
break;
case 'qrcode':
url="/pages_app/myCode/myCode"
break;
case 'myInfo':
url="/pages_app/personInfo/personInfo"
break;
case 'plan':
url="/pages_chat/outPatient/outPatient"
break;
case 'myVideos':
url="/pages_app/myVideo/myVideo"
break;
case 'myCourses':
url="/pages_course/my_courses/my_courses"
break;
case 'myDownloads':
url="/pages_app/myDownLoad/myDownLoad"
break;
case 'myFavorites':
url="/pages_app/myCollect/myCollect"
break;
case 'myAccount':
url="/pages_app/myAccount/myAccount"
break;
case 'myPoints':
url="/pages_app/myPoint/myPoint"
break;
case 'pointMall':
url="/pages_goods/pointMall/pointMall"
break;
case 'myBenefits':
url="/pages_app/myWelfare/myWelfare"
break;
case 'myFlower':
url="/pages_app/myFlower/myFlower"
break;
case 'pptDetail':
url="/pages_app/myCourseware/myCourseware"
break;
case 'couseDetail':
url="/pages_course/order_record/order_record"
break;
case 'wechatUnbind':
url="/pages_app/wechatContact/wechatContact"
break;
case 'changePhone':
url="/pages_app/changeMobile/changeMobile"
break;
case 'benefitExchange':
url="/pages_app/myWelfareCard/myWelfareCard"
break;
case 'bankCard':
url="/pages_app/idcardAuth/bankCardList"
break;
case 'settings':
url="/pages_app/setting/setting"
break;
default:
uni.showToast({
title: '功能开发中',
icon: 'none'
});
}
navTo({
url:url
})
};
const showYearSummary = () => {
console.log('显示年度总结');
uni.showToast({
title: '年度总结功能开发中',
icon: 'none'
});
};
const showVersion = () => {
uni.showModal({
title: '版本信息',
content: '当前版本V'+version,
showCancel: false
});
};
const onStatsClick = (key) => {
let url = '';
switch (key) {
case 'followup':
// TODO: 跳转随访患者列表
url = '/pages_app/patientMsg/patientMsg'
break;
case 'consult':
// TODO: 跳转公益咨询列表
url = '/pages_app/consult/consult'
break;
case 'flower':
// TODO: 跳转送花记录
//uni.showToast({ title: '查看送花记录', icon: 'none' })
url = '/pages_app/myFlower/myFlower'
break;
default:
break;
}
navTo({
url: url
})
}
const getIsBoundWechat = async () => {
const res = await my_api.isBoundWechat()
console.log(res)
if (res.code === 200 && res.data) {
isBoundWechat.value = res.data
}
}
const isBoundWechat = ref(false)
onShow(() => {
console.log('我的页面显示');
getUserInfoFromStorage() // 先从storage获取用户信息
fetchMyInfo() // 然后从API获取最新数据
getIsBoundWechat()
});
</script>
<style lang="scss" scoped>
// 颜色变量
$primary-color: #ff6b6b;
$theme-color: #8B2316;
$cyan-color: #00CED1;
$white: #fff;
$gray-bg: #f5f5f5;
$gray-light: #eee;
$gray-medium: #999;
$gray-dark: #666;
$text-color: #333;
// 尺寸变量
$border-radius: 8px;
$border-radius-small: 6px;
$padding: 15px;
$padding-small: 10px;
.page {
background-color: $gray-bg;
height: calc(100vh - 140rpx);
overflow-y: scroll;
padding-bottom: 100rpx;
}
// 用户信息卡片
.user-card {
background: url('@/static/big_background_my.png') no-repeat 0 0;
height: 310rpx;
padding: 0 30rpx;
background-size: cover;
position: relative;
margin-bottom: 67rpx;
.user-info {
padding-top: 30rpx;
display: flex;
align-items: center;
gap: 20rpx;
margin-bottom: 40rpx;
.avatar {
width: 120rpx;
height: 120rpx;
border-radius: 10rpx;
}
.user-info-content {
display: flex;
flex-direction: column;
align-items: flex-start;
gap: 10rpx;
.username {
color: $white;
font-size: 36rpx;
font-weight: bold;
}
.honor_box {
width: 500rpx;
/* 根据设计可调整宽度,使内容可横向滚动 */
white-space: nowrap;
}
.honor_wrap {
display: inline-flex;
flex-direction: row;
align-items: center;
gap: 10rpx;
}
.honor_item {
display: inline-flex;
flex-direction: row;
align-items: center;
gap: 10rpx;
flex: 0 0 auto;
padding: 6rpx 12rpx;
border: 2rpx solid rgba(255, 255, 255, 0.6);
border-radius: 24rpx;
background: rgba(255, 255, 255, 0.08);
}
.honor_image {
width: 24rpx;
height: 24rpx;
}
.honor_text {
font-size: 24rpx;
color: $white;
}
}
}
}
.stats-section {
position: relative;
background-color: $white;
border-radius: $border-radius;
padding: 30rpx;
display: flex;
justify-content: space-around;
margin-bottom: 20rpx;
.divder {
width: 2rpx;
height: 50rpx;
margin-top: 32rpx;
margin-left: 10rpx;
margin-right: 150rpx;
background-color: #999;
}
.signbox {
position: absolute;
right: 0;
top: 54rpx;
width: 160rpx;
height: 56rpx;
display: flex;
align-items: center;
border-radius: 30rpx 0 0 30rpx;
background: #fc564a url("@/static/qd1_bg.9.png")no-repeat 0 0;
background-size: 57rpx 56rpx;
.sign {
margin-left: 60rpx;
font-size: 28rpx;
color: #fff;
}
}
.signbox_1 {
position: absolute;
right: 0;
top: 54rpx;
width: 160rpx;
height: 56rpx;
display: flex;
align-items: center;
border: 1rpx solid #fc564a;
border-radius: 30rpx 0 0 30rpx;
background: #fff url("@/static/qd_bg.9.png")no-repeat 0 0;
background-size: 57rpx 56rpx;
.sign {
margin-left: 60rpx;
font-size: 28rpx;
color: #fc564a;
}
}
.stats-item {
display: flex;
flex-direction: column;
align-items: center;
gap: 10rpx;
.stats-number {
font-size: 48rpx;
color: $text-color;
}
.stats-label {
font-size: 24rpx;
color: $text-color;
}
}
}
.checkin-btn {
position: absolute;
top: 30rpx;
right: 30rpx;
background-color: $theme-color;
color: $white;
padding: 16rpx 24rpx;
border-radius: 40rpx;
display: flex;
align-items: center;
gap: 8rpx;
font-size: 28rpx;
}
// 通用section样式
.section {
background-color: $white;
margin: $padding-small;
border-radius: $border-radius;
padding: 26rpx;
.section-title {
font-size: 32rpx;
font-weight: bold;
color: $text-color;
margin-bottom: 30rpx;
}
}
// 服务网格
.learning-grid,
.operation-grid {
display: flex;
}
.service-item,
.learning-item,
.account-item,
.operation-item {
width: 130rpx;
display: flex;
flex-direction: column;
align-items: center;
gap: 16rpx;
padding: 20rpx;
text {
white-space: nowrap;
font-size: 26rpx;
color: $text-color;
text-align: center;
}
}
.setbox {
margin: 0 26rpx;
border-radius: 20rpx;
overflow: hidden;
background-color: #fff;
margin-bottom: 230rpx;
}
// 新增模块样式
.benefit-section,
.invoice-section,
.bank-section,
.settings-section {
border-radius: $border-radius;
margin-bottom: 0;
padding: 0;
.benefit-item,
.invoice-item,
.bank-item,
.settings-item {
display: flex;
align-items: center;
padding: 14rpx;
background-color: $white;
border-bottom: 2rpx solid #efefef;
.benefit-icon,
.invoice-icon,
.bank-icon,
.settings-icon {
width: 80rpx;
height: 80rpx;
display: flex;
align-items: center;
justify-content: center;
margin-right: 20rpx;
}
.benefit-content,
.invoice-content,
.bank-content,
.settings-content {
flex: 1;
.benefit-title,
.invoice-title,
.bank-title,
.settings-title {
font-size: 26rpx;
color: $text-color;
font-weight: 500;
}
}
.benefit-arrow,
.invoice-arrow,
.bank-arrow,
.settings-arrow {
width: 30rpx;
height: 30rpx;
display: flex;
align-items: center;
justify-content: center;
}
}
}
// 年度总结悬浮按钮
.year-summary-btn {
position: fixed;
bottom: 200rpx;
right: 0rpx;
width: 150rpx;
height: 80rpx;
background: linear-gradient(135deg, $cyan-color 0%, #20B2AA 100%);
border-radius: 60rpx 0 0 60rpx;
justify-content: flex-start;
align-items: center;
color: $white;
display: flex;
box-shadow: 0 8rpx 24rpx rgba(0, 206, 209, 0.3);
z-index: 999;
.year-text {
font-size: 24rpx;
font-weight: bold;
width: 70rpx;
height: 70rpx;
display: flex;
margin-left: 5rpx;
justify-content: center;
align-items: center;
color: #3cc7c0;
border-radius: 50%;
background-color: #fff;
}
.summary-text {
font-weight: bold;
width: 50rpx;
margin-left: 10rpx;
font-size: 20rpx;
}
}
// 底部导航栏
.bottom-nav {
position: fixed;
bottom: 0;
left: 0;
right: 0;
background-color: $white;
display: flex;
border-top: 1px solid $gray-light;
padding: 16rpx 0;
z-index: 1000;
.nav-item {
flex: 1;
display: flex;
flex-direction: column;
align-items: center;
gap: 8rpx;
font-size: 20rpx;
color: $gray-medium;
&.active {
color: $theme-color;
}
}
}
</style>