refactor: trim smoke home API usage
This commit is contained in:
@@ -3,30 +3,14 @@ import { BASE_URL } from '@/config'
|
||||
|
||||
const BASE_URL_V2 = BASE_URL.replace('/v1', '/v2')
|
||||
|
||||
export function getDashboard(params = {}) {
|
||||
return request.get('/smoke/dashboard', params)
|
||||
}
|
||||
|
||||
export function getHome(params = {}) {
|
||||
return request.get('/smoke/home', params)
|
||||
}
|
||||
|
||||
export function getNextSmokeTime(params = {}) {
|
||||
return request.get('/smoke/next_smoke_time', params)
|
||||
}
|
||||
|
||||
export function getLogs(params = {}) {
|
||||
return request.get('/smoke/logs', params)
|
||||
}
|
||||
|
||||
export function getLatestLogs(limit = 20) {
|
||||
return request.get('/smoke/logs/latest', { limit })
|
||||
}
|
||||
|
||||
export function getLog(id) {
|
||||
return request.get(`/smoke/logs/${id}`)
|
||||
}
|
||||
|
||||
export function createLog(data) {
|
||||
return request.post('/smoke/logs', data)
|
||||
}
|
||||
@@ -39,14 +23,6 @@ export function deleteLog(id) {
|
||||
return request.delete(`/smoke/logs/${id}`)
|
||||
}
|
||||
|
||||
export function createResistedLog(data) {
|
||||
return request.post('/smoke/logs/resisted', data)
|
||||
}
|
||||
|
||||
export function getAiAdvice(date) {
|
||||
return request.get('/smoke/ai/advice', { date })
|
||||
}
|
||||
|
||||
export function unlockAiAdvice(data) {
|
||||
return request.post('/smoke/ai/advice_unlocks', data)
|
||||
}
|
||||
@@ -71,10 +47,6 @@ export function getShareData(shareToken, params = {}) {
|
||||
return request.get(`/smoke/share/${shareToken}`, params)
|
||||
}
|
||||
|
||||
export function revokeShare(shareToken) {
|
||||
return request.post(`/smoke/share/${shareToken}/revoke`)
|
||||
}
|
||||
|
||||
// 戒烟计划 API
|
||||
export function generateQuitPlan() {
|
||||
return request.post('/smoke/quit-plan/generate')
|
||||
|
||||
+14
-128
@@ -204,26 +204,6 @@
|
||||
<text class="record-bio-metric-name">{{ item.name }}</text>
|
||||
<text class="record-bio-metric-value">{{ item.value }}</text>
|
||||
</view>
|
||||
<view class="record-bio-divider"></view>
|
||||
<view class="record-bio-life-row">
|
||||
<text class="record-bio-life-value">+{{ recordLifeSaved }} 小时</text>
|
||||
<text class="record-bio-life-label">生命已回收</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="record-bio-trend-card">
|
||||
<view class="record-bio-section-head record-bio-section-head-compact">
|
||||
<text class="record-bio-section-title">7 天节奏</text>
|
||||
<text class="record-bio-section-chip">{{ recordStatusLabel }}</text>
|
||||
</view>
|
||||
<view class="record-bio-trend-chart">
|
||||
<view v-for="item in recordTrendItems" :key="item.label" class="record-bio-trend-col">
|
||||
<view class="record-bio-trend-line" :style="{ height: item.height }">
|
||||
<view class="record-bio-trend-dot" :class="{ 'record-bio-trend-dot-active': item.active }"></view>
|
||||
</view>
|
||||
<text class="record-bio-trend-label">{{ item.label }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
@@ -330,6 +310,7 @@ const timerSeconds = ref(0) // 页面存活期间累计秒数
|
||||
const isQuitMode = computed(() => userStore.mode === 'quit')
|
||||
const homeSummary = computed(() => homeData.value?.summary || {})
|
||||
const homeTimer = computed(() => homeData.value?.timer || {})
|
||||
const homeMotivation = computed(() => homeData.value?.motivation || {})
|
||||
const quitSummary = computed(() => quitHomeData.value?.summary || {})
|
||||
const quitDailyStatus = computed(() => quitHomeData.value?.daily_status || {})
|
||||
|
||||
@@ -340,6 +321,7 @@ const packPriceYuan = computed(() => (profileStore.profile?.pack_price_cent || 2
|
||||
// ========== 记录模式 ==========
|
||||
|
||||
const todayCount = computed(() => homeSummary.value.today_count ?? 0)
|
||||
const resistedCount = computed(() => homeSummary.value.resisted_count ?? 0)
|
||||
const dailyTarget = computed(() => {
|
||||
const target = homeSummary.value.daily_target
|
||||
if (target != null) return target
|
||||
@@ -386,12 +368,6 @@ const todayCountRingStyle = computed(() => {
|
||||
|
||||
const recordHasData = computed(() => todayCount.value > 0 || timerBaseSeconds.value >= 0)
|
||||
|
||||
// 今日节省(比目标少抽的部分换算)
|
||||
const recordSavedMoney = computed(() => {
|
||||
const saved = Math.max(0, (dailyTarget.value - todayCount.value) * (packPriceYuan.value / 20))
|
||||
return saved.toFixed(1)
|
||||
})
|
||||
|
||||
const recordHeroTitle = computed(() => {
|
||||
if (!recordHasData.value) return '先记录第一刻'
|
||||
if (todayCount.value === 0) return '今天还没抽烟'
|
||||
@@ -408,25 +384,19 @@ const recordRhythmText = computed(() => {
|
||||
|
||||
const achievementCardTitle = computed(() => isQuitMode.value ? '无烟等级' : '长期记录等级')
|
||||
|
||||
// 今日延长生命时长(每少一支 = 11 分钟)
|
||||
const recordLifeSaved = computed(() => {
|
||||
const minutes = Math.max(0, (dailyTarget.value - todayCount.value) * 11)
|
||||
return Math.round(minutes / 60 * 10) / 10
|
||||
})
|
||||
|
||||
const reducePercent = computed(() => {
|
||||
if (dailyTarget.value <= 0) return 0
|
||||
return Math.round(Math.max(0, dailyTarget.value - todayCount.value) / dailyTarget.value * 100)
|
||||
})
|
||||
|
||||
const recordHealthTip = computed(() => {
|
||||
if (homeMotivation.value.message) return homeMotivation.value.message
|
||||
if (todayCount.value === 0) return '今天还没抽烟,继续保持!'
|
||||
if (todayCount.value < dailyTarget.value) return `今天比目标少抽了${dailyTarget.value - todayCount.value}根,很棒!`
|
||||
if (todayCount.value === dailyTarget.value) return '今天已达到目标,加油!'
|
||||
return '今天超标了,明天继续努力'
|
||||
})
|
||||
|
||||
const recordGoalLeft = computed(() => Math.max(0, dailyTarget.value - todayCount.value))
|
||||
const recordControlScore = computed(() => {
|
||||
if (!dailyTarget.value || dailyTarget.value <= 0) return todayCount.value > 0 ? 40 : 88
|
||||
const score = Math.round((1 - Math.min(todayCount.value / dailyTarget.value, 1)) * 72) + 18
|
||||
@@ -450,26 +420,20 @@ const recordControlRingStyle = computed(() => {
|
||||
return { background: `conic-gradient(${accent} 0deg ${angle}deg, rgba(226, 232, 240, 0.78) ${angle}deg 360deg)` }
|
||||
})
|
||||
|
||||
const recordYesterdayText = computed(() => {
|
||||
const reduced = Number(homeSummary.value.reduced_from_yesterday)
|
||||
if (Number.isNaN(reduced)) return '暂无对比'
|
||||
if (reduced === 0) return '持平'
|
||||
return homeSummary.value.exceeded_yesterday ? `多 ${reduced} 根` : `少 ${reduced} 根`
|
||||
})
|
||||
|
||||
const recordBioHealthItems = computed(() => [
|
||||
{ name: '今日目标', value: `${todayCount.value}/${dailyTarget.value || '-'} 根` },
|
||||
{ name: '剩余额度', value: `${recordGoalLeft.value} 根` },
|
||||
{ name: '节省金额', value: `¥${recordSavedMoney.value}` }
|
||||
{ name: '今日忍住', value: `${resistedCount.value} 次` },
|
||||
{ name: '较昨日', value: recordYesterdayText.value },
|
||||
{ name: '建议时间', value: nextSmokeTimeText.value || '--:--' }
|
||||
])
|
||||
|
||||
const recordTrendItems = computed(() => {
|
||||
const labels = ['周一', '周二', '周三', '周四', '周五', '周六', '周日']
|
||||
const target = Math.max(dailyTarget.value || baselineCigsPerDay.value || 1, 1)
|
||||
return labels.map((label, index) => {
|
||||
const estimated = Math.max(0, todayCount.value + index - 6)
|
||||
const value = index === labels.length - 1 ? todayCount.value : Math.min(target, estimated)
|
||||
return {
|
||||
label,
|
||||
height: `${Math.max(24, Math.round((value / target) * 112))}rpx`,
|
||||
active: index === labels.length - 1
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
// ========== 戒烟模式 ==========
|
||||
|
||||
// 服务端连续无烟天数优先,失败时从本地缓存推算
|
||||
@@ -2793,7 +2757,6 @@ onShareAppMessage(() => ({
|
||||
.record-bio-status-card,
|
||||
.record-bio-console-card,
|
||||
.record-bio-health-card,
|
||||
.record-bio-trend-card,
|
||||
.record-bio-achievement-card,
|
||||
.record-bio-tip-card {
|
||||
position: relative;
|
||||
@@ -3060,7 +3023,6 @@ onShareAppMessage(() => ({
|
||||
}
|
||||
|
||||
.record-bio-health-card,
|
||||
.record-bio-trend-card,
|
||||
.record-bio-achievement-card {
|
||||
padding: 28rpx;
|
||||
border-radius: 34rpx;
|
||||
@@ -3170,82 +3132,6 @@ onShareAppMessage(() => ({
|
||||
color: #0F766E;
|
||||
}
|
||||
|
||||
.record-bio-divider {
|
||||
height: 1rpx;
|
||||
margin: 12rpx 0 14rpx;
|
||||
background: rgba(148, 163, 184, 0.18);
|
||||
}
|
||||
|
||||
.record-bio-life-row {
|
||||
@include flex-col;
|
||||
gap: 4rpx;
|
||||
}
|
||||
|
||||
.record-bio-life-value {
|
||||
font-size: 34rpx;
|
||||
line-height: 1.2;
|
||||
font-weight: 900;
|
||||
color: var(--record-gold);
|
||||
}
|
||||
|
||||
.record-bio-life-label {
|
||||
font-size: 21rpx;
|
||||
font-weight: 800;
|
||||
color: #64748B;
|
||||
}
|
||||
|
||||
.record-bio-trend-card {
|
||||
background: linear-gradient(135deg, #ECFDF5 0%, #F0F9FF 100%);
|
||||
}
|
||||
|
||||
.record-bio-trend-chart {
|
||||
height: 176rpx;
|
||||
margin-top: 22rpx;
|
||||
padding: 0 4rpx;
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
justify-content: space-between;
|
||||
border-bottom: 1rpx solid rgba(100, 116, 139, 0.18);
|
||||
}
|
||||
|
||||
.record-bio-trend-col {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
@include flex-center;
|
||||
flex-direction: column;
|
||||
justify-content: flex-end;
|
||||
gap: 10rpx;
|
||||
}
|
||||
|
||||
.record-bio-trend-line {
|
||||
position: relative;
|
||||
width: 4rpx;
|
||||
border-radius: 999rpx;
|
||||
background: linear-gradient(180deg, rgba(251, 191, 36, 0.86), rgba(103, 232, 249, 0.5));
|
||||
}
|
||||
|
||||
.record-bio-trend-dot {
|
||||
position: absolute;
|
||||
top: -8rpx;
|
||||
left: 50%;
|
||||
width: 16rpx;
|
||||
height: 16rpx;
|
||||
margin-left: -8rpx;
|
||||
border-radius: 50%;
|
||||
background: #67E8F9;
|
||||
box-shadow: 0 0 0 5rpx rgba(103, 232, 249, 0.14);
|
||||
}
|
||||
|
||||
.record-bio-trend-dot-active {
|
||||
background: var(--record-gold);
|
||||
box-shadow: 0 0 0 6rpx rgba(251, 191, 36, 0.18);
|
||||
}
|
||||
|
||||
.record-bio-trend-label {
|
||||
font-size: 18rpx;
|
||||
color: #64748B;
|
||||
}
|
||||
|
||||
.record-bio-achievement-card {
|
||||
background: linear-gradient(135deg, rgba(255, 255, 255, 0.78), rgba(250, 245, 255, 0.5));
|
||||
}
|
||||
@@ -3296,4 +3182,4 @@ onShareAppMessage(() => ({
|
||||
line-height: 1.55;
|
||||
color: #475569;
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
|
||||
@@ -1,72 +0,0 @@
|
||||
import { defineStore } from 'pinia'
|
||||
import { getDashboard, getNextSmokeTime } from '@/api/smoke'
|
||||
|
||||
export const useDashboardStore = defineStore('dashboard', {
|
||||
state: () => ({
|
||||
todayCount: 0,
|
||||
minutesSinceLast: 0,
|
||||
weekly: [],
|
||||
nextSmokeTime: null,
|
||||
lastFetchTime: 0,
|
||||
cacheExpiry: 30 * 1000,
|
||||
loading: false
|
||||
}),
|
||||
|
||||
getters: {
|
||||
isCacheValid: (state) => {
|
||||
return Date.now() - state.lastFetchTime < state.cacheExpiry
|
||||
}
|
||||
},
|
||||
|
||||
actions: {
|
||||
async fetchDashboard(forceRefresh = false) {
|
||||
if (!forceRefresh && this.isCacheValid) {
|
||||
return
|
||||
}
|
||||
|
||||
this.loading = true
|
||||
try {
|
||||
const res = await getDashboard()
|
||||
this.todayCount = res.data.today_count || 0
|
||||
this.minutesSinceLast = res.data.minutes_since_last || 0
|
||||
this.weekly = res.data.weekly || []
|
||||
this.lastFetchTime = Date.now()
|
||||
} catch (e) {
|
||||
console.error('fetchDashboard error:', e)
|
||||
throw e
|
||||
} finally {
|
||||
this.loading = false
|
||||
}
|
||||
},
|
||||
|
||||
async fetchNextSmokeTime() {
|
||||
try {
|
||||
const res = await getNextSmokeTime()
|
||||
this.nextSmokeTime = res.data
|
||||
return res.data
|
||||
} catch (e) {
|
||||
console.error('fetchNextSmokeTime error:', e)
|
||||
throw e
|
||||
}
|
||||
},
|
||||
|
||||
setDashboard(data) {
|
||||
this.todayCount = data.today_count || 0
|
||||
this.minutesSinceLast = data.minutes_since_last || 0
|
||||
this.weekly = data.weekly || []
|
||||
this.lastFetchTime = Date.now()
|
||||
},
|
||||
|
||||
setNextSmokeTime(data) {
|
||||
this.nextSmokeTime = data
|
||||
},
|
||||
|
||||
incrementTodayCount() {
|
||||
this.todayCount++
|
||||
},
|
||||
|
||||
resetTimer() {
|
||||
this.minutesSinceLast = 0
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -5,6 +5,5 @@ const pinia = createPinia()
|
||||
export default pinia
|
||||
|
||||
export * from './user'
|
||||
export * from './dashboard'
|
||||
export * from './profile'
|
||||
export * from './logs'
|
||||
|
||||
Reference in New Issue
Block a user