Files
msh-system/msh_single_uniapp/pages/tool/my-profile.vue
msh-agent 1224ed328b feat(my-profile): 隐藏未开发功能项,新增食谱计算历史入口
- 移除统计卡片中的「关注」(功能未实现)
- 移除「我的健康」中的「健康档案」(未实现)
- 整段隐藏「我的内容」(点赞/收藏/食谱均未实现)
- 「工具与服务」仅保留「邀请有礼」(移除营养师/消息通知/营养指导/用药指导)
- 整段隐藏「设置」(账号/隐私/帮助/关于均未实现);版本号下沉到底部独立展示
- 新增「我的健康」分组下的「食谱计算历史」入口 → /pages/tool/calculator-history
- 同步清理未使用的 data 字段、icon 资源与方法

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-03 03:37:32 +08:00

465 lines
10 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>
<view class="my-profile-page">
<!-- 用户信息 -->
<view class="profile-header">
<view class="user-info-section">
<view class="user-avatar">
<text class="avatar-icon">👤</text>
</view>
<view class="user-details">
<view class="user-name-row">
<text class="user-name">{{ userInfo.name }}</text>
<view class="verified-badge">
<image class="verified-icon" :src="iconVerified" mode="aspectFit"></image>
</view>
</view>
<view class="user-tags">
<view class="user-tag">{{ userInfo.stage }}</view>
<text class="user-id">ID: {{ userInfo.id }}</text>
</view>
</view>
</view>
</view>
<!-- 内容区域 -->
<scroll-view class="content-scroll" scroll-y>
<!-- 统计数据卡片仅展示已实现入口的统计隐藏关注入口相关功能尚未开发 -->
<view class="stats-card">
<view class="stat-item" @click="goToCheckin">
<text class="stat-value">{{ stats.checkin }}</text>
<text class="stat-label">打卡</text>
</view>
<view class="stat-item" @click="goToPoints">
<text class="stat-value">{{ stats.points }}</text>
<text class="stat-label">积分</text>
</view>
</view>
<!-- 我的健康 -->
<view class="section-card">
<view class="section-title">我的健康</view>
<view class="menu-list">
<view class="menu-item" @click="goToDietRecord">
<text class="menu-icon">📊</text>
<text class="menu-text">饮食记录</text>
<view class="menu-badge">{{ dietRecordCount }}</view>
</view>
<!-- 食谱计算历史入口test-0415 反馈2-2 后的产品落地 -->
<view class="menu-item" @click="goToCalculatorHistory">
<text class="menu-icon">🧮</text>
<text class="menu-text">食谱计算历史</text>
</view>
</view>
</view>
<!-- 工具与服务仅保留已实现入口其它项隐藏 -->
<view class="section-card">
<view class="section-title">工具与服务</view>
<view class="menu-list">
<view class="menu-item" @click="goToInvite">
<image class="menu-icon-img" :src="iconGift" mode="aspectFit"></image>
<text class="menu-text">邀请有礼</text>
</view>
</view>
</view>
<!-- 退出登录按钮 -->
<view class="logout-btn" @click="handleLogout">
<image class="logout-icon" :src="iconLogout" mode="aspectFit"></image>
<text>退出登录</text>
</view>
<!-- 版本号关于我们入口已隐藏版本信息直接展示在底部 -->
<view class="version-tip">
<text class="version-tip-text">v2.0</text>
</view>
<!-- 底部安全距离 -->
<view class="safe-bottom"></view>
</scroll-view>
</view>
</template>
<script>
import { getUserPoints, getCheckinStreak } from '@/api/tool.js';
import { mapGetters } from 'vuex';
export default {
computed: {
...mapGetters({ storeUserInfo: 'userInfo', uid: 'uid', isLogin: 'isLogin' })
},
data() {
return {
// 仅保留模板还在使用的图标资源;其它未开发入口已隐藏,对应图标无需加载
iconVerified: 'https://www.figma.com/api/mcp/asset/e06ebfe5-bf8d-40e7-9b5f-a395c823127b',
iconGift: 'https://www.figma.com/api/mcp/asset/afaeb0a1-7276-4a8c-87c0-ba4dc4ce3eba',
iconLogout: 'https://www.figma.com/api/mcp/asset/a4d5597f-0287-4411-a173-1e62db3c6c9f',
userInfo: {
name: '慢友小张',
stage: '透析期',
id: '1001'
},
stats: {
checkin: 0,
points: 0
},
dietRecordCount: 0
}
},
onLoad() {
this.syncUserInfo();
this.loadProfileStats();
},
onShow() {
this.syncUserInfo();
this.loadProfileStats();
},
methods: {
syncUserInfo() {
if (this.isLogin && this.storeUserInfo) {
this.userInfo = {
name: this.storeUserInfo.nickname || '慢友小张',
stage: this.storeUserInfo.level || '透析期',
id: this.uid || '1001'
}
}
},
async loadProfileStats() {
try {
const [pointsRes, streakRes] = await Promise.all([
getUserPoints().catch(() => ({ data: {} })),
getCheckinStreak().catch(() => ({ data: {} }))
]);
const pointsData = pointsRes.data || {};
const streakData = streakRes.data || {};
this.stats = {
checkin: streakData.totalCheckins || streakData.currentStreak || this.stats.checkin,
points: pointsData.points || pointsData.totalPoints || this.stats.points
};
this.dietRecordCount = streakData.totalCheckins || this.dietRecordCount;
} catch (error) {
console.error('加载个人统计失败:', error);
}
},
// 仅保留已实现入口的方法未开发功能项已从模板移除避免点击只弹「开发中」toast
goToCheckin() {
uni.navigateTo({ url: '/pages/tool/checkin' })
},
goToPoints() {
uni.navigateTo({ url: '/pages/tool/points-rules' })
},
goToDietRecord() {
uni.navigateTo({ url: '/pages/tool/dietary-records' })
},
goToCalculatorHistory() {
uni.navigateTo({ url: '/pages/tool/calculator-history' })
},
goToInvite() {
uni.navigateTo({ url: '/pages/tool/invite-rewards' })
},
handleLogout() {
uni.showModal({
title: '提示',
content: '确定要退出登录吗?',
success: (res) => {
if (res.confirm) {
// 清除本地存储的登录信息
uni.removeStorageSync('token')
uni.removeStorageSync('userInfo')
uni.removeStorageSync('uid')
uni.removeStorageSync('expires_time')
// 清除 Vuex 状态
this.$store.commit('LOGOUT')
uni.showToast({
title: '退出登录成功',
icon: 'success'
})
// 跳转到登录页或首页
setTimeout(() => {
uni.reLaunch({
url: '/pages/index/index'
})
}, 1500)
}
}
})
}
}
}
</script>
<style lang="scss" scoped>
.my-profile-page {
min-height: 100vh;
background: linear-gradient(180deg, #f8f9fa 0%, #e9ecef 100%);
display: flex;
flex-direction: column;
}
/* 顶部导航栏和用户信息 */
.profile-header {
background: linear-gradient(135deg, #ff8c52 0%, #ff7f50 50%, #ff6b35 100%);
padding-top: 0;
position: relative;
overflow: hidden;
&::before {
content: '';
position: absolute;
right: -80rpx;
top: -80rpx;
width: 384rpx;
height: 384rpx;
background: rgba(255, 255, 255, 0.1);
border-radius: 50%;
filter: blur(60rpx);
}
&::after {
content: '';
position: absolute;
left: -80rpx;
bottom: -80rpx;
width: 320rpx;
height: 320rpx;
background: rgba(0, 0, 0, 0.05);
border-radius: 50%;
filter: blur(40rpx);
}
}
.user-info-section {
display: flex;
align-items: center;
gap: 1rpx;
padding: calc(var(--status-bar-height, 0) + 1rpx) 32rpx 32rpx;
position: relative;
z-index: 1;
}
.user-avatar {
width: 128rpx;
height: 128rpx; margin-right: 24rpx;
background: #ffffff;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
box-shadow: 0 40rpx 50rpx rgba(0, 0, 0, 0.1), 0 16rpx 20rpx rgba(0, 0, 0, 0.1);
.avatar-icon {
font-size: 60rpx;
}
}
.user-details {
flex: 1;
display: flex;
flex-direction: column;
gap: 20rpx;
}
.user-name-row {
display: flex;
align-items: center;
gap: 16rpx;
.user-name {
font-size: 36rpx;
color: #ffffff;
font-weight: 500;
text-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.15);
}
.verified-badge {
width: 32rpx;
height: 32rpx;
background: #ff6b35;
border: 2rpx solid #ffffff;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
.verified-icon {
width: 20rpx;
height: 20rpx;
}
}
}
.user-tags {
display: flex;
align-items: center;
gap: 16rpx;
.user-tag {
background: rgba(255, 255, 255, 0.2);
border: 1rpx solid rgba(255, 255, 255, 0.3);
border-radius: 50rpx;
padding: 4rpx 20rpx;
font-size: 24rpx;
color: #ffffff;
}
.user-id {
font-size: 24rpx;
color: rgba(255, 255, 255, 0.8);
text-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1);
}
}
/* 内容滚动区域 */
.content-scroll {
flex: 1;
padding: 0;
}
/* 统计数据卡片 */
.stats-card {
background: #ffffff;
border-radius: 32rpx;
padding: 20rpx;
margin: 32rpx 32rpx 0;
display: flex;
justify-content: space-around;
box-shadow: 0 20rpx 30rpx rgba(0, 0, 0, 0.1), 0 8rpx 12rpx rgba(0, 0, 0, 0.1);
}
.stat-item {
display: flex;
flex-direction: column;
align-items: center;
gap: 8rpx;
flex: 1;
.stat-value {
font-size: 40rpx;
color: #1e2939;
font-weight: 500;
}
.stat-label {
font-size: 24rpx;
color: #6a7282;
}
}
/* 通用卡片样式 */
.section-card {
background: #ffffff;
border: 1rpx solid #e8eaed;
border-radius: 24rpx;
margin: 32rpx;
padding: 24rpx;
}
.section-title {
font-size: 28rpx;
color: #9fa5c0;
margin-bottom: 16rpx;
padding-left: 16rpx;
}
.menu-list {
display: flex;
flex-direction: column;
gap: 8rpx;
}
.menu-item {
display: flex;
align-items: center;
gap: 24rpx;
padding: 8rpx 16rpx;
border-radius: 16rpx;
min-height: 80rpx;
transition: background-color 0.2s;
&:active {
background: #f8f9fa;
}
}
.menu-icon {
font-size: 40rpx;
width: 40rpx;
height: 40rpx;
display: flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
}
.menu-icon-img {
width: 40rpx;
height: 40rpx;
flex-shrink: 0;
}
.menu-text {
flex: 1;
font-size: 28rpx;
color: #2e3e5c;
}
.menu-badge {
background: linear-gradient(180deg, #fff5f0 0%, #ffe8dc 100%);
border: 1rpx solid rgba(255, 107, 53, 0.3);
border-radius: 50rpx;
padding: 4rpx 16rpx;
font-size: 24rpx;
color: #ff6b35;
flex-shrink: 0;
&.online {
background: linear-gradient(180deg, #fff5f0 0%, #ffe8dc 100%);
border: 1rpx solid rgba(255, 107, 53, 0.3);
color: #ff6b35;
}
}
/* 退出登录按钮 */
.logout-btn {
background: #ffffff;
border-radius: 24rpx;
height: 96rpx;
margin: 0 32rpx 32rpx;
display: flex;
align-items: center;
justify-content: center;
gap: 16rpx;
box-shadow: 0 2rpx 6rpx rgba(0, 0, 0, 0.1);
.logout-icon {
width: 40rpx;
height: 40rpx;
}
text {
font-size: 32rpx;
color: #364153;
font-weight: 500;
}
}
/* 版本号(替代原「关于我们」入口) */
.version-tip {
text-align: center;
padding: 20rpx 0;
}
.version-tip-text {
font-size: 22rpx;
color: #9fa5c0;
}
/* 底部安全距离 */
.safe-bottom {
height: 40rpx;
}
</style>