fix
All checks were successful
Docker Build & Deploy / Build Docker Image (push) Successful in 4m27s
Docker Build & Deploy / Deploy to Production (push) Successful in 7s
Docker Build & Deploy / Cleanup Dangling Images (push) Successful in 1s
Docker Build & Deploy / WeChat Notification (push) Successful in 1s
All checks were successful
Docker Build & Deploy / Build Docker Image (push) Successful in 4m27s
Docker Build & Deploy / Deploy to Production (push) Successful in 7s
Docker Build & Deploy / Cleanup Dangling Images (push) Successful in 1s
Docker Build & Deploy / WeChat Notification (push) Successful in 1s
This commit is contained in:
23
Web/src/api/holiday.js
Normal file
23
Web/src/api/holiday.js
Normal file
@@ -0,0 +1,23 @@
|
||||
import request from './request'
|
||||
|
||||
/**
|
||||
* 获取指定年月的节假日数据
|
||||
*/
|
||||
export function getMonthHolidays (year, month) {
|
||||
return request({
|
||||
url: '/holiday/GetMonthHolidays',
|
||||
method: 'get',
|
||||
params: { year, month }
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 手动触发同步节假日数据
|
||||
*/
|
||||
export function syncHolidays (year) {
|
||||
return request({
|
||||
url: '/holiday/SyncHolidays',
|
||||
method: 'post',
|
||||
params: { year }
|
||||
})
|
||||
}
|
||||
@@ -167,7 +167,8 @@ onMounted(() => {
|
||||
left: 0;
|
||||
right: 0;
|
||||
width: 100%;
|
||||
height: 95px;
|
||||
// 基础高度 + 安全区域,确保在PWA中正确贴底
|
||||
height: calc(95px + env(safe-area-inset-bottom, 0px));
|
||||
z-index: 1000;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<!-- eslint-disable vue/no-v-html -->
|
||||
<!-- eslint-disable vue/no-v-html -->
|
||||
<template>
|
||||
<div class="page-container-flex">
|
||||
<van-nav-bar
|
||||
@@ -156,7 +156,7 @@
|
||||
description="暂无存款计划"
|
||||
/>
|
||||
</div>
|
||||
<div style="height: calc(50px + env(safe-area-inset-bottom, 0px))" />
|
||||
<div style="height: calc(95px + env(safe-area-inset-bottom, 0px))" />
|
||||
</van-pull-refresh>
|
||||
</van-tab>
|
||||
</van-tabs>
|
||||
@@ -417,7 +417,7 @@
|
||||
/>
|
||||
</template>
|
||||
</div>
|
||||
<div style="height: calc(50px + env(safe-area-inset-bottom, 0px))" />
|
||||
<div style="height: calc(95px + env(safe-area-inset-bottom, 0px))" />
|
||||
</van-pull-refresh>
|
||||
</PopupContainer>
|
||||
|
||||
@@ -649,7 +649,7 @@ const fetchCategoryStats = async () => {
|
||||
const data = res.data
|
||||
overallStats.value = {
|
||||
month: {
|
||||
rate: data.month?.rate?.toFixed(1) || '0.0',
|
||||
rate: data.month?.usagePercentage?.toFixed(1) || '0.0',
|
||||
current: data.month?.current || 0,
|
||||
limit: data.month?.limit || 0,
|
||||
count: data.month?.count || 0,
|
||||
@@ -657,7 +657,7 @@ const fetchCategoryStats = async () => {
|
||||
description: data.month?.description || ''
|
||||
},
|
||||
year: {
|
||||
rate: data.year?.rate?.toFixed(1) || '0.0',
|
||||
rate: data.year?.usagePercentage?.toFixed(1) || '0.0',
|
||||
current: data.year?.current || 0,
|
||||
limit: data.year?.limit || 0,
|
||||
count: data.year?.count || 0,
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
/>
|
||||
|
||||
<!-- 底部安全距离 -->
|
||||
<div style="height: calc(60px + env(safe-area-inset-bottom, 0px))" />
|
||||
<div style="height: calc(95px + env(safe-area-inset-bottom, 0px))" />
|
||||
|
||||
<!-- 日期交易列表弹出层 -->
|
||||
<PopupContainer
|
||||
|
||||
@@ -137,7 +137,7 @@
|
||||
/>
|
||||
</van-cell-group>
|
||||
<!-- 底部安全距离 -->
|
||||
<div style="height: calc(80px + env(safe-area-inset-bottom, 0px))" />
|
||||
<div style="height: calc(95px + env(safe-area-inset-bottom, 0px))" />
|
||||
</div>
|
||||
|
||||
<!-- 液态玻璃底部导航栏 -->
|
||||
|
||||
@@ -101,8 +101,7 @@ const router = useRouter()
|
||||
|
||||
// 底部导航栏
|
||||
const activeTab = ref('calendar')
|
||||
const handleTabClick = (item, index) => {
|
||||
console.log('Tab clicked:', item.name, index)
|
||||
const handleTabClick = () => {
|
||||
// 导航逻辑已在组件内部处理
|
||||
}
|
||||
|
||||
@@ -212,7 +211,14 @@ const onDatePickerConfirm = ({ selectedValues }) => {
|
||||
|
||||
// 更新日期
|
||||
currentDate.value = newDate
|
||||
selectedDate.value = newDate
|
||||
|
||||
// 判断是否选择了当前月(复用上面的 today 变量)
|
||||
const isCurrentMonth = newDate.getFullYear() === today.getFullYear() &&
|
||||
newDate.getMonth() === today.getMonth()
|
||||
|
||||
// 如果选择的是当前月,选中今天;否则选中该月第一天
|
||||
selectedDate.value = isCurrentMonth ? today : newDate
|
||||
|
||||
calendarKey.value += 1
|
||||
showDatePicker.value = false
|
||||
}
|
||||
@@ -258,9 +264,16 @@ const changeMonth = async (offset) => {
|
||||
|
||||
currentDate.value = newDate
|
||||
|
||||
// 根据切换方向选择合适的日期
|
||||
// 判断是否切换到当前月(复用上面的 today 变量)
|
||||
const isCurrentMonth = newDate.getFullYear() === today.getFullYear() &&
|
||||
newDate.getMonth() === today.getMonth()
|
||||
|
||||
// 根据切换方向和是否为当前月选择合适的日期
|
||||
let newSelectedDate
|
||||
if (offset > 0) {
|
||||
if (isCurrentMonth) {
|
||||
// 如果切换到当前月,选中今天
|
||||
newSelectedDate = today
|
||||
} else if (offset > 0) {
|
||||
// 切换到下个月,选中下个月的第一天
|
||||
newSelectedDate = new Date(newDate.getFullYear(), newDate.getMonth(), 1)
|
||||
} else {
|
||||
@@ -387,8 +400,8 @@ onBeforeUnmount(() => {
|
||||
background-color: var(--bg-primary);
|
||||
}
|
||||
|
||||
/* 底部安全距离 */
|
||||
/* 底部安全距离 - 匹配底部导航栏高度 */
|
||||
.bottom-spacer {
|
||||
height: calc(60px + env(safe-area-inset-bottom, 0px));
|
||||
height: calc(95px + env(safe-area-inset-bottom, 0px));
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -32,6 +32,8 @@
|
||||
:key="day.date"
|
||||
class="day-cell"
|
||||
@click="onDayClick(day)"
|
||||
@touchstart="onTouchStartHoliday($event, day)"
|
||||
@touchend="onTouchEndHoliday"
|
||||
>
|
||||
<div
|
||||
class="day-number"
|
||||
@@ -40,10 +42,19 @@
|
||||
'day-selected': day.isSelected,
|
||||
'day-has-data': day.hasData,
|
||||
'day-over-limit': day.isOverLimit,
|
||||
'day-other-month': !day.isCurrentMonth
|
||||
'day-other-month': !day.isCurrentMonth,
|
||||
'day-holiday': day.isHoliday && day.isRest,
|
||||
'day-workday': day.isWorkday
|
||||
}"
|
||||
>
|
||||
{{ day.dayNumber }}
|
||||
<!-- 节假日标记 -->
|
||||
<span
|
||||
v-if="day.isHoliday"
|
||||
class="holiday-badge"
|
||||
>
|
||||
{{ day.isWorkday ? '班' : '休' }}
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
v-if="day.amount"
|
||||
@@ -60,6 +71,26 @@
|
||||
</div>
|
||||
</Transition>
|
||||
</div>
|
||||
|
||||
<!-- 节假日提示浮层 -->
|
||||
<van-overlay
|
||||
:show="showHolidayTooltip"
|
||||
@click="closeHolidayTooltip"
|
||||
>
|
||||
<div
|
||||
class="holiday-tooltip-wrapper"
|
||||
@click.stop
|
||||
>
|
||||
<div class="holiday-tooltip">
|
||||
<div class="tooltip-title">
|
||||
{{ currentHolidayName }}
|
||||
</div>
|
||||
<div class="tooltip-desc">
|
||||
{{ currentHolidayDesc }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</van-overlay>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -67,6 +98,7 @@
|
||||
import { computed, watch, ref } from 'vue'
|
||||
import { getDailyStatistics } from '@/api/statistics'
|
||||
import { getBudgetList } from '@/api/budget'
|
||||
import { getMonthHolidays } from '@/api/holiday'
|
||||
|
||||
const props = defineProps({
|
||||
currentDate: Date,
|
||||
@@ -90,6 +122,13 @@ const weekDays = ['一', '二', '三', '四', '五', '六', '日']
|
||||
const dailyStatsMap = ref({})
|
||||
const dailyBudget = ref(0)
|
||||
const loading = ref(false)
|
||||
const holidaysMap = ref({}) // 节假日数据映射
|
||||
|
||||
// 节假日提示相关
|
||||
const showHolidayTooltip = ref(false)
|
||||
const currentHolidayName = ref('')
|
||||
const currentHolidayDesc = ref('')
|
||||
let holdTimer = null
|
||||
|
||||
// 获取月度每日统计数据
|
||||
const fetchDailyStats = async (year, month) => {
|
||||
@@ -101,7 +140,9 @@ const fetchDailyStats = async (year, month) => {
|
||||
// 构建日期 Map
|
||||
const statsMap = {}
|
||||
response.data.forEach(item => {
|
||||
statsMap[item.date] = {
|
||||
// 后端返回的是 day (1-31),需要构建完整的日期字符串
|
||||
const dateKey = `${year}-${String(month).padStart(2, '0')}-${String(item.day).padStart(2, '0')}`
|
||||
statsMap[dateKey] = {
|
||||
count: item.count,
|
||||
expense: item.expense,
|
||||
income: item.income
|
||||
@@ -142,18 +183,20 @@ const fetchAllRelevantMonthsData = async (year, month) => {
|
||||
|
||||
// 并行加载所有需要的月份数据
|
||||
// JavaScript Date.month 是 0-11,但后端 API 期望 1-12
|
||||
const promises = [fetchDailyStats(year, month + 1)]
|
||||
const promises = [fetchDailyStats(year, month + 1), fetchHolidays(year, month + 1)]
|
||||
|
||||
if (needPrevMonth) {
|
||||
const prevMonth = month === 0 ? 11 : month - 1
|
||||
const prevYear = month === 0 ? year - 1 : year
|
||||
promises.push(fetchDailyStats(prevYear, prevMonth + 1))
|
||||
promises.push(fetchHolidays(prevYear, prevMonth + 1))
|
||||
}
|
||||
|
||||
if (needNextMonth) {
|
||||
const nextMonth = month === 11 ? 0 : month + 1
|
||||
const nextYear = month === 11 ? year + 1 : year
|
||||
promises.push(fetchDailyStats(nextYear, nextMonth + 1))
|
||||
promises.push(fetchHolidays(nextYear, nextMonth + 1))
|
||||
}
|
||||
|
||||
await Promise.all(promises)
|
||||
@@ -178,6 +221,23 @@ const fetchBudgetData = async () => {
|
||||
}
|
||||
}
|
||||
|
||||
// 获取节假日数据
|
||||
const fetchHolidays = async (year, month) => {
|
||||
try {
|
||||
const response = await getMonthHolidays(year, month)
|
||||
if (response.success && response.data) {
|
||||
const map = {}
|
||||
response.data.forEach(item => {
|
||||
map[item.date] = item
|
||||
})
|
||||
holidaysMap.value = { ...holidaysMap.value, ...map }
|
||||
}
|
||||
} catch (error) {
|
||||
// 静默失败,仅记录日志
|
||||
console.error('获取节假日数据失败:', error)
|
||||
}
|
||||
}
|
||||
|
||||
// 监听 currentDate 变化,重新加载数据
|
||||
watch(() => props.currentDate, async (newDate) => {
|
||||
if (newDate) {
|
||||
@@ -251,6 +311,7 @@ const createDayObject = (date, isCurrentMonth) => {
|
||||
// 从 API 数据获取
|
||||
const dateKey = formatDateKey(date)
|
||||
const dayStats = dailyStatsMap.value[dateKey] || {}
|
||||
const holidayInfo = holidaysMap.value[dateKey] // 获取节假日信息
|
||||
|
||||
// 计算净支出(支出 - 收入)
|
||||
const netAmount = (dayStats.expense || 0) - (dayStats.income || 0)
|
||||
@@ -258,6 +319,30 @@ const createDayObject = (date, isCurrentMonth) => {
|
||||
// 收入大于支出为盈利(绿色),否则为支出(红色)
|
||||
const isProfitable = hasData && netAmount < 0
|
||||
|
||||
// 判断是否是周末(0=周日, 6=周六)
|
||||
const dayOfWeek = date.getDay()
|
||||
const isWeekend = dayOfWeek === 0 || dayOfWeek === 6
|
||||
|
||||
// 节假日逻辑判断
|
||||
let isHoliday = false
|
||||
let holidayName = ''
|
||||
let isWorkday = false
|
||||
let isRest = false
|
||||
|
||||
if (holidayInfo) {
|
||||
// 有节假日信息,以节假日信息为准
|
||||
isHoliday = true
|
||||
holidayName = holidayInfo.holidayName
|
||||
isWorkday = holidayInfo.dayType === 3 // 调休工作日
|
||||
isRest = holidayInfo.rest === 1
|
||||
} else if (isWeekend) {
|
||||
// 没有节假日信息,但是周末,标记为普通休息日
|
||||
isHoliday = true
|
||||
holidayName = dayOfWeek === 0 ? '周日' : '周六'
|
||||
isWorkday = false
|
||||
isRest = true
|
||||
}
|
||||
|
||||
return {
|
||||
date: date.getTime(),
|
||||
dayNumber: date.getDate(),
|
||||
@@ -267,7 +352,12 @@ const createDayObject = (date, isCurrentMonth) => {
|
||||
hasData,
|
||||
amount: hasData ? Math.abs(netAmount).toFixed(0) : '',
|
||||
isOverLimit: netAmount > (dailyBudget.value || 0), // 超过每日预算标红
|
||||
isProfitable // 是否盈利(收入>支出)
|
||||
isProfitable, // 是否盈利(收入>支出)
|
||||
// 节假日信息
|
||||
isHoliday,
|
||||
holidayName,
|
||||
isWorkday, // 调休工作日
|
||||
isRest // 是否休息
|
||||
}
|
||||
}
|
||||
|
||||
@@ -284,6 +374,31 @@ const onDayClick = (day) => {
|
||||
emit('dayClick', day)
|
||||
}
|
||||
|
||||
// 节假日长按事件处理
|
||||
const onTouchStartHoliday = (e, day) => {
|
||||
if (!day.isHoliday) {return}
|
||||
|
||||
// 长按500ms显示提示
|
||||
holdTimer = setTimeout(() => {
|
||||
currentHolidayName.value = day.holidayName
|
||||
currentHolidayDesc.value = day.isWorkday
|
||||
? `${day.holidayName} - 调休工作日`
|
||||
: `${day.holidayName} - 休息日`
|
||||
showHolidayTooltip.value = true
|
||||
}, 500)
|
||||
}
|
||||
|
||||
const onTouchEndHoliday = () => {
|
||||
if (holdTimer) {
|
||||
clearTimeout(holdTimer)
|
||||
holdTimer = null
|
||||
}
|
||||
}
|
||||
|
||||
const closeHolidayTooltip = () => {
|
||||
showHolidayTooltip.value = false
|
||||
}
|
||||
|
||||
// 触摸事件
|
||||
const onTouchStart = (e) => {
|
||||
emit('touchStart', e)
|
||||
@@ -384,7 +499,8 @@ const onTouchEnd = () => {
|
||||
.calendar-grid-wrapper {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
overflow: hidden; /* 保持 hidden 以支持切换动画 */
|
||||
padding-top: 4px; /* 新增:为第一行的徽章留出空间 */
|
||||
}
|
||||
|
||||
.calendar-grid {
|
||||
@@ -392,6 +508,7 @@ const onTouchEnd = () => {
|
||||
flex-direction: column;
|
||||
gap: var(--spacing-lg);
|
||||
width: 100%;
|
||||
padding-top: 4px; /* 新增:为第一行徽章留出空间 */
|
||||
}
|
||||
|
||||
.calendar-week {
|
||||
@@ -410,6 +527,7 @@ const onTouchEnd = () => {
|
||||
}
|
||||
|
||||
.day-number {
|
||||
position: relative; /* 为绝对定位的徽章提供定位上下文 */
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
@@ -451,4 +569,65 @@ const onTouchEnd = () => {
|
||||
.day-amount.amount-profit {
|
||||
color: var(--accent-success);
|
||||
}
|
||||
|
||||
/* ========== 节假日样式 ========== */
|
||||
/* 节假日放假样式(绿色系) */
|
||||
.day-number.day-holiday {
|
||||
background: linear-gradient(135deg, #E8F5E9 0%, #C8E6C9 100%);
|
||||
color: #2E7D32;
|
||||
font-weight: var(--font-bold);
|
||||
}
|
||||
|
||||
/* 调休工作日样式(橙色/黄色系) */
|
||||
.day-number.day-workday {
|
||||
background: linear-gradient(135deg, #FFF3E0 0%, #FFE0B2 100%);
|
||||
color: #E65100;
|
||||
font-weight: var(--font-bold);
|
||||
}
|
||||
|
||||
/* 节假日标记 */
|
||||
.holiday-badge {
|
||||
position: absolute;
|
||||
top: -2px;
|
||||
right: -2px;
|
||||
font-size: 9px;
|
||||
background-color: var(--accent-danger);
|
||||
color: white;
|
||||
border-radius: 4px;
|
||||
padding: 1px 3px;
|
||||
line-height: 1.2;
|
||||
font-weight: var(--font-bold);
|
||||
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
|
||||
z-index: 100;
|
||||
}
|
||||
|
||||
/* 节假日提示浮层 */
|
||||
.holiday-tooltip-wrapper {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.holiday-tooltip {
|
||||
background: white;
|
||||
border-radius: 12px;
|
||||
padding: 24px;
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
|
||||
max-width: 280px;
|
||||
}
|
||||
|
||||
.tooltip-title {
|
||||
font-size: 18px;
|
||||
font-weight: bold;
|
||||
color: var(--text-primary);
|
||||
margin-bottom: 8px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.tooltip-desc {
|
||||
font-size: 14px;
|
||||
color: var(--text-secondary);
|
||||
text-align: center;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -243,7 +243,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<!-- 底部安全距离 -->
|
||||
<div style="height: calc(50px + env(safe-area-inset-bottom, 0px))" />
|
||||
<div style="height: calc(95px + env(safe-area-inset-bottom, 0px))" />
|
||||
</div>
|
||||
</div>
|
||||
</van-pull-refresh>
|
||||
|
||||
@@ -397,12 +397,21 @@ const loadWeeklyData = async () => {
|
||||
})
|
||||
|
||||
if (dailyResult?.success && dailyResult.data) {
|
||||
// 转换数据格式以适配图表组件
|
||||
trendStats.value = dailyResult.data.map(item => ({
|
||||
date: item.date,
|
||||
amount: (item.income || 0) - (item.expense || 0),
|
||||
count: item.count || 0
|
||||
}))
|
||||
// ⚠️ 注意: API 返回的 data 按日期顺序排列,但只有 day 字段(天数)
|
||||
// 需要根据 weekStart 和索引重建完整日期
|
||||
trendStats.value = dailyResult.data.map((item, index) => {
|
||||
// 从 weekStart 开始,按索引递增天数
|
||||
const date = new Date(weekStart)
|
||||
date.setDate(weekStart.getDate() + index)
|
||||
const dateStr = formatDateToString(date)
|
||||
|
||||
return {
|
||||
date: dateStr,
|
||||
expense: item.expense || 0,
|
||||
income: item.income || 0,
|
||||
count: item.count || 0
|
||||
}
|
||||
})
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('加载周度数据失败:', error)
|
||||
@@ -638,6 +647,9 @@ const isLastPeriod = () => {
|
||||
const handleTouchStart = (e) => {
|
||||
touchStartX.value = e.touches[0].clientX
|
||||
touchStartY.value = e.touches[0].clientY
|
||||
// 重置 touchEnd 值,防止使用上次的残留值
|
||||
touchEndX.value = touchStartX.value
|
||||
touchEndY.value = touchStartY.value
|
||||
}
|
||||
|
||||
const handleTouchMove = (e) => {
|
||||
@@ -645,12 +657,21 @@ const handleTouchMove = (e) => {
|
||||
touchEndY.value = e.touches[0].clientY
|
||||
}
|
||||
|
||||
const handleTouchEnd = () => {
|
||||
const handleTouchEnd = (e) => {
|
||||
// 如果 touchEnd 事件中还有 changedTouches,使用它来获取最终位置
|
||||
if (e.changedTouches && e.changedTouches.length > 0) {
|
||||
touchEndX.value = e.changedTouches[0].clientX
|
||||
touchEndY.value = e.changedTouches[0].clientY
|
||||
}
|
||||
|
||||
const deltaX = touchEndX.value - touchStartX.value
|
||||
const deltaY = touchEndY.value - touchStartY.value
|
||||
|
||||
// 判断是否是水平滑动(水平距离大于垂直距离)
|
||||
if (Math.abs(deltaX) > Math.abs(deltaY) && Math.abs(deltaX) > 50) {
|
||||
// 最小滑动距离阈值(像素)
|
||||
const MIN_SWIPE_DISTANCE = 50
|
||||
|
||||
// 判断是否是水平滑动(水平距离大于垂直距离且超过阈值)
|
||||
if (Math.abs(deltaX) > Math.abs(deltaY) && Math.abs(deltaX) > MIN_SWIPE_DISTANCE) {
|
||||
if (deltaX > 0) {
|
||||
// 右滑 - 上一个周期
|
||||
handlePrevPeriod()
|
||||
@@ -744,7 +765,7 @@ onMounted(() => {
|
||||
overflow-y: auto;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
overscroll-behavior: contain;
|
||||
background-color: var(--bg-secondary);
|
||||
background-color: var(--bg-primary);
|
||||
/* 改善滚动性能 */
|
||||
will-change: scroll-position;
|
||||
/* 防止滚动卡顿 */
|
||||
@@ -753,7 +774,7 @@ onMounted(() => {
|
||||
|
||||
.statistics-content {
|
||||
padding: var(--spacing-md);
|
||||
padding-bottom: calc(80px + env(safe-area-inset-bottom, 0px));
|
||||
padding-bottom: calc(95px + env(safe-area-inset-bottom, 0px));
|
||||
min-height: 100%;
|
||||
/* 确保内容足够高以便滚动 */
|
||||
display: flex;
|
||||
@@ -781,7 +802,7 @@ onMounted(() => {
|
||||
|
||||
.statistics-content {
|
||||
padding: var(--spacing-sm);
|
||||
padding-bottom: calc(90px + env(safe-area-inset-bottom, 0px));
|
||||
padding-bottom: calc(95px + env(safe-area-inset-bottom, 0px));
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,4 +1,4 @@
|
||||
<template>
|
||||
<template>
|
||||
<div class="daily-trend-card common-card">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">
|
||||
@@ -333,7 +333,7 @@ onBeforeUnmount(() => {
|
||||
@import '@/assets/theme.css';
|
||||
|
||||
.daily-trend-card {
|
||||
background: var(--bg-primary);
|
||||
background: var(--bg-secondary);
|
||||
border-radius: var(--radius-lg);
|
||||
padding: var(--spacing-xl);
|
||||
margin-bottom: var(--spacing-xl);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<template>
|
||||
<template>
|
||||
<!-- 支出分类统计 -->
|
||||
<div
|
||||
class="common-card"
|
||||
@@ -274,7 +274,7 @@ onBeforeUnmount(() => {
|
||||
|
||||
// 通用卡片样式
|
||||
.common-card {
|
||||
background: var(--bg-primary);
|
||||
background: var(--bg-secondary);
|
||||
border-radius: var(--radius-lg);
|
||||
padding: var(--spacing-xl);
|
||||
margin-bottom: var(--spacing-xl);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<template>
|
||||
<template>
|
||||
<div class="income-balance-card common-card">
|
||||
<div class="stats-row">
|
||||
<div class="stat-item">
|
||||
@@ -50,7 +50,7 @@ const balanceClass = computed(() => ({
|
||||
@import '@/assets/theme.css';
|
||||
|
||||
.income-balance-card {
|
||||
background: var(--bg-primary);
|
||||
background: var(--bg-secondary);
|
||||
border-radius: var(--radius-lg);
|
||||
padding: var(--spacing-xl);
|
||||
margin-bottom: var(--spacing-xl);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<template>
|
||||
<template>
|
||||
<!-- 收支和不计收支并列显示 -->
|
||||
<div class="side-by-side-cards">
|
||||
<!-- 收入分类统计 -->
|
||||
@@ -155,7 +155,7 @@ const noneCategories = computed(() => {
|
||||
|
||||
// 通用卡片样式
|
||||
.common-card {
|
||||
background: var(--bg-primary);
|
||||
background: var(--bg-secondary);
|
||||
border-radius: var(--radius-lg);
|
||||
padding: var(--spacing-xl);
|
||||
margin-bottom: var(--spacing-xl);
|
||||
|
||||
@@ -373,18 +373,16 @@ const updateChart = () => {
|
||||
}
|
||||
}
|
||||
|
||||
// 显示累计值和当日值
|
||||
// 只显示当日值
|
||||
params.forEach((param) => {
|
||||
const color = param.seriesName === '支出' ? '#ff6b6b' : '#4ade80'
|
||||
const cumulativeValue = param.value
|
||||
const dailyValue = param.seriesName === '支出' ? dailyExpense : dailyIncome
|
||||
|
||||
content += `<span style="display:inline-block;margin-right:5px;border-radius:50%;width:10px;height:10px;background-color:${color}"></span>`
|
||||
content += `${param.seriesName}累计: ¥${cumulativeValue.toFixed(2)}`
|
||||
if (dailyValue > 0) {
|
||||
content += ` (当日: ¥${dailyValue.toFixed(2)})`
|
||||
content += `<span style="display:inline-block;margin-right:5px;border-radius:50%;width:10px;height:10px;background-color:${color}"></span>`
|
||||
content += `${param.seriesName}: ¥${dailyValue.toFixed(2)}`
|
||||
content += '<br/>'
|
||||
}
|
||||
content += '<br/>'
|
||||
})
|
||||
} catch (error) {
|
||||
console.warn('格式化tooltip失败:', error)
|
||||
@@ -432,7 +430,7 @@ onBeforeUnmount(() => {
|
||||
|
||||
// 通用卡片样式
|
||||
.common-card {
|
||||
background: var(--bg-primary);
|
||||
background: var(--bg-secondary);
|
||||
border-radius: var(--radius-lg);
|
||||
padding: var(--spacing-xl);
|
||||
margin-bottom: var(--spacing-xl);
|
||||
|
||||
Reference in New Issue
Block a user