index.vue 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  1. <template>
  2. <view class="container">
  3. <!-- Tabbar 切换过渡页 -->
  4. <tab-transition v-if="showTabTransition" dimCode="body" ref="tabTransition" @close="showTabTransition = false" />
  5. <!-- 品牌头部 -->
  6. <PageBanner theme="body"
  7. tagline="主动健康 · 闭环管理"
  8. quote="测评→报告→方案→执行→追踪" />
  9. <!-- 未登录态 -->
  10. <template v-if="!isLoggedIn">
  11. <LoginGuideCard
  12. title="登录后查看全家健康数据"
  13. :items="[
  14. '查看全家健康报告和身体能量数据',
  15. '记录每日健康打卡,获取身体能量',
  16. '查看专属健康商品和活动价格'
  17. ]" />
  18. </template>
  19. <!-- 登录态 -->
  20. <template v-else>
  21. <!-- 家庭成员选择条 -->
  22. <FamilyMemberStrip
  23. :members="familyMembersVisible"
  24. :selectedMemberId="selectedMemberId"
  25. @select="onFamilyMemberSelect"
  26. @removed="loadFamilyMembersVisible" />
  27. <!-- 闭环入口网格 -->
  28. <view class="func-section">
  29. <view class="func-grid">
  30. <view class="func-item" @click="goReportList">
  31. <view class="func-icon-wrap" style="background: rgba(91,155,213,0.15);">
  32. <text class="func-icon">📊</text>
  33. </view>
  34. <text class="func-label">健康报告</text>
  35. </view>
  36. <view class="func-item" @click="goUploadReport">
  37. <view class="func-icon-wrap" style="background: rgba(16,185,129,0.15);">
  38. <text class="func-icon">📤</text>
  39. </view>
  40. <text class="func-label">上传报告</text>
  41. </view>
  42. <view class="func-item" @click="goCheckin">
  43. <view class="func-icon-wrap" style="background: rgba(249,115,22,0.15);">
  44. <text class="func-icon">✅</text>
  45. </view>
  46. <text class="func-label">健康打卡</text>
  47. </view>
  48. <view class="func-item" @click="goAssessment">
  49. <view class="func-icon-wrap" style="background: rgba(99,102,241,0.15);">
  50. <text class="func-icon">📋</text>
  51. </view>
  52. <text class="func-label">申请测评</text>
  53. </view>
  54. <view class="func-item" @click="goNutrition">
  55. <view class="func-icon-wrap" style="background: rgba(245,158,11,0.15);">
  56. <text class="func-icon">🍽️</text>
  57. </view>
  58. <text class="func-label">营养档案</text>
  59. </view>
  60. <view class="func-item" @click="goDiet">
  61. <view class="func-icon-wrap" style="background: rgba(239,68,68,0.15);">
  62. <text class="func-icon">🥗</text>
  63. </view>
  64. <text class="func-label">饮食推荐</text>
  65. </view>
  66. <view class="func-item" @click="goExercise">
  67. <view class="func-icon-wrap" style="background: rgba(34,197,94,0.15);">
  68. <text class="func-icon">🏃</text>
  69. </view>
  70. <text class="func-label">运动</text>
  71. </view>
  72. <view class="func-item" @click="goSleep">
  73. <view class="func-icon-wrap" style="background: rgba(139,92,246,0.15);">
  74. <text class="func-icon">😴</text>
  75. </view>
  76. <text class="func-label">作息</text>
  77. </view>
  78. <view class="func-item" @click="goMeditation">
  79. <view class="func-icon-wrap" style="background: rgba(236,72,153,0.15);">
  80. <text class="func-icon">🧘</text>
  81. </view>
  82. <text class="func-label">冥想</text>
  83. </view>
  84. <view class="func-item" @click="goTongue">
  85. <view class="func-icon-wrap" style="background: rgba(255,140,66,0.15);">
  86. <text class="func-icon">👅</text>
  87. </view>
  88. <text class="func-label">舌诊分析</text>
  89. </view>
  90. <view class="func-item" @click="goHealthDimensions">
  91. <view class="func-icon-wrap" style="background: rgba(6,182,212,0.15);">
  92. <text class="func-icon">🌏</text>
  93. </view>
  94. <text class="func-label">健康维度</text>
  95. </view>
  96. <view class="func-item" @click="goBodyDetail">
  97. <view class="func-icon-wrap" style="background: rgba(249,115,22,0.15);">
  98. <text class="func-icon">🔬</text>
  99. </view>
  100. <text class="func-label">身体能量</text>
  101. </view>
  102. </view>
  103. </view>
  104. </template>
  105. <AIFloatingAvatar />
  106. </view>
  107. </template>
  108. <script>
  109. import TabTransition from '../../components/tab-transition.vue'
  110. import PageBanner from '../../components/PageBanner.vue'
  111. import LoginGuideCard from '../../components/LoginGuideCard.vue'
  112. import FamilyMemberStrip from '../../components/FamilyMemberStrip.vue'
  113. import AIFloatingAvatar from '../../components/AIFloatingAvatar.vue'
  114. import { getVisibleFamilyMembers } from '../../utils/api.js'
  115. export default {
  116. components: {
  117. TabTransition,
  118. PageBanner,
  119. LoginGuideCard,
  120. FamilyMemberStrip,
  121. AIFloatingAvatar
  122. },
  123. data() {
  124. return {
  125. showTabTransition: true,
  126. isLoggedIn: false,
  127. familyMembersVisible: [],
  128. selectedMemberId: null
  129. }
  130. },
  131. onLoad() {
  132. this.isLoggedIn = !!uni.getStorageSync('token')
  133. if (this.isLoggedIn) {
  134. this.loadFamilyMembersVisible()
  135. }
  136. },
  137. onShow() {
  138. this.showTabTransition = true
  139. this.isLoggedIn = !!uni.getStorageSync('token')
  140. this._watchPageReady()
  141. },
  142. methods: {
  143. loadFamilyMembersVisible() {
  144. var self = this
  145. getVisibleFamilyMembers().then(function(res) {
  146. if (res.code === 200 && res.data) {
  147. self.familyMembersVisible = Array.isArray(res.data) ? res.data : (res.data.list || [])
  148. }
  149. }).catch(function() {})
  150. },
  151. onFamilyMemberSelect(member) {
  152. this.selectedMemberId = member.id
  153. },
  154. _watchPageReady() {
  155. var self = this
  156. this.$nextTick(function() {
  157. if (self.$refs.tabTransition) self.$refs.tabTransition.markReady()
  158. })
  159. },
  160. goReportList() {
  161. uni.navigateTo({ url: '/pages/health/report-list' })
  162. },
  163. goUploadReport() {
  164. uni.navigateTo({ url: '/pages/health/report-upload' })
  165. },
  166. goCheckin() {
  167. uni.navigateTo({ url: '/pages/health/daily-checkin' })
  168. },
  169. goAssessment() {
  170. uni.navigateTo({ url: '/pages/assessment/apply' })
  171. },
  172. goNutrition() {
  173. var id = this.selectedMemberId || ''
  174. uni.navigateTo({ url: '/pages/health/nutrition-profile?memberId=' + id })
  175. },
  176. goDiet() {
  177. uni.navigateTo({ url: '/pages/meal/recommend' })
  178. },
  179. goExercise() {
  180. uni.navigateTo({ url: '/pages/health/exercise-index' })
  181. },
  182. goSleep() {
  183. uni.navigateTo({ url: '/pages/health/sleep-index' })
  184. },
  185. goMeditation() {
  186. uni.navigateTo({ url: '/pages/health/meditation-index' })
  187. },
  188. goTongue() {
  189. uni.navigateTo({ url: '/pages/health/report-upload?reportType=tongue' })
  190. },
  191. goHealthDimensions() {
  192. var id = this.selectedMemberId || ''
  193. uni.navigateTo({ url: '/pages/body-detail/health-dimensions?memberId=' + id })
  194. },
  195. goBodyDetail() {
  196. var id = this.selectedMemberId || ''
  197. uni.navigateTo({ url: '/pages/body-detail/health-report?memberId=' + id })
  198. }
  199. }
  200. }
  201. </script>
  202. <style scoped>
  203. .container {
  204. min-height: 100vh;
  205. background: #f5f7fa;
  206. padding-bottom: 120rpx;
  207. }
  208. .func-section {
  209. margin: 20rpx 30rpx;
  210. }
  211. .func-grid {
  212. display: flex;
  213. flex-wrap: wrap;
  214. gap: 20rpx;
  215. }
  216. .func-item {
  217. width: calc(25% - 15rpx);
  218. display: flex;
  219. flex-direction: column;
  220. align-items: center;
  221. padding: 24rpx 0;
  222. background: #fff;
  223. border-radius: 16rpx;
  224. box-shadow: 0 2rpx 8rpx rgba(0,0,0,0.05);
  225. }
  226. .func-item:active {
  227. opacity: 0.7;
  228. }
  229. .func-icon-wrap {
  230. width: 72rpx;
  231. height: 72rpx;
  232. border-radius: 50%;
  233. display: flex;
  234. align-items: center;
  235. justify-content: center;
  236. margin-bottom: 10rpx;
  237. }
  238. .func-icon {
  239. font-size: 32rpx;
  240. }
  241. .func-label {
  242. font-size: 22rpx;
  243. color: #333;
  244. text-align: center;
  245. }
  246. </style>