feat: 增加可以自定义默认值功能
This commit is contained in:
20
src/App.vue
20
src/App.vue
@@ -1,8 +1,26 @@
|
||||
<script setup lang="ts">
|
||||
import { onLaunch, onShow, onHide } from "@dcloudio/uni-app";
|
||||
import { getOverview, saveOverview, getPlan, savePlan } from "@/utils/profile";
|
||||
import {
|
||||
getOverview,
|
||||
saveOverview,
|
||||
getPlan,
|
||||
savePlan,
|
||||
getDefaultRecordValue,
|
||||
saveDefaultRecordValue
|
||||
} from "@/utils/profile";
|
||||
|
||||
onLaunch(() => {
|
||||
if (!getDefaultRecordValue()) {
|
||||
saveDefaultRecordValue({
|
||||
weightValue: 70,
|
||||
sportDuration: 30,
|
||||
bloodPressureSystolic: 120,
|
||||
bloodPressureDiastolic: 70,
|
||||
bloodPressureHeartRate: 80,
|
||||
bloodSugarValue: 5.4,
|
||||
temperatureValue: 36.5,
|
||||
})
|
||||
}
|
||||
if (getOverview().length === 0) {
|
||||
saveOverview(['weight', 'sleep', 'sport', 'bloodPressure'])
|
||||
}
|
||||
|
||||
@@ -24,10 +24,9 @@
|
||||
<view class="flex items-center gap-2">
|
||||
<wd-input-number
|
||||
v-model="recordStore.bloodPressureForm.systolic"
|
||||
:min="60"
|
||||
:min="1"
|
||||
:max="250"
|
||||
:step="1"
|
||||
:decimal-length="0"
|
||||
/>
|
||||
<text class="shrink-0 text-sm text-gray-400">mmHg</text>
|
||||
</view>
|
||||
@@ -38,10 +37,9 @@
|
||||
<view class="flex items-center gap-2">
|
||||
<wd-input-number
|
||||
v-model="recordStore.bloodPressureForm.diastolic"
|
||||
:min="40"
|
||||
:min="1"
|
||||
:max="180"
|
||||
:step="1"
|
||||
:decimal-length="0"
|
||||
/>
|
||||
<text class="shrink-0 text-sm text-gray-400">mmHg</text>
|
||||
</view>
|
||||
@@ -51,10 +49,9 @@
|
||||
<view class="flex items-center gap-2">
|
||||
<wd-input-number
|
||||
v-model="recordStore.bloodPressureForm.heartRate"
|
||||
:min="30"
|
||||
:min="1"
|
||||
:max="220"
|
||||
:step="1"
|
||||
:decimal-length="0"
|
||||
/>
|
||||
<text class="shrink-0 text-sm text-gray-400">bpm</text>
|
||||
</view>
|
||||
|
||||
@@ -96,7 +96,7 @@ const recordStore = useRecordStore()
|
||||
|
||||
const periodColumns = [
|
||||
{ label: '空腹', value: '空腹' },
|
||||
{ label: '餐后1h', value: '餐后1h' },
|
||||
{ label: '餐前', value: '餐前' },
|
||||
{ label: '餐后2h', value: '餐后2h' },
|
||||
{ label: '睡前', value: '睡前' },
|
||||
{ label: '随机', value: '随机' },
|
||||
|
||||
@@ -39,8 +39,7 @@
|
||||
v-model="recordStore.sportForm.duration"
|
||||
:min="1"
|
||||
:max="600"
|
||||
:step="5"
|
||||
:decimal-length="0"
|
||||
:step="1"
|
||||
/>
|
||||
<text class="shrink-0 text-sm text-gray-400">分钟</text>
|
||||
</view>
|
||||
|
||||
@@ -96,9 +96,7 @@ const recordStore = useRecordStore()
|
||||
|
||||
const locationColumns = [
|
||||
{ label: '腋下', value: '腋下' },
|
||||
{ label: '口腔', value: '口腔' },
|
||||
{ label: '耳温', value: '耳温' },
|
||||
{ label: '额温', value: '额温' },
|
||||
{ label: '口腔', value: '口腔' }
|
||||
]
|
||||
|
||||
function handeClosePopup() {
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
custom-style="border-radius: 32rpx 32rpx 0 0; padding: 40rpx 32rpx"
|
||||
@close="handeClosePopup"
|
||||
>
|
||||
|
||||
<view class="mb-5 text-center text-base text-gray-700 font-semibold">
|
||||
⚖️ 记录体重
|
||||
</view>
|
||||
@@ -14,7 +15,7 @@
|
||||
<wd-form ref="form" :model="recordStore.weightForm" layout="horizontal" title-width="80" size="large" border>
|
||||
<wd-form-item title="体重">
|
||||
<view class="flex items-center gap-2">
|
||||
<wd-input-number v-model="recordStore.weightForm.value" :min="1" :max="200" />
|
||||
<wd-input-number v-model="recordStore.weightForm.value" :min="1" :max="200" :step="0.1" :precision="1"/>
|
||||
<text class="shrink-0 text-sm text-gray-400">Kg</text>
|
||||
</view>
|
||||
</wd-form-item>
|
||||
|
||||
118
src/components/Profile/DefaultPopup.vue
Normal file
118
src/components/Profile/DefaultPopup.vue
Normal file
@@ -0,0 +1,118 @@
|
||||
<template>
|
||||
<wd-popup
|
||||
v-model="profileStore.showDefaultRecordValuePopup"
|
||||
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-form :model="profileStore.defaultRecordValueForm" layout="horizontal" title-width="80" size="large" border>
|
||||
<wd-form-item title="体重">
|
||||
<view class="flex items-center gap-2">
|
||||
<wd-input-number v-model="profileStore.defaultRecordValueForm.weightValue" :min="1" :max="200" :step="0.1" :precision="1"/>
|
||||
<text class="shrink-0 text-sm text-gray-400">Kg</text>
|
||||
</view>
|
||||
</wd-form-item>
|
||||
|
||||
<wd-form-item title="运动时长">
|
||||
<view class="flex items-center gap-2">
|
||||
<wd-input-number v-model="profileStore.defaultRecordValueForm.sportDuration" :min="1" :max="600" :step="1"/>
|
||||
<text class="shrink-0 text-sm text-gray-400">分钟</text>
|
||||
</view>
|
||||
</wd-form-item>
|
||||
|
||||
<!-- 收缩压(高压) -->
|
||||
<wd-form-item title="收缩压">
|
||||
<view class="flex items-center gap-2">
|
||||
<wd-input-number
|
||||
v-model="profileStore.defaultRecordValueForm.bloodPressureSystolic"
|
||||
:min="1"
|
||||
:max="250"
|
||||
:step="1"
|
||||
/>
|
||||
<text class="shrink-0 text-sm text-gray-400">mmHg</text>
|
||||
</view>
|
||||
</wd-form-item>
|
||||
|
||||
<!-- 舒张压(低压) -->
|
||||
<wd-form-item title="舒张压">
|
||||
<view class="flex items-center gap-2">
|
||||
<wd-input-number
|
||||
v-model="profileStore.defaultRecordValueForm.bloodPressureDiastolic"
|
||||
:min="1"
|
||||
:max="180"
|
||||
:step="1"
|
||||
/>
|
||||
<text class="shrink-0 text-sm text-gray-400">mmHg</text>
|
||||
</view>
|
||||
</wd-form-item>
|
||||
|
||||
<wd-form-item title="心率">
|
||||
<view class="flex items-center gap-2">
|
||||
<wd-input-number
|
||||
v-model="profileStore.defaultRecordValueForm.bloodPressureHeartRate"
|
||||
:min="1"
|
||||
:max="220"
|
||||
:step="1"
|
||||
/>
|
||||
<text class="shrink-0 text-sm text-gray-400">bpm</text>
|
||||
</view>
|
||||
</wd-form-item>
|
||||
|
||||
<wd-form-item title="血糖值">
|
||||
<view class="flex items-center gap-2">
|
||||
<wd-input-number
|
||||
v-model="profileStore.defaultRecordValueForm.bloodSugarValue"
|
||||
:min="1"
|
||||
:max="30"
|
||||
:step="0.1"
|
||||
:precision="1"
|
||||
/>
|
||||
<text class="shrink-0 text-sm text-gray-400">mmol/L</text>
|
||||
</view>
|
||||
</wd-form-item>
|
||||
|
||||
<!-- 体温值 -->
|
||||
<wd-form-item title="体温">
|
||||
<view class="flex items-center gap-2">
|
||||
<wd-input-number
|
||||
v-model="profileStore.defaultRecordValueForm.temperatureValue"
|
||||
:min="35"
|
||||
:max="42"
|
||||
:step="0.1"
|
||||
:precision="1"
|
||||
/>
|
||||
<text class="shrink-0 text-sm text-gray-400">℃</text>
|
||||
</view>
|
||||
</wd-form-item>
|
||||
</wd-form>
|
||||
|
||||
<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 { saveDefaultRecordValue } from '@/utils/profile'
|
||||
import { useProfileStore } from '@/store/profile'
|
||||
|
||||
const profileStore = useProfileStore()
|
||||
|
||||
function cancelClick() {
|
||||
profileStore.showDefaultRecordValuePopup = false
|
||||
}
|
||||
|
||||
function saveClick() {
|
||||
saveDefaultRecordValue(profileStore.defaultRecordValueForm)
|
||||
profileStore.showDefaultRecordValuePopup = false
|
||||
uni.showToast({ title: '保存信息成功', icon: 'success' })
|
||||
}
|
||||
</script>
|
||||
@@ -89,7 +89,7 @@ import BloodSugarPopup from "@/components/Home/BloodSugarPopup.vue";
|
||||
import TemperaturePopup from "@/components/Home/TemperaturePopup.vue";
|
||||
import { ref, computed, watch } from 'vue'
|
||||
import { useRecordStore } from '@/store/record'
|
||||
import {getDateStr, getDayRecords, getTimeStr} from '@/utils/record'
|
||||
import { getDateStr, getDayRecords, getTimeStr } from '@/utils/record'
|
||||
import type { IHealthRecord } from "@/type/record";
|
||||
import { onShow } from "@dcloudio/uni-app";
|
||||
import { getOverview, getPlan, getProfile } from "@/utils/profile";
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
</wd-card>
|
||||
|
||||
<wd-cell-group>
|
||||
<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="openPlanPopup"/>
|
||||
<wd-cell size="large" title="存储详情" is-link @click="openStoragePopup"/>
|
||||
@@ -35,6 +36,8 @@
|
||||
<overview-popup />
|
||||
|
||||
<plan-popup />
|
||||
|
||||
<default-popup />
|
||||
</view>
|
||||
</template>
|
||||
|
||||
@@ -44,11 +47,12 @@ import StoragePopup from "@/components/Profile/StoragePopup.vue";
|
||||
import OverviewPopup from "@/components/Profile/OverviewPopup.vue";
|
||||
import PlanPopup from "@/components/Profile/PlanPopup.vue";
|
||||
import { computed, ref, watch } from 'vue'
|
||||
import { getOverview, getPlan, getProfile } from '@/utils/profile'
|
||||
import {getDefaultRecordValue, getOverview, getPlan, getProfile} from '@/utils/profile'
|
||||
import { useProfileStore } from '@/store/profile'
|
||||
import { useAppStore } from "@/store/app";
|
||||
import type { IProfile } from "@/type/profile";
|
||||
import { countRecordsByMonth, getMaxRecord, getTotalCount } from "@/utils/record";
|
||||
import DefaultPopup from "@/components/Profile/DefaultPopup.vue";
|
||||
|
||||
const profileStore = useProfileStore()
|
||||
const appStore = useAppStore()
|
||||
@@ -74,6 +78,11 @@ function openProfile() {
|
||||
profileStore.showProfilePopup = true
|
||||
}
|
||||
|
||||
function openDefaultPopup() {
|
||||
profileStore.defaultRecordValueForm = getDefaultRecordValue()
|
||||
profileStore.showDefaultRecordValuePopup = true
|
||||
}
|
||||
|
||||
function openOverviewPopup() {
|
||||
profileStore.overviewList = getOverview()
|
||||
profileStore.showOverviewPopup = true
|
||||
|
||||
@@ -2,7 +2,7 @@ import { defineStore } from 'pinia'
|
||||
|
||||
export const useAppStore = defineStore('app', {
|
||||
state: () => ({
|
||||
version: '1.0.1',
|
||||
version: '1.1.0',
|
||||
viewRecordType: 'calendar',
|
||||
}),
|
||||
actions: {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { defineStore } from 'pinia'
|
||||
import type { IProfile } from "@/type/profile";
|
||||
import type {IDefaultRecordValue, IProfile} from "@/type/profile";
|
||||
import type {IStats} from "@/type";
|
||||
|
||||
export const useProfileStore = defineStore('profile', {
|
||||
@@ -8,16 +8,27 @@ export const useProfileStore = defineStore('profile', {
|
||||
showStoragePopup: false,
|
||||
showOverviewPopup: false,
|
||||
showPlanPopup: false,
|
||||
showDefaultRecordValuePopup: false,
|
||||
profileForm: {
|
||||
gender: '',
|
||||
height: 0,
|
||||
name: '',
|
||||
} as IProfile,
|
||||
defaultRecordValueForm: {
|
||||
weightValue: 70,
|
||||
sportDuration: 30,
|
||||
bloodPressureSystolic: 120,
|
||||
bloodPressureDiastolic: 70,
|
||||
bloodPressureHeartRate: 80,
|
||||
bloodSugarValue: 5.4,
|
||||
temperatureValue: 36.5,
|
||||
} as IDefaultRecordValue,
|
||||
storageStats: [] as IStats[],
|
||||
storageTotal: 0,
|
||||
storageMax: 1000,
|
||||
overviewList: [] as string[],
|
||||
planList: [] as string[],
|
||||
defaultList: [],
|
||||
isRefresh: false,
|
||||
}),
|
||||
actions: {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { defineStore } from 'pinia'
|
||||
import { addBloodPressure, addBloodSugar, addSleep, addSport, addTemperature, addWeight } from '@/utils/record'
|
||||
import {getDefaultRecordValue} from "@/utils/profile";
|
||||
|
||||
export const useRecordStore = defineStore('record', {
|
||||
state: () => ({
|
||||
@@ -133,22 +134,27 @@ export const useRecordStore = defineStore('record', {
|
||||
this.isRecord = !this.isRecord
|
||||
},
|
||||
resetWeight() {
|
||||
this.weightForm = { value: 70, note: '', time: Date.now() }
|
||||
const { weightValue } = getDefaultRecordValue()
|
||||
this.weightForm = { value: weightValue, note: '', time: Date.now() }
|
||||
},
|
||||
resetSleep() {
|
||||
this.sleepForm = { startTime: Date.now() - 8 * 60 * 60 * 1000, endTime: Date.now(), duration: 8, note: '', time: Date.now() }
|
||||
},
|
||||
resetSport() {
|
||||
this.sportForm = { category: '跑步', duration: 30, note: '', time: Date.now() }
|
||||
const { sportDuration } = getDefaultRecordValue()
|
||||
this.sportForm = { category: '跑步', duration: sportDuration, note: '', time: Date.now() }
|
||||
},
|
||||
resetBloodPressure() {
|
||||
this.bloodPressureForm = { systolic: 120, diastolic: 70, heartRate: 80, note: '', time: Date.now() }
|
||||
const { bloodPressureSystolic, bloodPressureDiastolic, bloodPressureHeartRate } = getDefaultRecordValue()
|
||||
this.bloodPressureForm = { systolic: bloodPressureSystolic, diastolic: bloodPressureDiastolic, heartRate: bloodPressureHeartRate, note: '', time: Date.now() }
|
||||
},
|
||||
resetBloodSugar() {
|
||||
this.bloodSugarForm = { value: 5.4, period: '空腹', note: '', time: Date.now() }
|
||||
const { bloodSugarValue } = getDefaultRecordValue()
|
||||
this.bloodSugarForm = { value: bloodSugarValue, period: '空腹', note: '', time: Date.now() }
|
||||
},
|
||||
resetTemperature() {
|
||||
this.temperatureForm = { value: 36.5, location: '腋下', note: '', time: Date.now() }
|
||||
const { temperatureValue } = getDefaultRecordValue()
|
||||
this.temperatureForm = { value: temperatureValue, location: '腋下', note: '', time: Date.now() }
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
@@ -17,3 +17,13 @@ export interface IPlan {
|
||||
label: string
|
||||
done: boolean
|
||||
}
|
||||
|
||||
export interface IDefaultRecordValue {
|
||||
weightValue: number
|
||||
sportDuration: number
|
||||
bloodPressureSystolic: number
|
||||
bloodPressureDiastolic: number
|
||||
bloodPressureHeartRate: number
|
||||
bloodSugarValue: number
|
||||
temperatureValue: number
|
||||
}
|
||||
@@ -1,8 +1,9 @@
|
||||
import type { IProfile } from "@/type/profile";
|
||||
import type {IDefaultRecordValue, IProfile} from "@/type/profile";
|
||||
|
||||
const PROFILE_KEY = 'user_profile'
|
||||
const OVERVIEW_KEY = 'user_overview'
|
||||
const PLAN_KEY = 'user_plan'
|
||||
const DEFAULT_RECORD_VALUE_KEY = 'user_default_record_value'
|
||||
|
||||
function getEmptyProfile(): IProfile {
|
||||
return {
|
||||
@@ -20,6 +21,14 @@ export function saveProfile(data: IProfile) {
|
||||
wx.setStorageSync(PROFILE_KEY, data)
|
||||
}
|
||||
|
||||
export function getDefaultRecordValue(): IDefaultRecordValue {
|
||||
return wx.getStorageSync(DEFAULT_RECORD_VALUE_KEY)
|
||||
}
|
||||
|
||||
export function saveDefaultRecordValue(data: IDefaultRecordValue) {
|
||||
wx.setStorageSync(DEFAULT_RECORD_VALUE_KEY, data)
|
||||
}
|
||||
|
||||
export function getOverview(): string[] {
|
||||
return wx.getStorageSync(OVERVIEW_KEY) || []
|
||||
}
|
||||
|
||||
@@ -13,9 +13,12 @@ function getMonthKey(timestamp: number) {
|
||||
return `${RECORD_PREFIX}${getMonthStr(timestamp)}`
|
||||
}
|
||||
|
||||
export function getDateStr(timestamp: number) {
|
||||
export function getDateStr(timestamp: number): string {
|
||||
const d = new Date(timestamp)
|
||||
return d.toISOString().slice(0, 10)
|
||||
const y = d.getFullYear()
|
||||
const m = String(d.getMonth() + 1).padStart(2, '0')
|
||||
const day = String(d.getDate()).padStart(2, '0')
|
||||
return `${y}-${m}-${day}`
|
||||
}
|
||||
|
||||
export function getMonthStr(timestamp: number): string {
|
||||
|
||||
Reference in New Issue
Block a user