整合api请求、添加购买会员卡页面、登陆页面

This commit is contained in:
future
2026-06-23 22:17:53 +08:00
parent 1c547a717e
commit 8d8c823616
70 changed files with 7666 additions and 2656 deletions
@@ -1,47 +1,28 @@
<template>
<view class="scroll-container theme-light">
<view class="bt-page">
<MemberInfoSubNav title="智能体测" @back="goBack" />
<view class="bt-page__action-bar bt-page__action-bar--end">
<text
class="bt-page__action-link"
hover-class="mi-tap--hover"
:hover-stay-time="150"
@tap="goSettings"
>
体测设置
</text>
</view>
<MemberInfoSubNav title="体测" @back="goBack" />
<view class="bt-page__body">
<view class="bt-hero">
<view class="bt-hero__top">
<text class="bt-hero__label">最新体测评分</text>
<view class="bt-hero__badge">
<text class="bt-hero__badge-text">{{ latest?.status || '暂无数据' }}</text>
<view v-if="latest" class="bt-hero">
<view class="bt-hero__time">
<image class="bt-hero__time-icon" src="https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/images/clock.png" mode="aspectFit" />
<text class="bt-hero__time-text">{{ latest.testTime }}</text>
</view>
<view class="bt-hero__metrics">
<view
v-for="m in previewMetrics"
:key="m.key"
class="bt-hero__metric"
>
<text class="bt-hero__metric-value">{{ m.value }}</text>
<text class="bt-hero__metric-label">{{ m.label }}</text>
</view>
</view>
<view class="bt-hero__score-row">
<text class="bt-hero__score">{{ latest?.score ?? '--' }}</text>
<text class="bt-hero__grade">{{ latest?.grade ?? '' }} {{ latest?.gradeLabel ?? '' }}</text>
</view>
<text class="bt-hero__meta">
{{ latest ? `最近测量 · ${latest.date} ${latest.time}` : '完成首次体测,获取健康画像' }}
</text>
<view class="bt-hero__actions">
<view
class="bt-btn bt-btn--primary"
hover-class="mi-tap-btn--hover"
:hover-stay-time="150"
@tap="startMeasure"
>
<image class="bt-btn__icon" src="https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/images/activity.png" mode="aspectFit" />
<text class="bt-btn__text">开始体测</text>
</view>
<view
v-if="latest"
class="bt-btn bt-btn--ghost"
hover-class="mi-tap-btn--hover"
:hover-stay-time="150"
@tap="viewLatestReport"
>
<text class="bt-btn__text">查看报告</text>
@@ -50,142 +31,145 @@
</view>
<view class="bt-card">
<text class="bt-card__title">设备状态</text>
<view class="bt-device">
<view class="bt-device__icon-wrap">
<image class="bt-device__icon" src="https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/images/mappin2.png" mode="aspectFit" />
</view>
<view class="bt-device__info">
<text class="bt-device__name">{{ device.name }}</text>
<text
class="bt-device__status"
:class="{ 'bt-device__status--on': device.connected }"
>
{{ deviceStatusText }}
</text>
</view>
<view class="bt-card__header">
<text class="bt-card__title">快捷操作</text>
</view>
<view class="bt-quick-grid">
<view
class="bt-device__dot"
:class="{ 'bt-device__dot--on': device.connected }"
></view>
v-for="link in quickLinks"
:key="link.key"
class="bt-quick-item"
hover-class="mi-tap--hover"
:hover-stay-time="150"
@tap="onQuickLink(link.key)"
>
<image class="bt-quick-item__icon" :src="link.icon" mode="aspectFit" />
<text class="bt-quick-item__label">{{ link.label }}</text>
</view>
</view>
</view>
<view class="bt-card">
<text class="bt-card__title">快捷入口</text>
<view class="bt-grid">
<view class="bt-card__header">
<text class="bt-card__title">开始体测</text>
</view>
<view class="bt-device-status" @tap="startMeasure">
<view class="bt-device-status__icon-wrap">
<image
class="bt-device-status__icon"
src="https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/images/bluetooth.png"
mode="aspectFit"
/>
</view>
<view class="bt-device-status__info">
<text class="bt-device-status__name">{{ device.name || '体脂秤' }}</text>
<text class="bt-device-status__text">{{ deviceStatusText }}</text>
</view>
<image
class="bt-device-status__arrow"
src="https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/images/rightarrow.png"
mode="aspectFit"
/>
</view>
<view class="bt-card__actions">
<view
v-for="item in quickLinks"
:key="item.key"
class="bt-grid__item"
hover-class="mi-tap--hover"
class="bt-btn bt-btn--primary"
hover-class="mi-tap-btn--hover"
:hover-stay-time="150"
@tap="onQuickLink(item.key)"
@tap="startMeasure"
>
<image class="bt-grid__icon" :src="item.icon" mode="aspectFit" />
<text class="bt-grid__label">{{ item.label }}</text>
<text class="bt-btn__text">{{ device.connected ? '开始测量' : '连接设备' }}</text>
</view>
</view>
</view>
<view v-if="latest" class="bt-card">
<text class="bt-card__title">核心指标概览</text>
<view class="bt-metrics">
<view
v-for="m in previewMetrics"
:key="m.key"
class="bt-metric"
>
<text class="bt-metric__value">{{ m.value }}</text>
<text class="bt-metric__label">{{ m.label }}</text>
</view>
</view>
<view class="bt-settings-link" @tap="goSettings">
<text class="bt-settings-link__text">体测设置</text>
<image class="bt-settings-link__arrow" src="https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/images/rightarrow.png" mode="aspectFit" />
</view>
</view>
</view>
</view>
</template>
<script>
<script setup>
import { ref, computed } from 'vue'
import MemberInfoSubNav from '@/components/memberInfo/MemberInfoSubNav.vue'
import { PAGE, navigateToPage } from '@/common/constants/routes.js'
import { PAGE, navigateToPage, backToMemberCenter } from '@/common/constants/routes.js'
import { loadMemberStore } from '@/common/memberInfo/store.js'
import { getLatestBodyTestRecord } from '@/common/memberInfo/bodyTestStore.js'
import { subPageMixin } from '@/common/memberInfo/mixins.js'
export default {
components: { MemberInfoSubNav },
mixins: [subPageMixin],
data() {
return {
latest: null,
device: {},
quickLinks: [
{ key: 'history', label: '历史记录', icon: 'https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/images/clock.png' },
{ key: 'compare', label: '历史对比', icon: 'https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/images/trendingdown.png' },
{ key: 'trend', label: '趋势分析', icon: 'https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/images/activity.png' },
{ key: 'report', label: '体测报告', icon: 'https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/images/filetext.png' }
]
}
},
computed: {
deviceStatusText() {
if (this.device.connected) {
return `已连接 · 电量 ${this.device.battery}%`
}
return '未连接 · 点击开始体测进行配对'
},
previewMetrics() {
if (!this.latest?.metrics) return []
const m = this.latest.metrics
return [
{ key: 'weight', label: '体重(kg)', value: m.weight },
{ key: 'bmi', label: 'BMI', value: m.bmi },
{ key: 'bodyFat', label: '体脂率(%)', value: m.bodyFat },
{ key: 'muscleMass', label: '肌肉量(kg)', value: m.muscleMass }
]
}
},
onShow() {
this.refreshFromStore()
},
methods: {
refreshFromStore() {
const store = loadMemberStore()
this.latest = getLatestBodyTestRecord(store)
this.device = { ...store.bodyTest.device }
},
startMeasure() {
const store = loadMemberStore()
if (store.bodyTest.device.connected) {
navigateToPage(PAGE.BODY_TEST_MEASURING)
} else {
navigateToPage(PAGE.BODY_TEST_CONNECT)
}
},
viewLatestReport() {
if (!this.latest) return
navigateToPage(`${PAGE.BODY_TEST_REPORT}?id=${this.latest.id}`)
},
goSettings() {
navigateToPage(PAGE.BODY_TEST_SETTINGS)
},
onQuickLink(key) {
const routes = {
history: PAGE.BODY_TEST_HISTORY,
compare: PAGE.BODY_TEST_COMPARE,
trend: PAGE.BODY_TEST_TREND,
report: this.latest
? `${PAGE.BODY_TEST_REPORT}?id=${this.latest.id}`
: PAGE.BODY_TEST_HISTORY
}
navigateToPage(routes[key] || PAGE.BODY_TEST_HOME)
}
const latest = ref(null)
const device = ref({})
const quickLinks = ref([
{ key: 'history', label: '历史记录', icon: 'https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/images/clock.png' },
{ key: 'compare', label: '历史对比', icon: 'https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/images/trendingdown.png' },
{ key: 'trend', label: '趋势分析', icon: 'https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/images/activity.png' },
{ key: 'report', label: '体测报告', icon: 'https://gymfuture.oss-cn-chengdu.aliyuncs.com/static/images/filetext.png' }
])
const deviceStatusText = computed(() => {
if (device.value.connected) {
return `已连接 · 电量 ${device.value.battery}%`
}
return '未连接 · 点击开始体测进行配对'
})
const previewMetrics = computed(() => {
if (!latest.value?.metrics) return []
const m = latest.value.metrics
return [
{ key: 'weight', label: '体重(kg)', value: m.weight },
{ key: 'bmi', label: 'BMI', value: m.bmi },
{ key: 'bodyFat', label: '体脂率(%)', value: m.bodyFat },
{ key: 'muscleMass', label: '肌肉量(kg)', value: m.muscleMass }
]
})
function refreshFromStore() {
const store = loadMemberStore()
latest.value = getLatestBodyTestRecord(store)
device.value = { ...store.bodyTest.device }
}
function goBack() {
backToMemberCenter()
}
function startMeasure() {
const store = loadMemberStore()
if (store.bodyTest.device.connected) {
navigateToPage(PAGE.BODY_TEST_MEASURING)
} else {
navigateToPage(PAGE.BODY_TEST_CONNECT)
}
}
function viewLatestReport() {
if (!latest.value) return
navigateToPage(`${PAGE.BODY_TEST_REPORT}?id=${latest.value.id}`)
}
function goSettings() {
navigateToPage(PAGE.BODY_TEST_SETTINGS)
}
function onQuickLink(key) {
const routes = {
history: PAGE.BODY_TEST_HISTORY,
compare: PAGE.BODY_TEST_COMPARE,
trend: PAGE.BODY_TEST_TREND,
report: latest.value
? `${PAGE.BODY_TEST_REPORT}?id=${latest.value.id}`
: PAGE.BODY_TEST_HISTORY
}
navigateToPage(routes[key] || PAGE.BODY_TEST_HOME)
}
refreshFromStore()
</script>
<style>
<style lang="scss">
@import '@/common/style/base.css';
@import '@/common/style/memberInfo/pages/page-reset.css';
@import '@/common/style/memberInfo/pages/sub-page-base.css';