refactor ui layout for home and stats

This commit is contained in:
你çšnepiedg
2026-03-19 01:17:00 +08:00
parent 55f5c216bd
commit ee4beaa7a0
3 changed files with 531 additions and 441 deletions
+1 -1
View File
@@ -21,7 +21,7 @@
{ {
"path": "pages/stats/index", "path": "pages/stats/index",
"style": { "style": {
"navigationBarTitleText": "数据统计分析" "navigationStyle": "custom"
} }
}, },
{ {
+504 -427
View File
File diff suppressed because it is too large Load Diff
+26 -13
View File
@@ -3,7 +3,7 @@
<view class="page-glow page-glow-a"></view> <view class="page-glow page-glow-a"></view>
<view class="page-glow page-glow-b"></view> <view class="page-glow page-glow-b"></view>
<view class="sticky-bar"> <view class="sticky-bar">
<view class="status-bar" :style="{ height: statusBarHeight + 'px' }"></view> <view class="status-bar" :style="{ height: navBarHeight + 'px' }"></view>
<view class="page-head"> <view class="page-head">
<text class="page-eyebrow">Statistics</text> <text class="page-eyebrow">Statistics</text>
<text class="page-title">数据统计</text> <text class="page-title">数据统计</text>
@@ -55,7 +55,7 @@
<scroll-view v-if="trendItems.length > 0" scroll-x class="trend-chart-scroll" :show-scrollbar="false"> <scroll-view v-if="trendItems.length > 0" scroll-x class="trend-chart-scroll" :show-scrollbar="false">
<view class="trend-chart" :style="{ minWidth: trendChartMinWidth }"> <view class="trend-chart" :style="{ minWidth: trendChartMinWidth }">
<view v-for="(item, index) in trendItems" :key="index" class="trend-bar-item"> <view v-for="(item, index) in trendItems" :key="index" class="trend-bar-item">
<view v-if="item.isHighlight" class="trend-bubble">{{ item.count }}</view> <view v-if="item.isHighlight && item.count > 0" class="trend-bubble">{{ item.count }}</view>
<view class="trend-bar-wrap"> <view class="trend-bar-wrap">
<view class="trend-bar" :style="{ height: item.height }"></view> <view class="trend-bar" :style="{ height: item.height }"></view>
</view> </view>
@@ -193,7 +193,7 @@ import { useLogin } from '@/hooks/useLogin'
import * as api from '@/api' import * as api from '@/api'
const { waitForLogin } = useLogin() const { waitForLogin } = useLogin()
const statusBarHeight = ref(0) const navBarHeight = ref(0)
const tabs = [ const tabs = [
{ label: '周', value: 'week' }, { label: '周', value: 'week' },
@@ -264,8 +264,8 @@ const statusIconClass = computed(() => {
const averageCount = computed(() => { const averageCount = computed(() => {
const avg = statsData.value?.daily_average const avg = statsData.value?.daily_average
if (avg === undefined || avg === null) return 1 if (avg === undefined || avg === null) return 0
return avg return Number(avg) || 0
}) })
// 图表仅使用接口返回的 trend 渲染,无数据时为空 // 图表仅使用接口返回的 trend 渲染,无数据时为空
@@ -275,10 +275,13 @@ const trendItems = computed(() => {
if (!trend || !Array.isArray(trend) || trend.length === 0) { if (!trend || !Array.isArray(trend) || trend.length === 0) {
return [] return []
} }
const maxCount = Math.max(...trend.map(item => Number(item.count) || 0), 1) const counts = trend.map(item => Number(item.count) || 0)
const maxCount = Math.max(...counts, 0)
return trend.map((item, index) => { return trend.map((item, index) => {
const count = Number(item.count) || 0 const count = Number(item.count) || 0
const height = `${Math.max((count / maxCount) * 100, 6)}%` const height = maxCount > 0
? `${Math.max((count / maxCount) * 100, count > 0 ? 6 : 0)}%`
: '0%'
return { return {
label: formatTrendLabel(item.label, trendUnit), label: formatTrendLabel(item.label, trendUnit),
count, count,
@@ -485,6 +488,17 @@ function formatRangeText(start, end) {
return `${startMonth}${startDay}日-${endMonth}${endDay}` return `${startMonth}${startDay}日-${endMonth}${endDay}`
} }
function setupNavBar() {
const systemInfo = uni.getSystemInfoSync()
const statusBarH = systemInfo.statusBarHeight || 0
try {
const menuBtn = uni.getMenuButtonBoundingClientRect()
navBarHeight.value = menuBtn.bottom + (menuBtn.top - statusBarH)
} catch (e) {
navBarHeight.value = statusBarH + 44
}
}
async function fetchStats() { async function fetchStats() {
try { try {
await waitForLogin() await waitForLogin()
@@ -500,8 +514,7 @@ watch(currentTab, () => {
}) })
onMounted(() => { onMounted(() => {
const sys = uni.getSystemInfoSync() setupNavBar()
statusBarHeight.value = Math.max((sys.statusBarHeight || 0) - 20, 0)
fetchStats() fetchStats()
}) })
@@ -560,11 +573,13 @@ onShareAppMessage(() => {
top: 0; top: 0;
z-index: 20; z-index: 20;
background: linear-gradient(180deg, rgba(237, 242, 248, 0.96) 0%, rgba(245, 247, 251, 0.92) 76%, rgba(251, 253, 255, 0) 100%); background: linear-gradient(180deg, rgba(237, 242, 248, 0.96) 0%, rgba(245, 247, 251, 0.92) 76%, rgba(251, 253, 255, 0) 100%);
padding-left: 8rpx;
padding-right: 8rpx;
padding-bottom: 8rpx; padding-bottom: 8rpx;
} }
.page-head { .page-head {
padding: 18rpx 0 18rpx; padding: 24rpx 14rpx 18rpx;
} }
.page-eyebrow { .page-eyebrow {
@@ -599,7 +614,7 @@ onShareAppMessage(() => {
padding: 6rpx; padding: 6rpx;
border-radius: 24rpx; border-radius: 24rpx;
gap: 6rpx; gap: 6rpx;
margin-bottom: 16rpx; margin: 0 6rpx 16rpx;
border: 2rpx solid rgba(255, 255, 255, 0.66); border: 2rpx solid rgba(255, 255, 255, 0.66);
box-shadow: 0 12rpx 28rpx rgba(15, 23, 42, 0.06); box-shadow: 0 12rpx 28rpx rgba(15, 23, 42, 0.06);
backdrop-filter: blur(24rpx); backdrop-filter: blur(24rpx);
@@ -1371,5 +1386,3 @@ onShareAppMessage(() => {
display: block; display: block;
} }
</style> </style>