feat: 增加存储详情功能
This commit is contained in:
@@ -54,6 +54,7 @@
|
|||||||
"@dcloudio/uni-mp-xhs": "3.0.0-5020420260813003",
|
"@dcloudio/uni-mp-xhs": "3.0.0-5020420260813003",
|
||||||
"@dcloudio/uni-quickapp-webview": "3.0.0-5020420260813003",
|
"@dcloudio/uni-quickapp-webview": "3.0.0-5020420260813003",
|
||||||
"@wot-ui/ui": "^2.3.2",
|
"@wot-ui/ui": "^2.3.2",
|
||||||
|
"miniprogram-api-typings": "^5.2.3",
|
||||||
"pinia": "^4.0.3",
|
"pinia": "^4.0.3",
|
||||||
"vue": "^3.4.21",
|
"vue": "^3.4.21",
|
||||||
"vue-i18n": "^9.1.9"
|
"vue-i18n": "^9.1.9"
|
||||||
|
|||||||
12
pnpm-lock.yaml
generated
12
pnpm-lock.yaml
generated
@@ -59,6 +59,9 @@ importers:
|
|||||||
'@wot-ui/ui':
|
'@wot-ui/ui':
|
||||||
specifier: ^2.3.2
|
specifier: ^2.3.2
|
||||||
version: 2.3.2(vue@3.5.41(typescript@4.9.5))
|
version: 2.3.2(vue@3.5.41(typescript@4.9.5))
|
||||||
|
miniprogram-api-typings:
|
||||||
|
specifier: ^5.2.3
|
||||||
|
version: 5.2.3
|
||||||
pinia:
|
pinia:
|
||||||
specifier: ^4.0.3
|
specifier: ^4.0.3
|
||||||
version: 4.0.3(@vue/devtools-api@6.6.4)(typescript@4.9.5)(vue@3.5.41(typescript@4.9.5))
|
version: 4.0.3(@vue/devtools-api@6.6.4)(typescript@4.9.5)(vue@3.5.41(typescript@4.9.5))
|
||||||
@@ -3179,6 +3182,9 @@ packages:
|
|||||||
minimist@1.2.8:
|
minimist@1.2.8:
|
||||||
resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==}
|
resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==}
|
||||||
|
|
||||||
|
miniprogram-api-typings@5.2.3:
|
||||||
|
resolution: {integrity: sha512-KVcNSfR2VmRtz35rxkjLxE92HlsBnbT6NsKyTcDX3ebbTKAsAiTOFO1mRM82Xbe848dnEYqNGzaD48LMEvGytw==}
|
||||||
|
|
||||||
mkdirp@0.5.6:
|
mkdirp@0.5.6:
|
||||||
resolution: {integrity: sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==}
|
resolution: {integrity: sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
@@ -6715,7 +6721,7 @@ snapshots:
|
|||||||
browserslist: 4.28.8
|
browserslist: 4.28.8
|
||||||
browserslist-to-esbuild: 2.1.1(browserslist@4.28.8)
|
browserslist-to-esbuild: 2.1.1(browserslist@4.28.8)
|
||||||
core-js: 3.50.0
|
core-js: 3.50.0
|
||||||
magic-string: 0.30.11
|
magic-string: 0.30.21
|
||||||
regenerator-runtime: 0.14.1
|
regenerator-runtime: 0.14.1
|
||||||
systemjs: 6.15.1
|
systemjs: 6.15.1
|
||||||
terser: 5.50.0
|
terser: 5.50.0
|
||||||
@@ -6814,7 +6820,7 @@ snapshots:
|
|||||||
'@vue/compiler-ssr': 3.4.21
|
'@vue/compiler-ssr': 3.4.21
|
||||||
'@vue/shared': 3.4.21
|
'@vue/shared': 3.4.21
|
||||||
estree-walker: 2.0.2
|
estree-walker: 2.0.2
|
||||||
magic-string: 0.30.11
|
magic-string: 0.30.21
|
||||||
postcss: 8.5.26
|
postcss: 8.5.26
|
||||||
source-map-js: 1.2.1
|
source-map-js: 1.2.1
|
||||||
|
|
||||||
@@ -8343,6 +8349,8 @@ snapshots:
|
|||||||
|
|
||||||
minimist@1.2.8: {}
|
minimist@1.2.8: {}
|
||||||
|
|
||||||
|
miniprogram-api-typings@5.2.3: {}
|
||||||
|
|
||||||
mkdirp@0.5.6:
|
mkdirp@0.5.6:
|
||||||
dependencies:
|
dependencies:
|
||||||
minimist: 1.2.8
|
minimist: 1.2.8
|
||||||
|
|||||||
54
src/components/Profile/StoragePopup.vue
Normal file
54
src/components/Profile/StoragePopup.vue
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
<template>
|
||||||
|
<wd-popup
|
||||||
|
v-model="profileStore.showStoragePopup"
|
||||||
|
position="bottom"
|
||||||
|
:safe-area-inset-bottom="true"
|
||||||
|
custom-style="border-radius: 32rpx 32rpx 0 0; padding: 40rpx 32rpx;"
|
||||||
|
>
|
||||||
|
<view class="mb-5 text-center text-base text-gray-700 font-semibold">
|
||||||
|
存储详情
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="flex flex-col items-center">
|
||||||
|
<wd-text :text="`${profileStore.storageTotal} / 1000`"></wd-text>
|
||||||
|
<wd-progress
|
||||||
|
:percentage="Number((profileStore.storageTotal / 1000 * 100).toFixed(2))"
|
||||||
|
:color="['#00c740', '#ffb300', '#e2231a']"/>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="max-h-[40vh] overflow-y-auto">
|
||||||
|
<wd-cell-group>
|
||||||
|
<wd-cell v-for="item in profileStore.storageStats"
|
||||||
|
:key="item.month"
|
||||||
|
:title="`${item.name}(${item.value}条)`"
|
||||||
|
center>
|
||||||
|
<wd-button size="small" type="danger" plain @click="clearMonth(item.name)">清除</wd-button>
|
||||||
|
</wd-cell>
|
||||||
|
</wd-cell-group>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<wd-empty v-if="profileStore.storageStats.length === 0" icon="no-content" tip="暂无记录" />
|
||||||
|
</wd-popup>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { useProfileStore } from '@/store/profile'
|
||||||
|
import { countRecordsByMonth, getTotalCount } from "@/utils/record";
|
||||||
|
|
||||||
|
const profileStore = useProfileStore()
|
||||||
|
|
||||||
|
function clearMonth(month: string) {
|
||||||
|
wx.showModal({
|
||||||
|
title: '提示',
|
||||||
|
content: `确定清除 ${month} 的所有记录吗?`,
|
||||||
|
success(res) {
|
||||||
|
if (res.confirm) {
|
||||||
|
wx.removeStorageSync(`health_${month}`)
|
||||||
|
profileStore.storageStats = countRecordsByMonth()
|
||||||
|
profileStore.storageTotal = getTotalCount()
|
||||||
|
wx.showToast({ title: '已清除', icon: 'success' })
|
||||||
|
}
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</script>
|
||||||
@@ -81,10 +81,11 @@ import SportPopup from "@/components/Home/SportPopup.vue";
|
|||||||
import BpPopup from "@/components/Home/BpPopup.vue";
|
import BpPopup from "@/components/Home/BpPopup.vue";
|
||||||
import GlucosePopup from "@/components/Home/GlucosePopup.vue";
|
import GlucosePopup from "@/components/Home/GlucosePopup.vue";
|
||||||
import TempPopup from "@/components/Home/TempPopup.vue";
|
import TempPopup from "@/components/Home/TempPopup.vue";
|
||||||
import { ref, computed, onMounted, watch } from 'vue'
|
import { ref, computed, watch } from 'vue'
|
||||||
import { useRecordStore } from '@/store/record'
|
import { useRecordStore } from '@/store/record'
|
||||||
import type { IHealthRecord } from '@/utils/record'
|
import { countRecordsByMonth, getDateStr, getDayRecords } from '@/utils/record'
|
||||||
import { getDateStr, getDayRecords } from '@/utils/record'
|
import type { IHealthRecord } from "@/type/record";
|
||||||
|
import {onShow} from "@dcloudio/uni-app";
|
||||||
|
|
||||||
defineOptions({
|
defineOptions({
|
||||||
name: 'Home',
|
name: 'Home',
|
||||||
@@ -114,7 +115,7 @@ const today = computed(() => {
|
|||||||
return `${m}月${d}日 周${w}`
|
return `${m}月${d}日 周${w}`
|
||||||
})
|
})
|
||||||
|
|
||||||
onMounted(() => {
|
onShow(() => {
|
||||||
todayRecords.value = getDayRecords(getDateStr(Date.now()))
|
todayRecords.value = getDayRecords(getDateStr(Date.now()))
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -196,3 +197,9 @@ function handelFabClick() {
|
|||||||
recordStore.showFab = false
|
recordStore.showFab = false
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
:deep(.wd-card:not(:last-child)) {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|||||||
@@ -13,12 +13,12 @@
|
|||||||
</wd-button>
|
</wd-button>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<wd-segmented v-model:value="current" :options="list" style="overflow: auto;" />
|
<wd-segmented v-model:value="current" :options="list"/>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<!-- 时间轴区域 -->
|
<!-- 时间轴区域 -->
|
||||||
<view class="px-5 py-2">
|
<view class="px-5 py-2">
|
||||||
<wd-empty v-if="grouped.length === 0" icon="no-content" tip="暂无内容" />
|
<wd-empty v-if="grouped.length === 0" icon="no-content" tip="暂无记录" />
|
||||||
|
|
||||||
<!-- 外层:每个日期分组 -->
|
<!-- 外层:每个日期分组 -->
|
||||||
<view v-for="group in grouped" :key="group.date" class="mb-6">
|
<view v-for="group in grouped" :key="group.date" class="mb-6">
|
||||||
@@ -90,7 +90,6 @@
|
|||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { computed, ref } from 'vue'
|
import { computed, ref } from 'vue'
|
||||||
import type { IHealthRecord } from '@/utils/record'
|
|
||||||
import {
|
import {
|
||||||
getMonthRecords,
|
getMonthRecords,
|
||||||
getMonthStr,
|
getMonthStr,
|
||||||
@@ -100,6 +99,7 @@ import {
|
|||||||
groupByDate,
|
groupByDate,
|
||||||
} from '@/utils/record'
|
} from '@/utils/record'
|
||||||
import { onShow } from "@dcloudio/uni-app";
|
import { onShow } from "@dcloudio/uni-app";
|
||||||
|
import type { IHealthRecord } from "@/type/record";
|
||||||
|
|
||||||
const currentDate = ref(Date.now())
|
const currentDate = ref(Date.now())
|
||||||
const showDatePicker = ref(false)
|
const showDatePicker = ref(false)
|
||||||
@@ -141,12 +141,16 @@ function openDatePicker() {
|
|||||||
showDatePicker.value = true
|
showDatePicker.value = true
|
||||||
}
|
}
|
||||||
|
|
||||||
function onDateConfirm({ value }) {
|
function onDateConfirm() {
|
||||||
loadRecords()
|
loadRecords()
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
|
:deep(.wd-segmented) {
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
|
||||||
:deep(.wd-segmented__item) {
|
:deep(.wd-segmented__item) {
|
||||||
min-width: 60px;
|
min-width: 60px;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
|
|||||||
@@ -20,16 +20,24 @@
|
|||||||
</view>
|
</view>
|
||||||
</wd-card>
|
</wd-card>
|
||||||
|
|
||||||
|
<wd-cell-group>
|
||||||
|
<wd-cell title="存储详情" is-link @click="openStoragePopup"/>
|
||||||
|
</wd-cell-group>
|
||||||
|
|
||||||
<profile-popup />
|
<profile-popup />
|
||||||
|
|
||||||
|
<storage-popup />
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import ProfilePopup from "@/components/Profile/ProfilePopup.vue";
|
import ProfilePopup from "@/components/Profile/ProfilePopup.vue";
|
||||||
|
import StoragePopup from "@/components/Profile/StoragePopup.vue";
|
||||||
import { computed, ref, watch } from 'vue'
|
import { computed, ref, watch } from 'vue'
|
||||||
import type { IProfile } from '@/utils/profile'
|
|
||||||
import { getProfile } from '@/utils/profile'
|
import { getProfile } from '@/utils/profile'
|
||||||
import { useProfileStore } from '@/store/profile'
|
import { useProfileStore } from '@/store/profile'
|
||||||
|
import type { IProfile } from "@/type/profile";
|
||||||
|
import {countRecordsByMonth, getTotalCount} from "@/utils/record";
|
||||||
|
|
||||||
const profileStore = useProfileStore()
|
const profileStore = useProfileStore()
|
||||||
|
|
||||||
@@ -53,4 +61,10 @@ function openProfile() {
|
|||||||
|
|
||||||
profileStore.showProfilePopup = true
|
profileStore.showProfilePopup = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function openStoragePopup() {
|
||||||
|
profileStore.storageStats = countRecordsByMonth()
|
||||||
|
profileStore.storageTotal = getTotalCount()
|
||||||
|
profileStore.showStoragePopup = true
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -1,15 +1,19 @@
|
|||||||
import { defineStore } from 'pinia'
|
import { defineStore } from 'pinia'
|
||||||
import type { IProfile } from '@/utils/profile'
|
import type { IProfile } from "@/type/profile";
|
||||||
|
import type {IStats} from "@/type";
|
||||||
|
|
||||||
export const useProfileStore = defineStore('profile', {
|
export const useProfileStore = defineStore('profile', {
|
||||||
state: () => ({
|
state: () => ({
|
||||||
showProfilePopup: false,
|
showProfilePopup: false,
|
||||||
|
showStoragePopup: false,
|
||||||
profileForm: {
|
profileForm: {
|
||||||
gender: '',
|
gender: '',
|
||||||
height: 0,
|
height: 0,
|
||||||
name: '',
|
name: '',
|
||||||
weight: 0,
|
weight: 0,
|
||||||
} as IProfile,
|
} as IProfile,
|
||||||
|
storageStats: [] as IStats[],
|
||||||
|
storageTotal: 0,
|
||||||
isRefresh: false,
|
isRefresh: false,
|
||||||
}),
|
}),
|
||||||
actions: {
|
actions: {
|
||||||
|
|||||||
4
src/type/index.ts
Normal file
4
src/type/index.ts
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
export interface IStats {
|
||||||
|
name: string;
|
||||||
|
value: number
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
export interface IProfile {
|
||||||
|
name: string
|
||||||
|
gender: 'male' | 'female' | ''
|
||||||
|
height: number | null
|
||||||
|
weight: number | null
|
||||||
|
}
|
||||||
|
|||||||
@@ -0,0 +1,18 @@
|
|||||||
|
export interface IHealthRecord {
|
||||||
|
id: string
|
||||||
|
type: string
|
||||||
|
time: string
|
||||||
|
date?: string
|
||||||
|
[key: string]: any
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IRecordMeta {
|
||||||
|
icon: string
|
||||||
|
label: string
|
||||||
|
color: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IRecordStats {
|
||||||
|
label: string
|
||||||
|
type: 'default' | 'primary' | 'success' | 'warning' | 'danger' | 'volcano' | 'lightblue' | 'cyan' | 'pink' | 'purple'
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,9 +1,4 @@
|
|||||||
export interface IProfile {
|
import type { IProfile } from "@/type/profile";
|
||||||
name: string
|
|
||||||
gender: 'male' | 'female' | ''
|
|
||||||
height: number | null
|
|
||||||
weight: number | null
|
|
||||||
}
|
|
||||||
|
|
||||||
const PROFILE_KEY = 'user_profile'
|
const PROFILE_KEY = 'user_profile'
|
||||||
|
|
||||||
|
|||||||
@@ -1,29 +1,12 @@
|
|||||||
import { getProfile } from '@/utils/profile'
|
import { getProfile } from '@/utils/profile'
|
||||||
|
import type {IHealthRecord, IRecordMeta, IRecordStats} from "@/type/record";
|
||||||
export interface IHealthRecord {
|
import type {IStats} from "@/type";
|
||||||
id: string
|
|
||||||
type: string
|
|
||||||
time: string
|
|
||||||
date?: string
|
|
||||||
[key: string]: any
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface IRecordMeta {
|
|
||||||
icon: string
|
|
||||||
label: string
|
|
||||||
color: string
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface IRecordStats {
|
|
||||||
label: string
|
|
||||||
type: 'default' | 'primary' | 'success' | 'warning' | 'danger' | 'volcano' | 'lightblue' | 'cyan' | 'pink' | 'purple'
|
|
||||||
}
|
|
||||||
|
|
||||||
const MONTH_KEEP = 12
|
const MONTH_KEEP = 12
|
||||||
|
const RECORD_PREFIX = 'health_'
|
||||||
|
|
||||||
function getMonthKey(timestamp: number) {
|
function getMonthKey(timestamp: number) {
|
||||||
const d = new Date(timestamp)
|
return `${RECORD_PREFIX}${getMonthStr(timestamp)}`
|
||||||
return `health_${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getDateStr(timestamp: number) {
|
export function getDateStr(timestamp: number) {
|
||||||
@@ -46,16 +29,17 @@ export function getTimeStr(timestamp: number) {
|
|||||||
function cleanOldMonths() {
|
function cleanOldMonths() {
|
||||||
const cutoff = new Date()
|
const cutoff = new Date()
|
||||||
cutoff.setMonth(cutoff.getMonth() - MONTH_KEEP)
|
cutoff.setMonth(cutoff.getMonth() - MONTH_KEEP)
|
||||||
const cutoffKey = `health_${cutoff.getFullYear()}-${String(cutoff.getMonth() + 1).padStart(2, '0')}`
|
const cutoffKey = `${RECORD_PREFIX}${cutoff.getFullYear()}-${String(cutoff.getMonth() + 1).padStart(2, '0')}`
|
||||||
const keys = wx.getStorageInfoSync().keys
|
const keys = wx.getStorageInfoSync().keys
|
||||||
keys.forEach((key) => {
|
keys.forEach((key: string) => {
|
||||||
if (key.startsWith('health_') && key < cutoffKey) {
|
if (key.startsWith(RECORD_PREFIX) && key < cutoffKey) {
|
||||||
wx.removeStorageSync(key)
|
wx.removeStorageSync(key)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
function addRecord(type: string, data: Record<string, any>, timestamp: number) {
|
function addRecord(type: string, data: Record<string, any>, timestamp: number) {
|
||||||
|
// 键为月份 例如 health_2026-08
|
||||||
const key = getMonthKey(timestamp)
|
const key = getMonthKey(timestamp)
|
||||||
const all = wx.getStorageSync(key) || {}
|
const all = wx.getStorageSync(key) || {}
|
||||||
const date = getDateStr(timestamp)
|
const date = getDateStr(timestamp)
|
||||||
@@ -63,6 +47,7 @@ function addRecord(type: string, data: Record<string, any>, timestamp: number) {
|
|||||||
if (!all[date])
|
if (!all[date])
|
||||||
all[date] = []
|
all[date] = []
|
||||||
|
|
||||||
|
// 在按天存储
|
||||||
all[date].push({
|
all[date].push({
|
||||||
id: Date.now() + Math.random().toString(36).slice(2, 6),
|
id: Date.now() + Math.random().toString(36).slice(2, 6),
|
||||||
time: getTimeStr(timestamp),
|
time: getTimeStr(timestamp),
|
||||||
@@ -97,31 +82,25 @@ export function addTemperature(value: number, location: string, note: string, ti
|
|||||||
addRecord('temperature', { value, location, note }, timestamp)
|
addRecord('temperature', { value, location, note }, timestamp)
|
||||||
}
|
}
|
||||||
|
|
||||||
function getAllMonthKeys(): string[] {
|
/**
|
||||||
return wx.getStorageInfoSync().keys.filter(k => k.startsWith('health_')).sort()
|
* 获取某天的记录
|
||||||
}
|
* @param dateStr 日期 YYYY-MM-DD
|
||||||
|
*/
|
||||||
// ─── 根据时间戳反推它属于哪个月的 key ───
|
export function getDayRecords(dateStr: string): IHealthRecord[] {
|
||||||
function getMonthKeyForTimestamp(timestamp: number): string {
|
|
||||||
const d = new Date(timestamp)
|
|
||||||
return `health_${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}`
|
|
||||||
}
|
|
||||||
|
|
||||||
// ─── 根据 "YYYY-MM-DD" 反推月份 key ───
|
|
||||||
function getMonthKeyForDate(dateStr: string): string {
|
|
||||||
const [y, m] = dateStr.split('-')
|
const [y, m] = dateStr.split('-')
|
||||||
return `health_${y}-${m}`
|
const key = `${RECORD_PREFIX}${y}-${m}`
|
||||||
}
|
|
||||||
|
|
||||||
export function getDayRecords(date: string): IHealthRecord[] {
|
|
||||||
const key = getMonthKeyForDate(date)
|
|
||||||
const all = wx.getStorageSync(key) || {}
|
const all = wx.getStorageSync(key) || {}
|
||||||
const dayRecords = all[date] || []
|
const dayRecords = all[dateStr] || []
|
||||||
return [...dayRecords].sort((a, b) => a.time.localeCompare(b.time))
|
return [...dayRecords].sort((a, b) => a.time.localeCompare(b.time))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取某月的记录
|
||||||
|
* @param yearMonth 月份 YYYY-MM
|
||||||
|
* @param type 类型
|
||||||
|
*/
|
||||||
export function getMonthRecords(yearMonth: string, type?: string): IHealthRecord[] {
|
export function getMonthRecords(yearMonth: string, type?: string): IHealthRecord[] {
|
||||||
const key = `health_${yearMonth}`
|
const key = `${RECORD_PREFIX}${yearMonth}`
|
||||||
const all = wx.getStorageSync(key) || {}
|
const all = wx.getStorageSync(key) || {}
|
||||||
|
|
||||||
const result: IHealthRecord[] = []
|
const result: IHealthRecord[] = []
|
||||||
@@ -146,6 +125,26 @@ function sortRecords(records: IHealthRecord[]): IHealthRecord[] {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function countRecordsByMonth(): IStats[] {
|
||||||
|
const keys = wx.getStorageInfoSync().keys
|
||||||
|
|
||||||
|
return keys
|
||||||
|
.filter(k => k.startsWith(RECORD_PREFIX))
|
||||||
|
.map(key => {
|
||||||
|
const all: IHealthRecord = wx.getStorageSync(key) || {}
|
||||||
|
const value: number = Object.values(all).reduce((sum: number, list: IHealthRecord[]) => sum + list.length, 0)
|
||||||
|
const name = key.replace(RECORD_PREFIX, '')
|
||||||
|
return { name, value }
|
||||||
|
})
|
||||||
|
.sort((a, b) => a.name.localeCompare(b.name))
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getTotalCount(): number {
|
||||||
|
return wx.getStorageInfoSync().keys
|
||||||
|
.filter(k => k.startsWith('health_'))
|
||||||
|
.reduce((sum, k) => sum + Object.values(wx.getStorageSync(k) || {}).flat().length, 0)
|
||||||
|
}
|
||||||
|
|
||||||
const META_MAP: Record<string, IRecordMeta> = {
|
const META_MAP: Record<string, IRecordMeta> = {
|
||||||
weight: { icon: '⚖️', label: '体重', color: 'bg-[#E89E3A]' },
|
weight: { icon: '⚖️', label: '体重', color: 'bg-[#E89E3A]' },
|
||||||
sleep: { icon: '😴', label: '睡眠', color: 'bg-[#2E5B8C]' },
|
sleep: { icon: '😴', label: '睡眠', color: 'bg-[#2E5B8C]' },
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
"@/*": ["./src/*"]
|
"@/*": ["./src/*"]
|
||||||
},
|
},
|
||||||
"lib": ["esnext", "dom"],
|
"lib": ["esnext", "dom"],
|
||||||
"types": ["@dcloudio/types"]
|
"types": ["@dcloudio/types", "miniprogram-api-typings"]
|
||||||
},
|
},
|
||||||
"include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"]
|
"include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"]
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user