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 @@
+
+
+
+
+ 积分与成就说明
+
+
+
+
+ ✨ 积分规则
+
+
+ 每日签到:+5 积分
+ 记录健康数据:+10 积分(每日上限5次)
+ 咨询AI助手:-100 积分
+ 删除数据不影响已获得的积分
+
+
+
+
+ 🏆 成就说明
+
+
+ 🌱 健康新手:累计记录 10 次
+ 🌿 记录达人:累计记录 50 次
+ 🌳 健康先锋:累计记录 100 次
+ 🏆 数据大师:累计记录 500 次
+ 💎 传奇健康家:累计记录 1000 次
+
+
+
+
+
+
+
+
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()
}
/**