feat: 增加数据统计自定义功能
This commit is contained in:
@@ -6,7 +6,7 @@ import {
|
|||||||
getPlan,
|
getPlan,
|
||||||
savePlan,
|
savePlan,
|
||||||
getDefaultRecordValue,
|
getDefaultRecordValue,
|
||||||
saveDefaultRecordValue
|
saveDefaultRecordValue, getStats, saveStats
|
||||||
} from "@/utils/profile";
|
} from "@/utils/profile";
|
||||||
|
|
||||||
onLaunch(() => {
|
onLaunch(() => {
|
||||||
@@ -27,6 +27,9 @@ onLaunch(() => {
|
|||||||
if (getPlan().length === 0) {
|
if (getPlan().length === 0) {
|
||||||
savePlan(['weight', 'sleep', 'sport', 'bloodPressure'])
|
savePlan(['weight', 'sleep', 'sport', 'bloodPressure'])
|
||||||
}
|
}
|
||||||
|
if (getStats().length === 0) {
|
||||||
|
saveStats(['weight', 'sleep', 'sport', 'bloodPressure', 'bloodSugar', 'temperature'])
|
||||||
|
}
|
||||||
console.log("App Launch");
|
console.log("App Launch");
|
||||||
});
|
});
|
||||||
onShow(() => {
|
onShow(() => {
|
||||||
|
|||||||
46
src/components/Profile/StatsPopup.vue
Normal file
46
src/components/Profile/StatsPopup.vue
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
<template>
|
||||||
|
<wd-popup
|
||||||
|
v-model="profileStore.showStatsPopup"
|
||||||
|
position="bottom"
|
||||||
|
:safe-area-inset-bottom="true"
|
||||||
|
custom-style="border-radius: 32rpx 32rpx 0 0; padding: 40rpx 32rpx"
|
||||||
|
>
|
||||||
|
<view class="mb-4 text-center text-base text-gray-700 font-semibold">
|
||||||
|
数据统计
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<wd-checkbox-group v-model="profileStore.statsList" type="button">
|
||||||
|
<wd-checkbox name="weight">体重统计</wd-checkbox>
|
||||||
|
<wd-checkbox name="sleep">睡眠统计</wd-checkbox>
|
||||||
|
<wd-checkbox name="sport">运动统计</wd-checkbox>
|
||||||
|
<wd-checkbox name="bloodPressure">血压统计</wd-checkbox>
|
||||||
|
<wd-checkbox name="bloodSugar">血糖统计</wd-checkbox>
|
||||||
|
<wd-checkbox name="temperature">体温统计</wd-checkbox>
|
||||||
|
</wd-checkbox-group>
|
||||||
|
|
||||||
|
<view class="flex w-full items-center justify-evenly">
|
||||||
|
<wd-button type="info" @click="cancelClick">
|
||||||
|
取消
|
||||||
|
</wd-button>
|
||||||
|
<wd-button type="primary" @click="saveClick">
|
||||||
|
保存
|
||||||
|
</wd-button>
|
||||||
|
</view>
|
||||||
|
</wd-popup>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { useProfileStore } from '@/store/profile'
|
||||||
|
import { saveStats } from "@/utils/profile";
|
||||||
|
|
||||||
|
const profileStore = useProfileStore()
|
||||||
|
|
||||||
|
function cancelClick() {
|
||||||
|
profileStore.showStatsPopup = false
|
||||||
|
}
|
||||||
|
|
||||||
|
function saveClick() {
|
||||||
|
saveStats(profileStore.statsList)
|
||||||
|
profileStore.showStatsPopup = false
|
||||||
|
}
|
||||||
|
</script>
|
||||||
@@ -8,7 +8,7 @@
|
|||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<wd-card title="体重">
|
<wd-card v-if="profileStore.statsList.includes('weight')" title="体重">
|
||||||
<qiun-data-charts
|
<qiun-data-charts
|
||||||
v-if="weightChartData.categories?.length"
|
v-if="weightChartData.categories?.length"
|
||||||
type="line"
|
type="line"
|
||||||
@@ -19,7 +19,7 @@
|
|||||||
<wd-empty v-else icon="no-content" tip="暂无记录" />
|
<wd-empty v-else icon="no-content" tip="暂无记录" />
|
||||||
</wd-card>
|
</wd-card>
|
||||||
|
|
||||||
<wd-card title="睡眠">
|
<wd-card v-if="profileStore.statsList.includes('sleep')" title="睡眠">
|
||||||
<qiun-data-charts
|
<qiun-data-charts
|
||||||
v-if="sleepChartData.categories?.length"
|
v-if="sleepChartData.categories?.length"
|
||||||
type="line"
|
type="line"
|
||||||
@@ -30,7 +30,7 @@
|
|||||||
<wd-empty v-else icon="no-content" tip="暂无记录" />
|
<wd-empty v-else icon="no-content" tip="暂无记录" />
|
||||||
</wd-card>
|
</wd-card>
|
||||||
|
|
||||||
<wd-card title="运动">
|
<wd-card v-if="profileStore.statsList.includes('sport')" title="运动">
|
||||||
<qiun-data-charts
|
<qiun-data-charts
|
||||||
v-if="sportChartData.categories?.length"
|
v-if="sportChartData.categories?.length"
|
||||||
type="line"
|
type="line"
|
||||||
@@ -41,7 +41,7 @@
|
|||||||
<wd-empty v-else icon="no-content" tip="暂无记录" />
|
<wd-empty v-else icon="no-content" tip="暂无记录" />
|
||||||
</wd-card>
|
</wd-card>
|
||||||
|
|
||||||
<wd-card title="血压">
|
<wd-card v-if="profileStore.statsList.includes('bloodPressure')" title="血压">
|
||||||
<qiun-data-charts
|
<qiun-data-charts
|
||||||
v-if="bloodPressureChartData.categories?.length"
|
v-if="bloodPressureChartData.categories?.length"
|
||||||
type="line"
|
type="line"
|
||||||
@@ -52,7 +52,18 @@
|
|||||||
<wd-empty v-else icon="no-content" tip="暂无记录" />
|
<wd-empty v-else icon="no-content" tip="暂无记录" />
|
||||||
</wd-card>
|
</wd-card>
|
||||||
|
|
||||||
<wd-card title="血糖">
|
<wd-card v-if="profileStore.statsList.includes('bloodPressure')" title="心率">
|
||||||
|
<qiun-data-charts
|
||||||
|
v-if="heartRateChartData.categories?.length"
|
||||||
|
type="line"
|
||||||
|
:opts="chartOpts"
|
||||||
|
:chartData="heartRateChartData"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<wd-empty v-else icon="no-content" tip="暂无记录" />
|
||||||
|
</wd-card>
|
||||||
|
|
||||||
|
<wd-card v-if="profileStore.statsList.includes('bloodSugar')" title="血糖">
|
||||||
<qiun-data-charts
|
<qiun-data-charts
|
||||||
v-if="bloodSugarChartData.categories?.length"
|
v-if="bloodSugarChartData.categories?.length"
|
||||||
type="line"
|
type="line"
|
||||||
@@ -63,7 +74,7 @@
|
|||||||
<wd-empty v-else icon="no-content" tip="暂无记录" />
|
<wd-empty v-else icon="no-content" tip="暂无记录" />
|
||||||
</wd-card>
|
</wd-card>
|
||||||
|
|
||||||
<wd-card title="体温">
|
<wd-card v-if="profileStore.statsList.includes('temperature')" title="体温">
|
||||||
<qiun-data-charts
|
<qiun-data-charts
|
||||||
v-if="temperatureChartData.categories?.length"
|
v-if="temperatureChartData.categories?.length"
|
||||||
type="line"
|
type="line"
|
||||||
@@ -80,6 +91,10 @@
|
|||||||
import { ref } from 'vue'
|
import { ref } from 'vue'
|
||||||
import { getRecentRecords } from '@/utils/record'
|
import { getRecentRecords } from '@/utils/record'
|
||||||
import { onShow } from "@dcloudio/uni-app";
|
import { onShow } from "@dcloudio/uni-app";
|
||||||
|
import { useProfileStore } from '@/store/profile'
|
||||||
|
import { getStats } from "@/utils/profile";
|
||||||
|
|
||||||
|
const profileStore = useProfileStore()
|
||||||
|
|
||||||
const weightChartData = ref({
|
const weightChartData = ref({
|
||||||
categories: [] as string[],
|
categories: [] as string[],
|
||||||
@@ -97,6 +112,10 @@ const bloodPressureChartData = ref({
|
|||||||
categories: [] as string[],
|
categories: [] as string[],
|
||||||
series: [] as any[]
|
series: [] as any[]
|
||||||
})
|
})
|
||||||
|
const heartRateChartData = ref({
|
||||||
|
categories: [] as string[],
|
||||||
|
series: [] as any[]
|
||||||
|
})
|
||||||
const bloodSugarChartData = ref({
|
const bloodSugarChartData = ref({
|
||||||
categories: [] as string[],
|
categories: [] as string[],
|
||||||
series: [] as any[]
|
series: [] as any[]
|
||||||
@@ -211,6 +230,25 @@ function getBloodPressureChartData() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getHeartRateChartData() {
|
||||||
|
const list = getRecentRecords('bloodPressure', 7)
|
||||||
|
|
||||||
|
if (list.length) {
|
||||||
|
const categories = list.map((_, index) => String(index + 1))
|
||||||
|
|
||||||
|
heartRateChartData.value = {
|
||||||
|
categories,
|
||||||
|
series: [
|
||||||
|
{ name: '心率(bpm)', data: list.map((r) => r.heartRate) },
|
||||||
|
],
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
heartRateChartData.value = {
|
||||||
|
categories: [], series: []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function getBloodSugarChartData() {
|
function getBloodSugarChartData() {
|
||||||
const list = getRecentRecords('bloodSugar', 7)
|
const list = getRecentRecords('bloodSugar', 7)
|
||||||
|
|
||||||
@@ -256,10 +294,12 @@ function getTemperatureChartData() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onShow(() => {
|
onShow(() => {
|
||||||
|
profileStore.statsList = getStats()
|
||||||
getWeightChartData()
|
getWeightChartData()
|
||||||
getSleepChartData()
|
getSleepChartData()
|
||||||
getSportChartData()
|
getSportChartData()
|
||||||
getBloodPressureChartData()
|
getBloodPressureChartData()
|
||||||
|
getHeartRateChartData()
|
||||||
getBloodSugarChartData()
|
getBloodSugarChartData()
|
||||||
getTemperatureChartData()
|
getTemperatureChartData()
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -42,6 +42,7 @@
|
|||||||
<wd-cell size="large" title="记录默认值" is-link @click="openDefaultPopup"/>
|
<wd-cell size="large" title="记录默认值" is-link @click="openDefaultPopup"/>
|
||||||
<wd-cell size="large" title="今日概览" is-link @click="openOverviewPopup"/>
|
<wd-cell size="large" title="今日概览" is-link @click="openOverviewPopup"/>
|
||||||
<wd-cell size="large" title="今日计划" is-link @click="openPlanPopup"/>
|
<wd-cell size="large" title="今日计划" is-link @click="openPlanPopup"/>
|
||||||
|
<wd-cell size="large" title="数据统计" is-link @click="openStatsPopup"/>
|
||||||
<wd-cell size="large" title="存储详情" is-link @click="openStoragePopup"/>
|
<wd-cell size="large" title="存储详情" is-link @click="openStoragePopup"/>
|
||||||
</wd-cell-group>
|
</wd-cell-group>
|
||||||
|
|
||||||
@@ -55,6 +56,8 @@
|
|||||||
|
|
||||||
<plan-popup />
|
<plan-popup />
|
||||||
|
|
||||||
|
<stats-popup />
|
||||||
|
|
||||||
<default-popup />
|
<default-popup />
|
||||||
|
|
||||||
<point-popup />
|
<point-popup />
|
||||||
@@ -67,7 +70,7 @@ import StoragePopup from "@/components/Profile/StoragePopup.vue";
|
|||||||
import OverviewPopup from "@/components/Profile/OverviewPopup.vue";
|
import OverviewPopup from "@/components/Profile/OverviewPopup.vue";
|
||||||
import PlanPopup from "@/components/Profile/PlanPopup.vue";
|
import PlanPopup from "@/components/Profile/PlanPopup.vue";
|
||||||
import { computed, ref, watch } from 'vue'
|
import { computed, ref, watch } from 'vue'
|
||||||
import { getDefaultRecordValue, getOverview, getPlan, getProfile } from '@/utils/profile'
|
import { getDefaultRecordValue, getOverview, getPlan, getProfile, getStats } from '@/utils/profile'
|
||||||
import { useProfileStore } from '@/store/profile'
|
import { useProfileStore } from '@/store/profile'
|
||||||
import { useAppStore } from "@/store/app";
|
import { useAppStore } from "@/store/app";
|
||||||
import type { IProfile } from "@/type/profile";
|
import type { IProfile } from "@/type/profile";
|
||||||
@@ -76,6 +79,7 @@ import DefaultPopup from "@/components/Profile/DefaultPopup.vue";
|
|||||||
import { getAchievement, getPoints, getRecordCount } from "@/utils/points";
|
import { getAchievement, getPoints, getRecordCount } from "@/utils/points";
|
||||||
import { onShow } from "@dcloudio/uni-app";
|
import { onShow } from "@dcloudio/uni-app";
|
||||||
import PointPopup from "@/components/Profile/PointPopup.vue";
|
import PointPopup from "@/components/Profile/PointPopup.vue";
|
||||||
|
import StatsPopup from "@/components/Profile/StatsPopup.vue";
|
||||||
|
|
||||||
const profileStore = useProfileStore()
|
const profileStore = useProfileStore()
|
||||||
const appStore = useAppStore()
|
const appStore = useAppStore()
|
||||||
@@ -122,6 +126,11 @@ function openPlanPopup() {
|
|||||||
profileStore.showPlanPopup = true
|
profileStore.showPlanPopup = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function openStatsPopup() {
|
||||||
|
profileStore.statsList = getStats()
|
||||||
|
profileStore.showStatsPopup = true
|
||||||
|
}
|
||||||
|
|
||||||
function openStoragePopup() {
|
function openStoragePopup() {
|
||||||
profileStore.storageStats = countRecordsByMonth()
|
profileStore.storageStats = countRecordsByMonth()
|
||||||
profileStore.storageTotal = getTotalCount()
|
profileStore.storageTotal = getTotalCount()
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ export const useProfileStore = defineStore('profile', {
|
|||||||
showStoragePopup: false,
|
showStoragePopup: false,
|
||||||
showOverviewPopup: false,
|
showOverviewPopup: false,
|
||||||
showPlanPopup: false,
|
showPlanPopup: false,
|
||||||
|
showStatsPopup: false,
|
||||||
showDefaultRecordValuePopup: false,
|
showDefaultRecordValuePopup: false,
|
||||||
showPointPopup: false,
|
showPointPopup: false,
|
||||||
profileForm: {
|
profileForm: {
|
||||||
@@ -29,6 +30,7 @@ export const useProfileStore = defineStore('profile', {
|
|||||||
storageMax: 1000,
|
storageMax: 1000,
|
||||||
overviewList: [] as string[],
|
overviewList: [] as string[],
|
||||||
planList: [] as string[],
|
planList: [] as string[],
|
||||||
|
statsList: [] as string[],
|
||||||
defaultList: [],
|
defaultList: [],
|
||||||
isRefresh: false,
|
isRefresh: false,
|
||||||
}),
|
}),
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import type {IDefaultRecordValue, IProfile} from "@/type/profile";
|
|||||||
const PROFILE_KEY = 'user_profile'
|
const PROFILE_KEY = 'user_profile'
|
||||||
const OVERVIEW_KEY = 'user_overview'
|
const OVERVIEW_KEY = 'user_overview'
|
||||||
const PLAN_KEY = 'user_plan'
|
const PLAN_KEY = 'user_plan'
|
||||||
|
const STATS_KEY = 'user_stats'
|
||||||
const DEFAULT_RECORD_VALUE_KEY = 'user_default_record_value'
|
const DEFAULT_RECORD_VALUE_KEY = 'user_default_record_value'
|
||||||
|
|
||||||
function getEmptyProfile(): IProfile {
|
function getEmptyProfile(): IProfile {
|
||||||
@@ -45,3 +46,11 @@ export function savePlan(data: string[]) {
|
|||||||
wx.setStorageSync(PLAN_KEY, data)
|
wx.setStorageSync(PLAN_KEY, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getStats(): string[] {
|
||||||
|
return wx.getStorageSync(STATS_KEY) || []
|
||||||
|
}
|
||||||
|
|
||||||
|
export function saveStats(data: string[]) {
|
||||||
|
wx.setStorageSync(STATS_KEY, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user