Files

609 lines
25 KiB
HTML

<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!-- 页面描述:预算管理页面,展示总体预算概览和各类别预算进度 -->
<title>预算管理 - 个人记账</title>
<!-- 引入公共样式 -->
<link rel="stylesheet" href="./css/style.css">
<!-- 引入Google Fonts - Inter -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">
<style>
/* ========================================
预算页面专用样式
======================================== */
/* 顶部操作栏 */
.page-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: var(--space-6);
}
.page-header-left {
display: flex;
align-items: center;
gap: var(--space-4);
}
.page-title {
font-size: 24px;
font-weight: 600;
color: var(--text-primary);
}
/* 概览卡片 */
.overview-card {
background: var(--surface);
border-radius: var(--radius-lg);
padding: var(--space-6);
box-shadow: var(--shadow-sm);
margin-bottom: var(--space-6);
display: flex;
align-items: center;
gap: var(--space-8);
}
.progress-ring-container {
position: relative;
width: 160px;
height: 160px;
flex-shrink: 0;
}
.progress-ring {
transform: rotate(-90deg);
}
.progress-ring-bg {
fill: none;
stroke: var(--border);
stroke-width: 12;
}
.progress-ring-fill {
fill: none;
stroke: var(--primary);
stroke-width: 12;
stroke-linecap: round;
stroke-dasharray: 408;
stroke-dashoffset: 147;
}
.progress-ring-text {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
text-align: center;
}
.progress-ring-percentage {
font-size: 30px;
font-weight: 700;
color: var(--text-primary);
line-height: 1;
}
.progress-ring-label {
font-size: 12px;
color: var(--text-secondary);
margin-top: var(--space-1);
}
.overview-info {
flex: 1;
}
.overview-info-title {
font-size: 18px;
font-weight: 600;
color: var(--text-primary);
margin-bottom: var(--space-4);
}
.overview-stats {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: var(--space-6);
}
.overview-stat {
display: flex;
flex-direction: column;
gap: var(--space-1);
}
.overview-stat-label {
font-size: 12px;
color: var(--text-secondary);
}
.overview-stat-value {
font-size: 24px;
font-weight: 700;
font-feature-settings: 'tnum';
}
.overview-stat-value.used { color: var(--danger); }
.overview-stat-value.remaining { color: var(--success); }
/* 预算列表 */
.section-title {
font-size: 14px;
font-weight: 600;
color: var(--text-secondary);
margin-bottom: var(--space-4);
padding-left: var(--space-3);
border-left: 3px solid var(--primary);
}
.budget-list {
background: var(--surface);
border-radius: var(--radius-lg);
box-shadow: var(--shadow-sm);
overflow: hidden;
}
.budget-item {
padding: var(--space-4) var(--space-5);
border-bottom: 1px solid var(--border);
}
.budget-item:last-child {
border-bottom: none;
}
.budget-item:hover {
background: #fafafa;
}
.budget-item-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: var(--space-3);
}
.budget-item-left {
display: flex;
align-items: center;
gap: var(--space-3);
}
.budget-category-icon {
width: 40px;
height: 40px;
border-radius: var(--radius-md);
display: flex;
align-items: center;
justify-content: center;
font-size: 20px;
}
.budget-category-name {
font-size: 16px;
font-weight: 600;
color: var(--text-primary);
}
.budget-amounts {
font-size: 14px;
color: var(--text-secondary);
margin-top: var(--space-1);
}
.btn-ghost {
display: inline-flex;
align-items: center;
gap: var(--space-2);
padding: 8px 16px;
background: transparent;
color: var(--primary);
border: none;
border-radius: var(--radius-md);
font-size: 14px;
font-weight: 500;
cursor: pointer;
transition: background-color 0.15s ease;
}
.btn-ghost:hover {
background: var(--primary-light);
}
/* Primary 按钮 - 设置预算按钮 */
.btn-primary {
display: inline-flex;
align-items: center;
justify-content: center;
gap: 6px;
padding: 8px 18px;
min-height: 40px;
background: var(--primary);
color: #ffffff;
border: none;
border-radius: var(--radius-md);
cursor: pointer;
font-size: 14px;
font-weight: 500;
line-height: 1.4;
white-space: nowrap;
transition: all 0.2s ease;
}
.btn-primary:hover {
background: var(--primary-hover);
}
.btn-primary svg {
width: 16px;
height: 16px;
flex-shrink: 0;
}
.budget-progress {
margin-bottom: var(--space-2);
}
.budget-progress-bar {
height: 8px;
background: var(--border);
border-radius: var(--radius-sm);
overflow: hidden;
}
.budget-progress-fill {
height: 100%;
border-radius: var(--radius-sm);
transition: width 0.3s ease;
}
.budget-progress-fill.normal { background: var(--success); }
.budget-progress-fill.warning { background: var(--warning); }
.budget-progress-fill.danger { background: var(--danger); }
.budget-item-footer {
display: flex;
justify-content: space-between;
align-items: center;
}
.budget-percentage { font-size: 12px; font-weight: 600; }
.budget-percentage.normal { color: var(--success); }
.budget-percentage.warning { color: var(--warning); }
.budget-percentage.danger { color: var(--danger); }
.budget-remaining { font-size: 12px; color: var(--text-secondary); }
.budget-remaining.overdue { color: var(--danger); font-weight: 500; }
.warning-tag {
display: inline-flex;
align-items: center;
gap: var(--space-1);
padding: 4px 8px;
background: rgba(255, 179, 0, 0.15);
color: var(--warning);
border-radius: var(--radius-sm);
font-size: 12px;
font-weight: 500;
}
/* 响应式 */
@media (max-width: 767px) {
.overview-card {
flex-direction: column;
padding: var(--space-5);
gap: var(--space-5);
}
.progress-ring-container {
width: 140px;
height: 140px;
}
.overview-stats {
grid-template-columns: repeat(3, 1fr);
gap: var(--space-4);
width: 100%;
}
.overview-stat-value { font-size: 20px; }
.budget-item { padding: var(--space-4); }
.page-title { font-size: 18px; }
}
</style>
</head>
<body>
<!-- 主布局容器 -->
<div class="app-layout">
<!-- 桌面端侧边栏 -->
<aside class="sidebar" role="navigation" aria-label="侧边导航">
<div class="sidebar-logo">
<div class="sidebar-logo-content">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="24" height="24">
<path d="M21 12V7H5a2 2 0 0 1 0-4h14v4"/>
<path d="M3 5v14a2 2 0 0 0 2 2h16v-5"/>
<path d="M18 12a2 2 0 0 0 0 4h4v-4h-4z"/>
</svg>
<span>个人记账</span>
</div>
<!-- 折叠按钮 -->
<div class="sidebar-toggle-wrapper" data-tooltip="收起侧边栏">
<button class="sidebar-toggle" type="button" aria-label="折叠/展开侧边栏">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<polyline points="15 18 9 12 15 6"/>
</svg>
</button>
</div>
</div>
<nav class="sidebar-nav">
<a href="index.html" class="sidebar-nav-item">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"/>
<polyline points="9 22 9 12 15 12 15 22"/>
</svg>
<span>首页</span>
</a>
<a href="record.html" class="sidebar-nav-item">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M12 2v20M17 5H9.5a3.5 3.5 0 0 0 0 7h5a3.5 3.5 0 0 1 0 7H6"/>
</svg>
<span>记账</span>
</a>
<a href="budget.html" class="sidebar-nav-item active" aria-current="page">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<rect x="2" y="3" width="20" height="14" rx="2" ry="2"/>
<line x1="8" y1="21" x2="16" y2="21"/>
<line x1="12" y1="17" x2="12" y2="21"/>
</svg>
<span>预算</span>
</a>
<a href="statistics.html" class="sidebar-nav-item">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<line x1="18" y1="20" x2="18" y2="10"/>
<line x1="12" y1="20" x2="12" y2="4"/>
<line x1="6" y1="20" x2="6" y2="14"/>
</svg>
<span>统计</span>
</a>
</nav>
</aside>
<!-- 主内容区 -->
<main class="main-content">
<!-- 顶部操作栏 -->
<header class="page-header">
<div class="page-header-left">
<button class="back-btn" aria-label="返回">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
<path stroke-linecap="round" stroke-linejoin="round" d="M15 19l-7-7 7-7" />
</svg>
</button>
<h1 class="page-title">预算管理</h1>
</div>
<button class="btn-primary">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
<path stroke-linecap="round" stroke-linejoin="round" d="M12 4v16m8-8H4" />
</svg>
<span>设置预算</span>
</button>
</header>
<!-- 总体概览卡片 -->
<section class="overview-card">
<!-- 环形进度图 - SVG实现 -->
<div class="progress-ring-container">
<svg class="progress-ring" width="160" height="160">
<circle
class="progress-ring-bg"
cx="80"
cy="80"
r="65"
/>
<circle
class="progress-ring-fill"
cx="80"
cy="80"
r="65"
/>
</svg>
<div class="progress-ring-text">
<div class="progress-ring-percentage">64%</div>
<div class="progress-ring-label">已使用</div>
</div>
</div>
<!-- 概览信息 -->
<div class="overview-info">
<h2 class="overview-info-title">本月总预算</h2>
<div class="overview-stats">
<div class="overview-stat">
<span class="overview-stat-label">总预算</span>
<span class="overview-stat-value total">¥5,000</span>
</div>
<div class="overview-stat">
<span class="overview-stat-label">已用</span>
<span class="overview-stat-value used">¥3,200</span>
</div>
<div class="overview-stat">
<span class="overview-stat-label">剩余</span>
<span class="overview-stat-value remaining">¥1,800</span>
</div>
</div>
</div>
</section>
<!-- 类别预算列表 -->
<h3 class="section-title">类别预算</h3>
<div class="budget-list">
<!-- 餐饮 - 70% 正常 -->
<article class="budget-item">
<div class="budget-item-header">
<div class="budget-item-left">
<div class="budget-category-icon" style="background: rgba(255, 179, 0, 0.15);">
<!-- 餐饮图标 -->
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
<path stroke-linecap="round" stroke-linejoin="round" d="M12 6.253v13m0-13C10.832 5.477 9.246 5 7.5 5S4.168 5.477 3 6.253v13C4.168 18.477 5.754 18 7.5 18s3.332.477 4.5 1.253m0-13C13.168 5.477 14.754 5 16.5 5c1.747 0 3.332.477 4.5 1.253v13C19.832 18.477 18.247 18 16.5 18c-1.746 0-3.332.477-4.5 1.253" />
</svg>
</div>
<span class="budget-category-name">餐饮</span>
</div>
<button class="btn-ghost" aria-label="编辑餐饮预算">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
<path stroke-linecap="round" stroke-linejoin="round" d="M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z" />
</svg>
<span>编辑</span>
</button>
</div>
<div class="budget-amounts">¥1,050 / ¥1,500</div>
<div class="budget-progress">
<div class="budget-progress-bar">
<div class="budget-progress-fill normal" style="width: 70%;"></div>
</div>
</div>
<div class="budget-item-footer">
<span class="budget-percentage normal">70%</span>
<span class="budget-remaining">剩余 ¥450</span>
</div>
</article>
<!-- 交通 - 45% 正常 -->
<article class="budget-item">
<div class="budget-item-header">
<div class="budget-item-left">
<div class="budget-category-icon" style="background: rgba(0, 184, 212, 0.15);">
<!-- 交通图标 -->
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
<path stroke-linecap="round" stroke-linejoin="round" d="M8 7h8m-8 4h8m-6 4h4M4 7h.01M4 15h16a1 1 0 001-1V8a1 1 0 00-1-1H4a1 1 0 00-1 1v6a1 1 0 001 1z" />
</svg>
</div>
<span class="budget-category-name">交通</span>
</div>
<button class="btn-ghost" aria-label="编辑交通预算">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
<path stroke-linecap="round" stroke-linejoin="round" d="M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z" />
</svg>
<span>编辑</span>
</button>
</div>
<div class="budget-amounts">¥225 / ¥500</div>
<div class="budget-progress">
<div class="budget-progress-bar">
<div class="budget-progress-fill normal" style="width: 45%;"></div>
</div>
</div>
<div class="budget-item-footer">
<span class="budget-percentage normal">45%</span>
<span class="budget-remaining">剩余 ¥275</span>
</div>
</article>
<!-- 购物 - 25% 正常 -->
<article class="budget-item">
<div class="budget-item-header">
<div class="budget-item-left">
<div class="budget-category-icon" style="background: rgba(156, 39, 176, 0.15);">
<!-- 购物图标 -->
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
<path stroke-linecap="round" stroke-linejoin="round" d="M16 11V7a4 4 0 00-8 0v4M5 9h14l1 12H4L5 9z" />
</svg>
</div>
<span class="budget-category-name">购物</span>
</div>
<button class="btn-ghost" aria-label="编辑购物预算">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
<path stroke-linecap="round" stroke-linejoin="round" d="M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z" />
</svg>
<span>编辑</span>
</button>
</div>
<div class="budget-amounts">¥250 / ¥1,000</div>
<div class="budget-progress">
<div class="budget-progress-bar">
<div class="budget-progress-fill normal" style="width: 25%;"></div>
</div>
</div>
<div class="budget-item-footer">
<span class="budget-percentage normal">25%</span>
<span class="budget-remaining">剩余 ¥750</span>
</div>
</article>
<!-- 娱乐 - 104% 超支 -->
<article class="budget-item">
<div class="budget-item-header">
<div class="budget-item-left">
<div class="budget-category-icon" style="background: rgba(233, 30, 99, 0.15);">
<!-- 娱乐图标 -->
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
<path stroke-linecap="round" stroke-linejoin="round" d="M14.828 14.828a4 4 0 01-5.656 0M9 10h.01M15 10h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
</div>
<span class="budget-category-name">娱乐</span>
<span class="warning-tag">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
<path stroke-linecap="round" stroke-linejoin="round" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z" />
</svg>
超支
</span>
</div>
<button class="btn-ghost" aria-label="编辑娱乐预算">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
<path stroke-linecap="round" stroke-linejoin="round" d="M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z" />
</svg>
<span>编辑</span>
</button>
</div>
<div class="budget-amounts">¥520 / ¥500</div>
<div class="budget-progress">
<div class="budget-progress-bar">
<div class="budget-progress-fill danger" style="width: 100%;"></div>
</div>
</div>
<div class="budget-item-footer">
<span class="budget-percentage danger">104%</span>
<span class="budget-remaining overdue">超支 ¥20</span>
</div>
</article>
</div>
</main>
</div>
<!-- 移动端底部Tab导航 -->
<nav class="bottom-tab-bar" role="navigation" aria-label="底部导航">
<a href="index.html" class="tab-item">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"/>
<polyline points="9 22 9 12 15 12 15 22"/>
</svg>
<span>首页</span>
</a>
<a href="record.html" class="tab-item">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M12 2v20M17 5H9.5a3.5 3.5 0 0 0 0 7h5a3.5 3.5 0 0 1 0 7H6"/>
</svg>
<span>记账</span>
</a>
<a href="budget.html" class="tab-item active" aria-current="page">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<rect x="2" y="3" width="20" height="14" rx="2" ry="2"/>
<line x1="8" y1="21" x2="16" y2="21"/>
<line x1="12" y1="17" x2="12" y2="21"/>
</svg>
<span>预算</span>
</a>
<a href="statistics.html" class="tab-item">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<line x1="18" y1="20" x2="18" y2="10"/>
<line x1="12" y1="20" x2="12" y2="4"/>
<line x1="6" y1="20" x2="6" y2="14"/>
</svg>
<span>统计</span>
</a>
</nav>
<!-- 侧边栏折叠功能 -->
<script src="./js/sidebar.js"></script>
</body>
</html>