From 9c6895caf1f9f1853944d1266d80f03c72079d82 Mon Sep 17 00:00:00 2001 From: Cxx0822 <1556464090@qq.com> Date: Mon, 31 Aug 2026 15:23:17 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=A2=9E=E5=8A=A0=E7=A7=AF=E5=88=86?= =?UTF-8?q?=E6=A8=A1=E5=9D=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/Profile/PointPopup.vue | 44 ++++++++++++++ src/pages/index/index.vue | 16 +++++ src/pages/stats/index.vue | 8 ++- src/pages/user/index.vue | 35 ++++++++++- src/store/app.ts | 3 + src/store/profile.ts | 1 + src/utils/points.ts | 84 +++++++++++++++++++++++++++ src/utils/record.ts | 3 + 8 files changed, 192 insertions(+), 2 deletions(-) create mode 100644 src/components/Profile/PointPopup.vue create mode 100644 src/utils/points.ts diff --git a/src/components/Profile/PointPopup.vue b/src/components/Profile/PointPopup.vue new file mode 100644 index 0000000..564af12 --- /dev/null +++ b/src/components/Profile/PointPopup.vue @@ -0,0 +1,44 @@ + + + diff --git a/src/pages/index/index.vue b/src/pages/index/index.vue index 10d928c..3961486 100644 --- a/src/pages/index/index.vue +++ b/src/pages/index/index.vue @@ -11,6 +11,10 @@ {{ today }} · 记录每一次改变 + + + {{ hasSignedToday ? '已签到' : '签到'}} + @@ -95,6 +99,7 @@ import { onShow } from "@dcloudio/uni-app"; import { getOverview, getPlan, getProfile } from "@/utils/profile"; import appLogo from '@/static/logo.png' import type { IOverview, IPlan } from "@/type/profile"; +import { addSignInPoint } from "@/utils/points"; defineOptions({ name: 'Home', @@ -105,6 +110,7 @@ const imgURL = appLogo const recordStore = useRecordStore() const todayRecords = ref([]) +const hasSignedToday = ref(checkSignedToday()) const now = new Date() const hour = now.getHours() @@ -119,6 +125,15 @@ const greeting = computed(() => { return '晚上好 ✨' }) +function checkSignedToday() { + return wx.getStorageSync('lastSignDate') === getDateStr(Date.now()) +} + +function handleSign() { + addSignInPoint() + hasSignedToday.value = checkSignedToday() +} + const today = computed(() => { const m = now.getMonth() + 1 const d = now.getDate() @@ -128,6 +143,7 @@ const today = computed(() => { onShow(() => { todayRecords.value = getDayRecords(getDateStr(Date.now())) + hasSignedToday.value = checkSignedToday() }) watch(() => recordStore.isRecord, () => { diff --git a/src/pages/stats/index.vue b/src/pages/stats/index.vue index 18da75c..9981e7c 100644 --- a/src/pages/stats/index.vue +++ b/src/pages/stats/index.vue @@ -113,7 +113,13 @@ const chartOpts = { enableScroll: false, legend: { show: true }, xAxis: { disableGrid: true }, - yAxis: { gridType: 'dash', dashLength: 2 }, + yAxis: { + gridType: 'dash', + dashLength: 2, + data: [ + { min: 0, format: (val: number) => val.toFixed(1) } + ] + }, extra: { line: { type: 'straight', width: 2, activeType: 'hollow'}, }, diff --git a/src/pages/user/index.vue b/src/pages/user/index.vue index e60b7a9..c63ba03 100644 --- a/src/pages/user/index.vue +++ b/src/pages/user/index.vue @@ -20,6 +20,24 @@ + + + + ✨ 当前积分:{{ appStore.points }}分 + 📊 记录次数:{{ appStore.recordCount }}次 + 🏆 当前成就:{{ appStore.achievement }} + + + + 查看说明 + + + + + 坚持记录健康数据,解锁更多成就 + + + @@ -38,6 +56,8 @@ + + @@ -47,12 +67,15 @@ 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 {getDefaultRecordValue, 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"; +import { getAchievement, getPoints, getRecordCount } from "@/utils/points"; +import { onShow } from "@dcloudio/uni-app"; +import PointPopup from "@/components/Profile/PointPopup.vue"; const profileStore = useProfileStore() const appStore = useAppStore() @@ -68,6 +91,12 @@ const genderText = computed(() => { return '性别未填' }) +onShow(() => { + appStore.points = getPoints() + appStore.recordCount = getRecordCount() + appStore.achievement = getAchievement() +}) + watch(() => profileStore.isRefresh, () => { profile.value = getProfile() }) @@ -99,4 +128,8 @@ function openStoragePopup() { profileStore.storageMax = getMaxRecord() profileStore.showStoragePopup = true } + +function openPointPopup() { + profileStore.showPointPopup = true +} diff --git a/src/store/app.ts b/src/store/app.ts index 84e6e9b..13238af 100644 --- a/src/store/app.ts +++ b/src/store/app.ts @@ -4,6 +4,9 @@ export const useAppStore = defineStore('app', { state: () => ({ version: '1.1.0', viewRecordType: 'calendar', + points: 0, + recordCount: 0, + achievement: '' }), actions: { diff --git a/src/store/profile.ts b/src/store/profile.ts index 0170834..da35105 100644 --- a/src/store/profile.ts +++ b/src/store/profile.ts @@ -9,6 +9,7 @@ export const useProfileStore = defineStore('profile', { showOverviewPopup: false, showPlanPopup: false, showDefaultRecordValuePopup: false, + showPointPopup: false, profileForm: { gender: '', height: 0, diff --git a/src/utils/points.ts b/src/utils/points.ts new file mode 100644 index 0000000..972fd37 --- /dev/null +++ b/src/utils/points.ts @@ -0,0 +1,84 @@ +import { getDateStr } from "@/utils/record"; + +const POINTS = { + SIGN_IN: 5, // 签到积分 + RECORD: 10, // 记录一次积分 + AI_COST: 100 // AI问答消耗积分 +} + +// 获取当前积分 +export function getPoints(): number { + return wx.getStorageSync('points') || 0 +} + +// 签到 +export function addSignInPoint() { + const lastSignDate = wx.getStorageSync('lastSignDate') + const today = getDateStr(Date.now()) + + if (lastSignDate === today) { + uni.showToast({ title: '今天已经签到过了', icon: 'success' }) + } + + const currentPoints = getPoints() + POINTS.SIGN_IN + wx.setStorageSync('points', currentPoints) + wx.setStorageSync('lastSignDate', today) + + uni.showToast({ title: '今日签到成功', icon: 'success' }) +} + +// 记录一次健康数据 +export function addRecordPoint() { + // 累计记录次数 + const recordCount = (wx.getStorageSync('recordCount') || 0) + 1 + wx.setStorageSync('recordCount', recordCount) + + // 累计积分 + const today = getDateStr(Date.now()) + const lastRecordDate = wx.getStorageSync('lastRecordDate') + const todayRecordCount = lastRecordDate === today ? wx.getStorageSync('todayRecordCount') || 0 : 0 + + if (todayRecordCount >= 5) { + return + } + + wx.setStorageSync('lastRecordDate', today) + wx.setStorageSync('todayRecordCount', todayRecordCount + 1) + + const currentPoints = getPoints() + POINTS.RECORD + wx.setStorageSync('points', currentPoints) +} + +// 兑换AI问答 +function exchangeAIPoint() { + const currentPoints = getPoints() + + if (currentPoints < POINTS.AI_COST) { + return { + success: false, + msg: `积分不足,还需要${POINTS.AI_COST - currentPoints}分` + } + } + + wx.setStorageSync('points', currentPoints - POINTS.AI_COST) + + // 累计兑换次数 + const aiCount = (wx.getStorageSync('aiCount') || 0) + 1 + wx.setStorageSync('aiCount', aiCount) +} + +export function getRecordCount() :number { + return uni.getStorageSync('recordCount') || 0 +} + +export function getAchievement() :string { + const recordCount = uni.getStorageSync('recordCount') || 0 + + if (recordCount >= 1000) return '💎 传奇健康家' + if (recordCount >= 500) return '🏆 数据大师' + if (recordCount >= 100) return '🌳 健康先锋' + if (recordCount >= 50) return '🌿 记录达人' + if (recordCount >= 10) return '🌱 健康新手' + + return '暂无成就' +} diff --git a/src/utils/record.ts b/src/utils/record.ts index c746752..640ad1f 100644 --- a/src/utils/record.ts +++ b/src/utils/record.ts @@ -1,6 +1,7 @@ import { getProfile } from '@/utils/profile' import type { IGroupHealthRecord, IHealthRecord, IRecordMeta, IRecordStats } from "@/type/record"; import type { IStats } from "@/type"; +import { addRecordPoint } from "@/utils/points"; const MAX_RECORD = 1000; const RECORD_PREFIX = 'health_' @@ -72,6 +73,8 @@ function addRecord(type: string, data: Record, timestamp: number) { wx.setStorageSync(key, all) appendRecentRecord(type, record) + + addRecordPoint() } /**