每日不定时更新,涵盖软件、教程、素材等资源下载。找免费资源就来酷玩资源网。

纯离线html:积分小管家:用积分带娃

酸奶丿果冻 HTML源码 0

现在学校、小饭桌,都采取积分奖励式带娃,之前dy也看到有大神做了app,不过是私用的。
前两天在公众号看到一个网页版的积分小管家,便用这个模板,用AI优化了一下,纯离线运行,历史数据可以保存,可以清控,设置可以重置、自定义,非常轻便,发到手机上,点开就能用,不到100kb。

txt改成html就行,要是有大神能封装成一个app就好了,不过估计app安装包可能就不止100km了


<!DOCTYPE html>
<html lang="zh-CN">
<head><meta name="robots" content="noindex,nofollow"><meta name="generator" content="ShipPage"><link rel="canonical" href="https://shippage.ai/p/jifen">
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
    <title>积分小管家</title>
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }

        body {
            font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
            background: linear-gradient(135deg, #4ade80 0%, #22c55e 100%);
            min-height: 100vh;
            color: #333;
            padding-bottom: 80px;
        }

        /* 顶部导航 */
        .header {
            background: rgba(255, 255, 255, 0.95);
            padding: 15px 20px;
            position: sticky;
            top: 0;
            z-index: 100;
            box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
        }

        /* 周积分网格样式 */
        .day-item {
            cursor: pointer;
            transition: all 0.2s ease;
            background: #f8f9fa;
            border-radius: 10px;
            padding: 10px 5px;
            text-align: center;
        }

        .day-item:hover {
            transform: translateY(-2px);
        }

        .day-item:active {
            transform: scale(0.95);
        }

        .day-item.selected {
            background: rgba(34, 197, 94, 0.1);
        }

        .day-points.today-points {
            font-weight: 800;
            font-size: 18px;
        }

        .day-points.selected-points {
            font-weight: 600;
            font-size: 16px;
            opacity: 0.8;
        }

        .header h1 {
            font-size: 20px;
            font-weight: 700;
            color: #22c55e;
            text-align: center;
        }

        /* 积分卡片 */
        .points-card {
            background: linear-gradient(135deg, #22c55e 0%, #16a34a 100%);
            margin: 20px;
            padding: 24px 20px;
            border-radius: 20px;
            color: white;
            box-shadow: 0 8px 20px rgba(34, 197, 94, 0.4);
            text-align: center;
        }

        .points-header {
            display: flex;
            align-items: baseline;
            justify-content: center;
            gap: 12px;
            margin-bottom: 8px;
        }

        .points-title {
            font-size: 16px;
            font-weight: 600;
            opacity: 0.85;
            letter-spacing: 2px;
        }

        .points-amount {
            font-size: 56px;
            font-weight: 900;
            text-shadow: 0 2px 8px rgba(0,0,0,0.2);
            letter-spacing: 2px;
        }

        .points-today {
            display: flex;
            align-items: center;
            justify-content: center;
            gap: 10px;
            font-size: 14px;
            background: rgba(255,255,255,0.15);
            border-radius: 12px;
            padding: 8px 16px;
            margin: 0 auto;
            width: fit-content;
        }

        .today-divider {
            width: 1px;
            height: 18px;
            background: rgba(255, 255, 255, 0.5);
        }

        .today-value {
            font-weight: 800;
            font-size: 15px;
        }

        .points-actions {
            display: flex;
            gap: 8px;
            margin-top: 12px;
        }

        .points-btn {
            flex: 1;
            padding: 10px;
            border: none;
            border-radius: 12px;
            font-size: 14px;
            font-weight: 600;
            cursor: pointer;
            transition: all 0.3s;
        }

        .points-btn.primary {
            background: white;
            color: #22c55e;
        }

        .points-btn.danger {
            background: rgba(239, 68, 68, 0.9);
            color: white;
        }

        .points-btn:active {
            transform: scale(0.95);
        }

        /* 功能入口 */
        .features {
            display: grid;
            grid-template-columns: repeat(3, 1fr);
            gap: 10px;
            padding: 0 20px;
            margin-bottom: 15px;
        }

        .feature-item {
            background: rgba(255, 255, 255, 0.95);
            border-radius: 14px;
            padding: 12px 8px;
            text-align: center;
            cursor: pointer;
            box-shadow: 0 4px 15px rgba(0, 0, 0, 0.05);
            transition: all 0.3s;
        }

        .feature-item:active {
            transform: scale(0.95);
        }

        .feature-icon {
            font-size: 24px;
            margin-bottom: 6px;
        }

        .feature-name {
            font-size: 11px;
            color: #333;
            font-weight: 600;
        }

        /* 内容区域 */
        .content-section {
            background: white;
            margin: 0 20px 15px;
            border-radius: 16px;
            padding: 15px;
            box-shadow: 0 4px 15px rgba(0, 0, 0, 0.05);
        }

        .section-title {
            display: flex;
            flex-direction: row;
            align-items: center;
            justify-content: space-between;
            gap: 8px;
            margin-bottom: 15px;
        }

        .section-title > span {
            font-size: 18px;
            font-weight: 700;
            color: #333;
        }

        .section-actions {
            display: flex;
            gap: 8px;
        }

        .action-btn {
            padding: 6px 12px;
            border: none;
            border-radius: 8px;
            font-size: 12px;
            font-weight: 600;
            cursor: pointer;
            transition: all 0.3s;
        }

        /* 手机端兼容性优化 */
        @media (max-width: 480px) {
            .action-btn {
                font-size: 11px;
                padding: 5px 10px;
            }

            .list-item {
                flex-wrap: wrap;
                gap: 10px;
            }

            .list-item .section-actions {
                width: 100%;
                justify-content: flex-end;
                margin-top: 5px;
            }
        }

        .action-btn.add {
            background: #22c55e;
            color: white;
        }

        .action-btn.edit {
            background: #f59e0b;
            color: white;
        }

        .action-btn.delete {
            background: #ef4444;
            color: white;
        }

        /* 列表项 */
        .list-item {
            display: flex;
            justify-content: space-between;
            align-items: center;
            padding: 15px;
            background: #f8f9fa;
            border-radius: 12px;
            margin-bottom: 10px;
        }

        .list-item:last-child {
            margin-bottom: 0;
        }

        .item-info {
            flex: 1;
        }

        .item-name {
            font-size: 14px;
            font-weight: 600;
            margin-bottom: 4px;
        }

        .item-points {
            font-size: 16px;
            font-weight: 700;
        }

        .item-points.income {
            color: #10b981;
        }

        .item-points.expense {
            color: #ef4444;
        }

        .item-actions {
            display: flex;
            gap: 8px;
        }

        .item-btn {
            padding: 6px 12px;
            border: none;
            border-radius: 8px;
            font-size: 12px;
            font-weight: 600;
            cursor: pointer;
        }

        .item-btn.earn {
            background: #10b981;
            color: white;
        }

        .item-btn.deduct {
            background: #ef4444;
            color: white;
        }

        .item-btn.exchange {
            background: #667eea;
            color: white;
        }

        /* 快速添加行 */
        .quick-add {
            display: flex;
            align-items: center;
            gap: 8px;
            padding: 10px;
            background: #f0fdf4;
            border: 1px dashed #22c55e;
            border-radius: 12px;
            margin-bottom: 12px;
        }

        .quick-add input {
            border: 1px solid #e5e7eb;
            border-radius: 8px;
            padding: 8px 10px;
            font-size: 13px;
            outline: none;
        }

        .quick-add input:focus {
            border-color: #22c55e;
        }

        .quick-add .qa-name {
            flex: 1;
            max-width: 50%;
        }

        .quick-add .qa-points {
            width: 80px;
            text-align: center;
        }

        .quick-add .qa-btn {
            padding: 8px 16px;
            background: #22c55e;
            color: white;
            border: none;
            border-radius: 8px;
            font-size: 13px;
            font-weight: 600;
            cursor: pointer;
            white-space: nowrap;
            margin-left: auto;
        }

        .quick-add .qa-btn:active {
            background: #16a34a;
        }

        .quick-add.deduct {
            background: #fef2f2;
            border-color: #fca5a5;
        }

        .quick-add.deduct input:focus {
            border-color: #ef4444;
        }

        .quick-add.deduct .qa-btn {
            background: #ef4444;
        }

        .quick-add.deduct .qa-btn:active {
            background: #dc2626;
        }

        .quick-add.exchange {
            background: #f5f3ff;
            border-color: #c4b5fd;
        }

        .quick-add.exchange input:focus {
            border-color: #667eea;
        }

        .quick-add.exchange .qa-btn {
            background: #667eea;
        }

        .quick-add.exchange .qa-btn:active {
            background: #4f46e5;
        }

        /* 周积分统计 */
        .week-stats {
            margin-bottom: 20px;
        }

        .week-grid {
            display: grid;
            grid-template-columns: repeat(7, 1fr);
            gap: 8px;
        }

        .day-item.today {
            background: linear-gradient(135deg, #22c55e 0%, #16a34a 100%);
            color: white;
        }

        .day-name {
            font-size: 10px;
            margin-bottom: 4px;
            color: #666;
        }

        .day-item.today .day-name {
            color: rgba(255, 255, 255, 0.9);
        }

        .day-points {
            font-size: 14px;
            font-weight: 700;
        }

        .day-item.today .day-points {
            color: white;
        }

        /* 历史积分月日历 */
        .month-calendar {
            background: #f8f9fa;
            border-radius: 12px;
            padding: 12px;
            margin-bottom: 12px;
        }

        .month-header {
            display: flex;
            align-items: center;
            margin-bottom: 10px;
        }

        .month-title {
            font-size: 14px;
            font-weight: 700;
        }

        .month-weekdays {
            display: grid;
            grid-template-columns: repeat(7, 1fr);
            gap: 4px;
            margin-bottom: 4px;
        }

        .month-weekday {
            text-align: center;
            font-size: 10px;
            color: #999;
            padding: 2px 0;
        }

        .month-days {
            display: grid;
            grid-template-columns: repeat(7, 1fr);
            gap: 4px;
        }

        .month-day {
            text-align: center;
            padding: 6px 2px;
            background: white;
            border-radius: 6px;
            min-height: 38px;
            display: flex;
            flex-direction: column;
            justify-content: center;
            align-items: center;
        }

        .month-day.empty {
            background: transparent;
        }

        .month-day.today {
            background: rgba(34, 197, 94, 0.15);
        }

        .month-day.today .month-day-num {
            font-weight: 700;
            color: #22c55e;
        }

        .month-day-num {
            font-size: 11px;
            color: #333;
            line-height: 1;
        }

        .month-day-pts {
            font-size: 10px;
            font-weight: 600;
            color: #22c55e;
            line-height: 1;
            margin-top: 1px;
        }

        /* 年历卡片 */
        .year-calendar {
            display: grid;
            grid-template-columns: repeat(6, 1fr);
            gap: 8px;
        }

        .year-month-card {
            background: #f8f9fa;
            border-radius: 10px;
            padding: 10px 6px;
            text-align: center;
        }

        .year-month-card.current {
            background: rgba(34, 197, 94, 0.1);
            border: 1.5px solid #22c55e;
        }

        .year-month-name {
            font-size: 11px;
            color: #666;
            margin-bottom: 4px;
        }

        .year-month-total {
            font-size: 16px;
            font-weight: 700;
            color: #22c55e;
        }

        /* 积分记录列表 */
        .record-list {
            max-height: 400px;
            overflow-y: auto;
        }

        .record-item {
            display: flex;
            justify-content: space-between;
            align-items: center;
            padding: 15px 0;
            border-bottom: 1px solid #f0f0f0;
        }

        .record-item:last-child {
            border-bottom: none;
        }

        .record-info {
            flex: 1;
        }

        .record-title {
            font-size: 14px;
            font-weight: 600;
            margin-bottom: 4px;
        }

        .record-time {
            font-size: 12px;
            color: #999;
        }

        .record-amount {
            font-size: 16px;
            font-weight: 700;
            padding-left: 10px;
            padding-right: 15px;
            margin: 5px 0;
        }

        .record-amount.income {
            color: #10b981;
        }

        .record-amount.expense {
            color: #ef4444;
        }

        /* 底部导航菜单 */
        .bottom-nav {
            position: fixed;
            bottom: 0;
            left: 0;
            right: 0;
            background: white;
            display: flex;
            justify-content: space-around;
            padding: 10px 0;
            padding-bottom: calc(10px + env(safe-area-inset-bottom));
            box-shadow: 0 -2px 10px rgba(0, 0, 0, 0.1);
            z-index: 100;
        }

        .nav-item {
            text-align: center;
            cursor: pointer;
            flex: 1;
        }

        .nav-icon {
            font-size: 22px;
            margin-bottom: 2px;
        }

        .nav-text {
            font-size: 11px;
            color: #999;
        }

        .nav-item.active .nav-text {
            color: #22c55e;
        }

        .nav-item.active .nav-icon {
            color: #22c55e;
        }

        /* 弹窗样式 */
        .modal {
            display: none;
            position: fixed;
            top: 0;
            left: 0;
            right: 0;
            bottom: 0;
            background: rgba(0, 0, 0, 0.5);
            z-index: 1000;
            align-items: center;
            justify-content: center;
        }

        .modal.show {
            display: flex;
        }

        .modal-content {
            background: white;
            border-radius: 20px;
            padding: 25px;
            width: 90%;
            max-width: 400px;
            animation: modalSlide 0.3s ease;
        }

        @keyframes modalSlide {
            from {
                transform: translateY(20px);
                opacity: 0;
            }
            to {
                transform: translateY(0);
                opacity: 1;
            }
        }

        .modal-title {
            font-size: 18px;
            font-weight: 700;
            margin-bottom: 20px;
            text-align: center;
        }

        .modal-body {
            margin-bottom: 20px;
        }

        .form-group {
            margin-bottom: 15px;
        }

        .form-label {
            display: block;
            font-size: 14px;
            font-weight: 600;
            margin-bottom: 8px;
            color: #333;
        }

        .form-input {
            width: 100%;
            padding: 12px;
            border: 2px solid #e0e0e0;
            border-radius: 10px;
            font-size: 14px;
            transition: all 0.3s;
        }

        .form-input:focus {
            outline: none;
            border-color: #22c55e;
        }

        .form-input[type="number"] {
            -moz-appearance: textfield;
        }

        .form-input[type="number"]::-webkit-outer-spin-button,
        .form-input[type="number"]::-webkit-inner-spin-button {
            -webkit-appearance: none;
            margin: 0;
        }

        .modal-footer {
            display: flex;
            gap: 10px;
        }

        .modal-btn {
            flex: 1;
            padding: 12px;
            border: none;
            border-radius: 10px;
            font-size: 14px;
            font-weight: 600;
            cursor: pointer;
        }

        .modal-btn.confirm {
            background: #22c55e;
            color: white;
        }

        .modal-btn.cancel {
            background: #f0f0f0;
            color: #666;
        }

        .modal-btn.danger {
            background: #ef4444;
            color: white;
        }

        /* 页面切换 */
        .page {
            display: none;
        }

        .page.active {
            display: block;
        }

        /* 空状态 */
        .empty-state {
            text-align: center;
            padding: 40px 20px;
            color: #999;
        }

        .empty-icon {
            font-size: 48px;
            margin-bottom: 12px;
        }

        .empty-text {
            font-size: 14px;
        }

        /* 响应式适配 */
        @media (max-width: 420px) {
            .points-amount {
                font-size: 48px;
            }

            .features {
                gap: 8px;
            }

            .week-grid {
                gap: 4px;
            }

            .day-item {
                padding: 8px 3px;
            }
        }
    </style>
</head>
<body>
    <!-- 顶部导航 -->
    <div class="header">
        <h1>积分小管家</h1>
    </div>

    <!-- 底部导航菜单 -->
    <div class="bottom-nav">
        <div class="nav-item active" onclick="switchPage('home')">
            <div class="nav-icon">🏠</div>
            <div class="nav-text">首页</div>
        </div>
    </div>

    <!-- 首页 -->
    <div class="page active" id="home-page">
        <!-- 积分卡片(总积分 + 今日积分合并) -->
        <div class="points-card">
            <div class="points-header">
                <div class="points-title">总积分</div>
                <div class="points-amount" id="total-points">0</div>
            </div>
            <div class="points-today">
                <span>📅 今日积分</span>
                <span class="today-divider"></span>
                <span class="today-value" id="daily-challenge">赚0分 - 扣0分 = 0分</span>
            </div>
        </div>

        <!-- 功能入口 -->
        <div class="features">
            <div class="feature-item" onclick="switchPage('earn')">
                <div class="feature-icon">➕</div>
                <div class="feature-name">赚取积分</div>
            </div>
            <div class="feature-item" onclick="switchPage('deduct')">
                <div class="feature-icon">➖</div>
                <div class="feature-name">扣取积分</div>
            </div>
            <div class="feature-item" onclick="switchPage('exchange')">
                <div class="feature-icon">🏪</div>
                <div class="feature-name">奖励兑换中心</div>
            </div>
            <div class="feature-item" onclick="switchPage('earn-manage')">
                <div class="feature-icon">💰</div>
                <div class="feature-name">积分项设置</div>
            </div>
            <div class="feature-item" onclick="switchPage('deduct-manage')">
                <div class="feature-icon">⚠️</div>
                <div class="feature-name">扣分项设置</div>
            </div>
            <div class="feature-item" onclick="switchPage('exchange-manage')">
                <div class="feature-icon">🎁</div>
                <div class="feature-name">兑换奖励设置</div>
            </div>
        </div>

        <!-- 本周积分 -->
        <div class="content-section">
            <div class="section-title">
                <span id="week-score-text">本周积分</span>
            </div>
            <div class="week-stats">
                <div class="week-grid" id="current-week-grid">
                    <!-- 动态加载 -->
                </div>
            </div>
        </div>

        <!-- 快捷工具 -->
        <div class="features">
            <div class="feature-item" onclick="switchPage('records')">
                <div class="feature-icon">📊</div>
                <div class="feature-name">积分记录</div>
            </div>
            <div class="feature-item" onclick="showClearPointsModal()">
                <div class="feature-icon">🗑️</div>
                <div class="feature-name">积分清空</div>
            </div>
            <div class="feature-item" onclick="systemReset()">
                <div class="feature-icon">🔄</div>
                <div class="feature-name">系统重置</div>
            </div>
        </div>
    </div>

    <!-- 赚取积分页面 -->
    <div class="page" id="earn-page">
        <div class="content-section">
            <div class="section-title">
                <span>赚取积分</span>
            </div>
            <div id="earn-list">
                <!-- 动态加载 -->
            </div>
        </div>
    </div>

    <!-- 扣取积分页面 -->
    <div class="page" id="deduct-page">
        <div class="content-section">
            <div class="section-title">
                <span>扣取积分</span>
            </div>
            <div id="deduct-list">
                <!-- 动态加载 -->
            </div>
        </div>
    </div>

    <!-- 兑换中心页面 -->
    <div class="page" id="exchange-page">
        <div class="content-section">
            <div class="section-title">
                <span>兑换中心</span>
            </div>
            <div id="exchange-list">
                <!-- 动态加载 -->
            </div>
        </div>
    </div>

    <!-- 赚取积分项管理页面 -->
    <div class="page" id="earn-manage-page">
        <div class="content-section">
            <div class="section-title">
                <span>赚取积分项管理</span>
                <div class="section-actions">
                    <button class="action-btn add" onclick="showAddEarnItemModal()">+ 添加</button>
                </div>
            </div>
            <div id="earn-manage-list">
                <!-- 动态加载 -->
            </div>
        </div>
    </div>

    <!-- 扣取积分项管理页面 -->
    <div class="page" id="deduct-manage-page">
        <div class="content-section">
            <div class="section-title">
                <span>扣取积分项管理</span>
                <div class="section-actions">
                    <button class="action-btn add" onclick="showAddDeductItemModal()">+ 添加</button>
                </div>
            </div>
            <div id="deduct-manage-list">
                <!-- 动态加载 -->
            </div>
        </div>
    </div>

    <!-- 兑换奖励管理页面 -->
    <div class="page" id="exchange-manage-page">
        <div class="content-section">
            <div class="section-title">
                <span>兑换奖励管理</span>
                <div class="section-actions">
                    <button class="action-btn add" onclick="showAddRewardModal()">+ 添加</button>
                </div>
            </div>
            <div id="reward-manage-list">
                <!-- 动态加载 -->
            </div>
        </div>
    </div>

    <!-- 积分记录页面 -->
    <div class="page" id="records-page">
        <div class="content-section">
            <div class="section-title">
                <span id="records-week-score-text">本周积分</span>
                <div class="section-actions">
                    <button class="action-btn add" onclick="showAddPointsModal()">补积分</button>
                </div>
            </div>
            <div class="week-stats">
                <div class="week-grid" id="records-week-grid">
                    <!-- 动态加载 -->
                </div>
            </div>
        </div>

        <div class="content-section">
            <div class="section-title">每日积分记录</div>
            <div class="record-list" id="day-records">
                <!-- 动态加载 -->
            </div>
        </div>

        <div class="content-section">
            <div class="section-title">历史积分</div>
            <div id="history-weeks">
                <!-- 动态加载 -->
            </div>
        </div>
    </div>

    <!-- 添加赚取积分项弹窗 -->
    <div class="modal" id="add-earn-item-modal">
        <div class="modal-content">
            <div class="modal-title" id="earn-item-modal-title">添加赚取积分项</div>
            <div class="modal-body">
                <div class="form-group">
                    <label class="form-label">项目名称</label>
                    <input type="text" class="form-input" id="earn-item-name" placeholder="例如:完成作业">
                </div>
                <div class="form-group">
                    <label class="form-label">积分数量</label>
                    <input type="number" class="form-input" id="earn-item-points" placeholder="例如:10">
                </div>
            </div>
            <div class="modal-footer">
                <button class="modal-btn cancel" onclick="closeModal('add-earn-item-modal')">取消</button>
                <button class="modal-btn confirm" onclick="saveEarnItem()">保存</button>
            </div>
        </div>
    </div>

    <!-- 添加扣取积分项弹窗 -->
    <div class="modal" id="add-deduct-item-modal">
        <div class="modal-content">
            <div class="modal-title" id="deduct-item-modal-title">添加扣取积分项</div>
            <div class="modal-body">
                <div class="form-group">
                    <label class="form-label">项目名称</label>
                    <input type="text" class="form-input" id="deduct-item-name" placeholder="例如:未完成作业">
                </div>
                <div class="form-group">
                    <label class="form-label">积分数量</label>
                    <input type="number" class="form-input" id="deduct-item-points" placeholder="例如:10">
                </div>
            </div>
            <div class="modal-footer">
                <button class="modal-btn cancel" onclick="closeModal('add-deduct-item-modal')">取消</button>
                <button class="modal-btn confirm" onclick="saveDeductItem()">保存</button>
            </div>
        </div>
    </div>

    <!-- 添加兑换奖励弹窗 -->
    <div class="modal" id="add-reward-modal">
        <div class="modal-content">
            <div class="modal-title" id="reward-modal-title">添加兑换奖励</div>
            <div class="modal-body">
                <div class="form-group">
                    <label class="form-label">奖励名称</label>
                    <input type="text" class="form-input" id="reward-name" placeholder="例如:看电视30分钟">
                </div>
                <div class="form-group">
                    <label class="form-label">所需积分</label>
                    <input type="number" class="form-input" id="reward-points" placeholder="例如:50">
                </div>
            </div>
            <div class="modal-footer">
                <button class="modal-btn cancel" onclick="closeModal('add-reward-modal')">取消</button>
                <button class="modal-btn confirm" onclick="saveReward()">保存</button>
            </div>
        </div>
    </div>

    <!-- 兑换确认弹窗 -->
    <div class="modal" id="exchange-confirm-modal">
        <div class="modal-content">
            <div class="modal-title">确认兑换</div>
            <div class="modal-body">
                <p id="exchange-reward-name">看电视30分钟</p>
                <p style="color: #667eea; font-weight: 700; font-size: 20px; margin-top: 10px;" id="exchange-reward-points">50积分</p>
            </div>
            <div class="modal-footer">
                <button class="modal-btn cancel" onclick="closeModal('exchange-confirm-modal')">取消</button>
                <button class="modal-btn confirm" onclick="confirmExchange()">确认兑换</button>
            </div>
        </div>
    </div>

    <!-- 补积分弹窗 -->
    <div class="modal" id="add-points-modal">
        <div class="modal-content">
            <div class="modal-title">补积分</div>
            <div class="modal-body">
                <div class="form-group">
                    <label class="form-label">补积分原因</label>
                    <input type="text" class="form-input" id="add-points-reason" placeholder="例如:忘记记录的作业完成">
                </div>
                <div class="form-group">
                    <label class="form-label">积分数值</label>
                    <input type="number" class="form-input" id="add-points-value" placeholder="例如:10">
                </div>
                <div class="form-group">
                    <label class="form-label">选择日期</label>
                    <input type="date" class="form-input" id="add-points-date">
                </div>
            </div>
            <div class="modal-footer">
                <button class="modal-btn cancel" onclick="closeModal('add-points-modal')">取消</button>
                <button class="modal-btn confirm" onclick="addPoints()">确认补积分</button>
            </div>
        </div>
    </div>

    <!-- 清空积分确认弹窗 -->
    <div class="modal" id="clear-points-modal">
        <div class="modal-content">
            <div class="modal-title">确认清空积分</div>
            <div class="modal-body">
                <p>确定要清空所有积分吗?此操作不可恢复!</p>
            </div>
            <div class="modal-footer">
                <button class="modal-btn cancel" onclick="closeModal('clear-points-modal')">取消</button>
                <button class="modal-btn danger" onclick="confirmClearPoints()">确认清空</button>
            </div>
        </div>
    </div>

    <!-- 删除确认弹窗 -->
    <div class="modal" id="delete-confirm-modal">
        <div class="modal-content">
            <div class="modal-title">确认删除</div>
            <div class="modal-body">
                <p>确定要删除此项目吗?</p>
            </div>
            <div class="modal-footer">
                <button class="modal-btn cancel" onclick="closeModal('delete-confirm-modal')">取消</button>
                <button class="modal-btn danger" onclick="confirmDelete()">确认删除</button>
            </div>
        </div>
    </div>

    <script>
        // 数据存储键
        const STORAGE_KEYS = {
            TOTAL_POINTS: 'pointsDriver_totalPoints',
            EARN_ITEMS: 'pointsDriver_earnItems',
            DEDUCT_ITEMS: 'pointsDriver_deductItems',
            REWARDS: 'pointsDriver_rewards',
            RECORDS: 'pointsDriver_records',
            RECORD_ID_COUNTER: 'pointsDriver_recordIdCounter'
        };

        // 默认数据
        const DEFAULT_EARN_ITEMS = [
            { id: 1, name: '完成作业', points: 10 },
            { id: 2, name: '阅读30分钟', points: 5 },
            { id: 3, name: '做家务', points: 15 },
            { id: 4, name: '锻炼身体', points: 8 },
            { id: 5, name: '早睡早起', points: 5 }
        ];

        const DEFAULT_DEDUCT_ITEMS = [
            { id: 1, name: '未完成作业', points: -10 },
            { id: 2, name: '迟到', points: -5 },
            { id: 3, name: '说脏话', points: -8 },
            { id: 4, name: '不整理房间', points: -5 }
        ];

        const DEFAULT_REWARDS = [
            { id: 1, name: '看电视30分钟', points: 50 },
            { id: 2, name: '玩游戏1小时', points: 100 },
            { id: 3, name: '买零食', points: 30 },
            { id: 4, name: '周末外出', points: 200 }
        ];

        // 全局数据
        let totalPoints = 0;
        let earnItems = [];
        let deductItems = [];
        let rewards = [];
        let records = [];
        let recordIdCounter = 0;

        // 当前操作项
        let currentEditItem = null;
        let currentDeleteItem = null;
        let currentDeleteType = '';
        let currentExchangeReward = null;
        let selectedDate = null;
        let displayYear = null;
        let displayMonth = null;

        // 初始化数据
        function initData() {
            totalPoints = parseInt(localStorage.getItem(STORAGE_KEYS.TOTAL_POINTS)) || 0;
            earnItems = JSON.parse(localStorage.getItem(STORAGE_KEYS.EARN_ITEMS)) || JSON.parse(JSON.stringify(DEFAULT_EARN_ITEMS));
            deductItems = JSON.parse(localStorage.getItem(STORAGE_KEYS.DEDUCT_ITEMS)) || JSON.parse(JSON.stringify(DEFAULT_DEDUCT_ITEMS));
            rewards = JSON.parse(localStorage.getItem(STORAGE_KEYS.REWARDS)) || JSON.parse(JSON.stringify(DEFAULT_REWARDS));
            records = JSON.parse(localStorage.getItem(STORAGE_KEYS.RECORDS)) || [];
            recordIdCounter = parseInt(localStorage.getItem(STORAGE_KEYS.RECORD_ID_COUNTER)) || 0;
        }

        // 保存数据
        function saveData() {
            localStorage.setItem(STORAGE_KEYS.TOTAL_POINTS, totalPoints);
            localStorage.setItem(STORAGE_KEYS.EARN_ITEMS, JSON.stringify(earnItems));
            localStorage.setItem(STORAGE_KEYS.DEDUCT_ITEMS, JSON.stringify(deductItems));
            localStorage.setItem(STORAGE_KEYS.REWARDS, JSON.stringify(rewards));
            localStorage.setItem(STORAGE_KEYS.RECORDS, JSON.stringify(records));
            localStorage.setItem(STORAGE_KEYS.RECORD_ID_COUNTER, recordIdCounter);
        }

        // 更新积分显示
        function updatePointsDisplay() {
            document.getElementById('total-points').textContent = totalPoints.toLocaleString();
        }

        // 页面切换
        function switchPage(pageName) {
            // 隐藏所有页面
            document.querySelectorAll('.page').forEach(page => {
                page.classList.remove('active');
            });

            // 显示目标页面
            const targetPage = document.getElementById(pageName + '-page');
            if (targetPage) {
                targetPage.classList.add('active');
            }

            // 更新底部导航
            document.querySelectorAll('.nav-item').forEach(item => {
                item.classList.remove('active');
            });

            // 根据页面名称激活对应导航
            const navMap = { 'home': 0 };

            const navItems = document.querySelectorAll('.nav-item');
            if (navMap[pageName] !== undefined) {
                navItems[navMap[pageName]].classList.add('active');
            }

            // 加载页面数据
            if (pageName === 'home') {
                loadHomeData();
            } else if (pageName === 'earn') {
                loadEarnList();
            } else if (pageName === 'deduct') {
                loadDeductList();
            } else if (pageName === 'exchange') {
                loadExchangeList();
            } else if (pageName === 'earn-manage') {
                loadEarnManageList();
            } else if (pageName === 'deduct-manage') {
                loadDeductManageList();
            } else if (pageName === 'exchange-manage') {
                loadRewardManageList();
            } else if (pageName === 'records') {
                loadRecordsData();
            }
        }

        // 更新当天积分显示
        function updateTodayPointsDisplay() {
            const today = formatDate(new Date());
            const dayRecords = records.filter(r => r.date === today);
            const earnPoints = dayRecords.filter(r => r.type === 'income').reduce((sum, r) => sum + r.amount, 0);
            const deductPoints = Math.abs(dayRecords.filter(r => r.type === 'expense').reduce((sum, r) => sum + r.amount, 0));
            const netPoints = earnPoints - deductPoints;

            document.getElementById('daily-challenge').textContent = `赚${earnPoints}分 - 扣${deductPoints}分 = ${netPoints}分`;
        }

        // 加载首页数据
        function loadHomeData() {
            updatePointsDisplay();
            updateTodayPointsDisplay();
            loadCurrentWeekGrid('current-week-grid', 'week-score-text');
        }

        // 加载赚取积分列表
        function loadEarnList() {
            const listContainer = document.getElementById('earn-list');
            let html = `
                <div class="quick-add">
                    <input class="qa-name" id="quick-earn-name" placeholder="名称(留空则用日期)">
                    <input class="qa-points" id="quick-earn-points" type="number" placeholder="积分">
                    <button class="qa-btn" onclick="quickEarn()">赚取</button>
                </div>
            `;
            if (earnItems.length === 0) {
                html += `
                    <div class="empty-state">
                        <div class="empty-icon">💰</div>
                        <div class="empty-text">暂无赚取积分项</div>
                    </div>
                `;
            } else {
                html += earnItems.map(item => `
                    <div class="list-item">
                        <div class="item-info">
                            <div class="item-name">${item.name}</div>
                            <div class="item-points income">+${item.points}积分</div>
                        </div>
                        <button class="item-btn earn" onclick="earnPoints(${item.id})">赚取</button>
                    </div>
                `).join('');
            }
            listContainer.innerHTML = html;
        }

        // 加载扣取积分列表
        function loadDeductList() {
            const listContainer = document.getElementById('deduct-list');
            let html = `
                <div class="quick-add deduct">
                    <input class="qa-name" id="quick-deduct-name" placeholder="名称(留空则用日期)">
                    <input class="qa-points" id="quick-deduct-points" type="number" placeholder="积分">
                    <button class="qa-btn" onclick="quickDeduct()">扣取</button>
                </div>
            `;
            if (deductItems.length === 0) {
                html += `
                    <div class="empty-state">
                        <div class="empty-icon">⚠️</div>
                        <div class="empty-text">暂无扣取积分项</div>
                    </div>
                `;
            } else {
                html += deductItems.map(item => `
                    <div class="list-item">
                        <div class="item-info">
                            <div class="item-name">${item.name}</div>
                            <div class="item-points expense">${item.points}积分</div>
                        </div>
                        <button class="item-btn deduct" onclick="deductPoints(${item.id})">扣取</button>
                    </div>
                `).join('');
            }
            listContainer.innerHTML = html;
        }

        // 加载兑换列表
        function loadExchangeList() {
            const listContainer = document.getElementById('exchange-list');
            let html = `
                <div class="quick-add exchange">
                    <input class="qa-name" id="quick-exchange-name" placeholder="名称(留空则用日期)">
                    <input class="qa-points" id="quick-exchange-points" type="number" placeholder="积分">
                    <button class="qa-btn" onclick="quickExchange()">兑换</button>
                </div>
            `;
            if (rewards.length === 0) {
                html += `
                    <div class="empty-state">
                        <div class="empty-icon">🎁</div>
                        <div class="empty-text">暂无兑换奖励</div>
                    </div>
                `;
            } else {
                html += rewards.map(reward => `
                    <div class="list-item">
                        <div class="item-info">
                            <div class="item-name">${reward.name}</div>
                            <div class="item-points">${reward.points}积分</div>
                        </div>
                        <button class="item-btn exchange" onclick="showExchangeModal(${reward.id})">兑换</button>
                    </div>
            `).join('');
            }
            listContainer.innerHTML = html;
        }

        // 加载赚取积分项管理列表
        function loadEarnManageList() {
            const listContainer = document.getElementById('earn-manage-list');
            if (earnItems.length === 0) {
                listContainer.innerHTML = `
                    <div class="empty-state">
                        <div class="empty-icon">💰</div>
                        <div class="empty-text">暂无赚取积分项</div>
                    </div>
                `;
                return;
            }

            listContainer.innerHTML = earnItems.map(item => `
                <div class="list-item">
                    <div class="item-info">
                        <div class="item-name">${item.name}</div>
                        <div class="item-points income">+${item.points}积分</div>
                    </div>
                    <div class="item-actions">
                        <button class="action-btn edit" onclick="editEarnItem(${item.id})">编辑</button>
                        <button class="action-btn delete" onclick="deleteEarnItem(${item.id})">删除</button>
                    </div>
                </div>
            `).join('');
        }

        // 加载扣取积分项管理列表
        function loadDeductManageList() {
            const listContainer = document.getElementById('deduct-manage-list');
            if (deductItems.length === 0) {
                listContainer.innerHTML = `
                    <div class="empty-state">
                        <div class="empty-icon">⚠️</div>
                        <div class="empty-text">暂无扣取积分项</div>
                    </div>
                `;
                return;
            }

            listContainer.innerHTML = deductItems.map(item => `
                <div class="list-item">
                    <div class="item-info">
                        <div class="item-name">${item.name}</div>
                        <div class="item-points expense">${item.points}积分</div>
                    </div>
                    <div class="item-actions">
                        <button class="action-btn edit" onclick="editDeductItem(${item.id})">编辑</button>
                        <button class="action-btn delete" onclick="deleteDeductItem(${item.id})">删除</button>
                    </div>
                </div>
            `).join('');
        }

        // 加载奖励管理列表
        function loadRewardManageList() {
            const listContainer = document.getElementById('reward-manage-list');
            if (rewards.length === 0) {
                listContainer.innerHTML = `
                    <div class="empty-state">
                        <div class="empty-icon">🎁</div>
                        <div class="empty-text">暂无兑换奖励</div>
                    </div>
                `;
                return;
            }

            listContainer.innerHTML = rewards.map(reward => `
                <div class="list-item">
                    <div class="item-info">
                        <div class="item-name">${reward.name}</div>
                        <div class="item-points">${reward.points}积分</div>
                    </div>
                    <div class="item-actions">
                        <button class="action-btn edit" onclick="editReward(${reward.id})">编辑</button>
                        <button class="action-btn delete" onclick="deleteReward(${reward.id})">删除</button>
                    </div>
                </div>
            `).join('');
        }

        // 加载积分记录数据
        function loadRecordsData() {
            // 如果没有选中日期,默认选中当天
            if (!selectedDate) {
                selectedDate = formatDate(new Date());
            }
            loadCurrentWeekGrid('records-week-grid', 'records-week-score-text');
            loadDayRecords();
            loadHistoryWeeks();
        }

        // 加载当前周积分网格
        function loadCurrentWeekGrid(gridId, titleId) {
            const grid = document.getElementById(gridId);

            const now = new Date();
            const currentDay = now.getDay();
            const weekStart = new Date(now);
            weekStart.setDate(now.getDate() - (currentDay === 0 ? 6 : currentDay - 1)); // 周一

            let weekTotal = 0;
            const dayNames = ['周一', '周二', '周三', '周四', '周五', '周六', '周日'];

            let cellsHtml = '';
            dayNames.forEach((dayName, index) => {
                const date = new Date(weekStart);
                date.setDate(weekStart.getDate() + index);
                const dateStr = formatDate(date);

                const dayRecords = records.filter(r => r.date === dateStr);
                const dayTotal = dayRecords.reduce((sum, r) => sum + r.amount, 0);
                weekTotal += dayTotal;

                const isToday = date.toDateString() === now.toDateString();
                const isSelected = selectedDate === dateStr;

                let pointsClass = '';
                if (isToday) {
                    pointsClass = 'today-points';
                } else if (isSelected) {
                    pointsClass = 'selected-points';
                }

                cellsHtml += `
                    <div class="day-item ${isToday ? 'today' : ''} ${isSelected ? 'selected' : ''}" onclick="switchToDayRecords('${dateStr}')">
                        <div class="day-name">${dayName}</div>
                        <div class="day-points ${pointsClass}">${dayTotal > 0 ? '+' : ''}${dayTotal}</div>
                    </div>
                `;
            });
            grid.innerHTML = cellsHtml;

            // 更新本周积分标题
            const scoreEl = document.getElementById(titleId);
            if (scoreEl) {
                const sign = weekTotal >= 0 ? '+' : '';
                scoreEl.textContent = `本周积分 (${sign}${weekTotal})`;
            }
        }

        // 切换到记录页面并显示当天详情
        function switchToDayRecords(dateStr) {
            selectedDate = dateStr;
            switchPage('records');
            loadDayRecords();
            // 重新加载周积分网格,以更新选中状态
            loadCurrentWeekGrid('records-week-grid', 'records-week-score-text');
        }

        // 加载每日积分记录
        function loadDayRecords() {
            const container = document.getElementById('day-records');

            if (selectedDate) {
                const dayRecords = records.filter(r => r.date === selectedDate);
                if (dayRecords.length === 0) {
                    container.innerHTML = `
                        <div class="empty-state">
                            <div class="empty-icon">📊</div>
                            <div class="empty-text">该日期暂无积分记录</div>
                        </div>
                    `;
                } else {
                    container.innerHTML = dayRecords.map(record => `
                        <div class="record-item">
                            <div class="record-info">
                                <div class="record-title">${record.title}</div>
                                <div class="record-time">${record.time}</div>
                            </div>
                            <div class="record-amount ${record.type}">${record.type === 'income' ? '+' : ''}${record.amount}</div>
                            <button class="action-btn delete" onclick="undoRecord(${record.id})" style="font-size:10px;padding:3px 8px;flex-shrink:0;">撤销</button>
                        </div>
                    `).join('');
                }
            } else {
                container.innerHTML = `
                    <div class="empty-state">
                        <div class="empty-icon">📅</div>
                        <div class="empty-text">点击上方某天查看详细记录</div>
                    </div>
                `;
            }
        }

        // 加载历史积分(月日历 + 年历)
        function loadHistoryWeeks() {
            const container = document.getElementById('history-weeks');
            const now = new Date();
            const curYear = now.getFullYear();
            const curMonth = now.getMonth();
            const weekdayNames = ['一', '二', '三', '四', '五', '六', '日'];
            const monthNames = ['1月','2月','3月','4月','5月','6月','7月','8月','9月','10月','11月','12月'];

            // 确定显示的月份
            if (displayYear === null) displayYear = curYear;
            if (displayMonth === null) displayMonth = curMonth;
            const dYear = displayYear;
            const dMonth = displayMonth;

            // 年度总积分
            const yearStart = formatDate(new Date(dYear, 0, 1));
            const yearEnd = formatDate(new Date(dYear, 11, 31));
            const yearRecords = records.filter(r => r.date >= yearStart && r.date <= yearEnd);
            const yearTotal = yearRecords.reduce((sum, r) => sum + r.amount, 0);
            const ySign = yearTotal > 0 ? '+' : '';

            // 当月月历
            const daysInMonth = new Date(dYear, dMonth + 1, 0).getDate();
            const monthStart = formatDate(new Date(dYear, dMonth, 1));
            const monthEnd = formatDate(new Date(dYear, dMonth, daysInMonth));
            const monthRecords = records.filter(r => r.date >= monthStart && r.date <= monthEnd);
            const monthTotal = monthRecords.reduce((sum, r) => sum + r.amount, 0);
            const totalSign = monthTotal > 0 ? '+' : '';
            const firstDay = new Date(dYear, dMonth, 1).getDay();
            const startPadding = firstDay === 0 ? 6 : firstDay - 1;

            let html = `<div class="month-calendar">
                <div class="month-header">
                    <div class="month-title">${dYear}年${dMonth + 1}月 (${totalSign}${monthTotal})</div>
                </div>
                <div class="month-weekdays">${weekdayNames.map(w => `<div class="month-weekday">${w}</div>`).join('')}</div>
                <div class="month-days">`;

            for (let p = 0; p < startPadding; p++) {
                html += `<div class="month-day empty"></div>`;
            }

            for (let d = 1; d <= daysInMonth; d++) {
                const dateStr = formatDate(new Date(dYear, dMonth, d));
                const dayRecords = records.filter(r => r.date === dateStr);
                const dayTotal = dayRecords.reduce((sum, r) => sum + r.amount, 0);
                const ptsStr = dayTotal !== 0 ? ((dayTotal > 0 ? '+' : '') + dayTotal) : '';
                const isToday = dateStr === formatDate(now) ? ' today' : '';
                html += `<div class="month-day${isToday}">
                    <div class="month-day-num">${d}</div>
                    <div class="month-day-pts">${ptsStr}</div>
                </div>`;
            }

            html += `</div></div>`;

            // 年历
            html += `<div class="section-title">${dYear}年总积分 (${ySign}${yearTotal})</div>`;

            // 年历 6×2 宫格
            html += `<div class="year-calendar">`;
            for (let m = 0; m < 12; m++) {
                const mStart = formatDate(new Date(dYear, m, 1));
                const mEnd = formatDate(new Date(dYear, m, new Date(dYear, m + 1, 0).getDate()));
                const mRecords = records.filter(r => r.date >= mStart && r.date <= mEnd);
                const mTotal = mRecords.reduce((sum, r) => sum + r.amount, 0);
                const mSign = mTotal > 0 ? '+' : '';
                const isCur = (dYear === curYear && m === curMonth) ? ' current' : '';
                html += `<div class="year-month-card${isCur}" onclick="switchMonthCalendar(${m})">
                    <div class="year-month-name">${monthNames[m]}</div>
                    <div class="year-month-total">${mSign}${mTotal}</div>
                </div>`;
            }
            html += `</div>`;

            container.innerHTML = html;
        }

        // 点击年历卡片切换月日历
        function switchMonthCalendar(month) {
            displayYear = displayYear !== null ? displayYear : new Date().getFullYear();
            displayMonth = month;
            loadHistoryWeeks();
        }

        // 格式化日期
        function formatDate(date) {
            const year = date.getFullYear();
            const month = String(date.getMonth() + 1).padStart(2, '0');
            const day = String(date.getDate()).padStart(2, '0');
            return `${year}-${month}-${day}`;
        }

        // 赚取积分
        // 快速赚取积分(自定义填入)
        function quickEarn() {
            const nameEl = document.getElementById('quick-earn-name');
            const pointsEl = document.getElementById('quick-earn-points');
            const name = nameEl.value.trim() || formatDate(new Date());
            const points = parseInt(pointsEl.value);
            if (!points || points <= 0) { showAlert('请输入有效积分'); return; }
            totalPoints += points;
            addRecord(name, points, 'income');
            nameEl.value = '';
            pointsEl.value = '';
            updatePointsDisplay();
            updateTodayPointsDisplay();
            saveData();
            showAlert(`赚取 +${points} 积分`);
        }

        // 快速扣取积分(自定义填入)
        function quickDeduct() {
            const nameEl = document.getElementById('quick-deduct-name');
            const pointsEl = document.getElementById('quick-deduct-points');
            const name = nameEl.value.trim() || formatDate(new Date());
            const points = parseInt(pointsEl.value);
            if (!points || points <= 0) { showAlert('请输入有效积分'); return; }
            totalPoints -= points;
            addRecord(name, -points, 'expense');
            nameEl.value = '';
            pointsEl.value = '';
            updatePointsDisplay();
            updateTodayPointsDisplay();
            saveData();
            showAlert(`扣取 -${points} 积分`);
        }

        // 快速兑换(自定义填入)
        function quickExchange() {
            const nameEl = document.getElementById('quick-exchange-name');
            const pointsEl = document.getElementById('quick-exchange-points');
            const name = nameEl.value.trim() || formatDate(new Date());
            const points = parseInt(pointsEl.value);
            if (!points || points <= 0) { showAlert('请输入有效积分'); return; }
            if (totalPoints < points) { showAlert('积分不足'); return; }
            totalPoints -= points;
            addRecord(name, -points, 'expense');
            nameEl.value = '';
            pointsEl.value = '';
            updatePointsDisplay();
            updateTodayPointsDisplay();
            saveData();
            showAlert(`兑换成功!消耗 ${points} 积分`);
        }

        function earnPoints(itemId) {
            const item = earnItems.find(i => i.id === itemId);
            if (item) {
                totalPoints += item.points;
                addRecord(item.name, item.points, 'income');
                updatePointsDisplay();
                updateTodayPointsDisplay();
                saveData();
                showAlert(`成功赚取${item.points}积分!`);
            }
        }

        // 显示自定义提示弹窗
        function showAlert(message) {
            const modal = document.createElement('div');
            modal.className = 'modal show';
            modal.innerHTML = `
                <div class="modal-content">
                    <div class="modal-title">提示</div>
                    <div class="modal-body">
                        <p>${message}</p>
                    </div>
                    <div class="modal-footer">
                        <button class="modal-btn confirm" onclick="this.closest('.modal').remove()">确定</button>
                    </div>
                </div>
            `;
            document.body.appendChild(modal);

            // 点击弹窗外部关闭
            modal.addEventListener('click', function(e) {
                if (e.target === this) {
                    this.remove();
                }
            });
        }

        // 扣取积分
        function deductPoints(itemId) {
            const item = deductItems.find(i => i.id === itemId);
            if (item) {
                totalPoints += item.points;
                addRecord(item.name, item.points, 'expense');
                updatePointsDisplay();
                updateTodayPointsDisplay();
                saveData();
                showAlert(`成功扣取${Math.abs(item.points)}积分!`);
            }
        }

        // 添加积分记录
        function addRecord(title, amount, type, date = null, timeStr = null) {
            const now = new Date();
            const recordDate = date ? new Date(date) : now;
            recordIdCounter++;
            records.unshift({
                id: recordIdCounter,
                title: title,
                amount: amount,
                type: type,
                date: formatDate(recordDate),
                time: timeStr || now.toLocaleTimeString('zh-CN', { hour: '2-digit', minute: '2-digit' })
            });
        }

        // 显示添加赚取积分项弹窗
        function showAddEarnItemModal() {
            currentEditItem = null;
            document.getElementById('earn-item-modal-title').textContent = '添加赚取积分项';
            document.getElementById('earn-item-name').value = '';
            document.getElementById('earn-item-points').value = '';
            document.getElementById('add-earn-item-modal').classList.add('show');
        }

        // 编辑赚取积分项
        function editEarnItem(itemId) {
            const item = earnItems.find(i => i.id === itemId);
            if (item) {
                currentEditItem = item;
                document.getElementById('earn-item-modal-title').textContent = '编辑赚取积分项';
                document.getElementById('earn-item-name').value = item.name;
                document.getElementById('earn-item-points').value = item.points;
                document.getElementById('add-earn-item-modal').classList.add('show');
            }
        }

        // 保存赚取积分项
        function saveEarnItem() {
            const name = document.getElementById('earn-item-name').value.trim();
            const points = parseInt(document.getElementById('earn-item-points').value);

            if (!name || isNaN(points)) {
                showAlert('请填写完整信息');
                return;
            }

            if (currentEditItem) {
                // 编辑
                currentEditItem.name = name;
                currentEditItem.points = points;
            } else {
                // 添加
                const newId = earnItems.length > 0 ? Math.max(...earnItems.map(i => i.id)) + 1 : 1;
                earnItems.push({ id: newId, name: name, points: points });
            }

            saveData();
            loadEarnManageList();
            closeModal('add-earn-item-modal');
        }

        // 删除赚取积分项
        function deleteEarnItem(itemId) {
            currentDeleteItem = itemId;
            currentDeleteType = 'earn';
            document.getElementById('delete-confirm-modal').classList.add('show');
        }

        // 显示添加扣取积分项弹窗
        function showAddDeductItemModal() {
            currentEditItem = null;
            document.getElementById('deduct-item-modal-title').textContent = '添加扣取积分项';
            document.getElementById('deduct-item-name').value = '';
            document.getElementById('deduct-item-points').value = '';
            document.getElementById('add-deduct-item-modal').classList.add('show');
        }

        // 编辑扣取积分项
        function editDeductItem(itemId) {
            const item = deductItems.find(i => i.id === itemId);
            if (item) {
                currentEditItem = item;
                document.getElementById('deduct-item-modal-title').textContent = '编辑扣取积分项';
                document.getElementById('deduct-item-name').value = item.name;
                document.getElementById('deduct-item-points').value = Math.abs(item.points);
                document.getElementById('add-deduct-item-modal').classList.add('show');
            }
        }

        // 保存扣取积分项
        function saveDeductItem() {
            const name = document.getElementById('deduct-item-name').value.trim();
            const points = parseInt(document.getElementById('deduct-item-points').value);

            if (!name || isNaN(points)) {
                showAlert('请填写完整信息');
                return;
            }

            if (currentEditItem) {
                // 编辑
                currentEditItem.name = name;
                currentEditItem.points = -points;
            } else {
                // 添加
                const newId = deductItems.length > 0 ? Math.max(...deductItems.map(i => i.id)) + 1 : 1;
                deductItems.push({ id: newId, name: name, points: -points });
            }

            saveData();
            loadDeductManageList();
            closeModal('add-deduct-item-modal');
        }

        // 删除扣取积分项
        function deleteDeductItem(itemId) {
            currentDeleteItem = itemId;
            currentDeleteType = 'deduct';
            document.getElementById('delete-confirm-modal').classList.add('show');
        }

        // 显示添加奖励弹窗
        function showAddRewardModal() {
            currentEditItem = null;
            document.getElementById('reward-modal-title').textContent = '添加兑换奖励';
            document.getElementById('reward-name').value = '';
            document.getElementById('reward-points').value = '';
            document.getElementById('add-reward-modal').classList.add('show');
        }

        // 编辑奖励
        function editReward(rewardId) {
            const reward = rewards.find(r => r.id === rewardId);
            if (reward) {
                currentEditItem = reward;
                document.getElementById('reward-modal-title').textContent = '编辑兑换奖励';
                document.getElementById('reward-name').value = reward.name;
                document.getElementById('reward-points').value = reward.points;
                document.getElementById('add-reward-modal').classList.add('show');
            }
        }

        // 保存奖励
        function saveReward() {
            const name = document.getElementById('reward-name').value.trim();
            const points = parseInt(document.getElementById('reward-points').value);

            if (!name || isNaN(points)) {
                showAlert('请填写完整信息');
                return;
            }

            if (currentEditItem) {
                // 编辑
                currentEditItem.name = name;
                currentEditItem.points = points;
            } else {
                // 添加
                const newId = rewards.length > 0 ? Math.max(...rewards.map(r => r.id)) + 1 : 1;
                rewards.push({ id: newId, name: name, points: points });
            }

            saveData();
            loadRewardManageList();
            closeModal('add-reward-modal');
        }

        // 删除奖励
        function deleteReward(rewardId) {
            currentDeleteItem = rewardId;
            currentDeleteType = 'reward';
            document.getElementById('delete-confirm-modal').classList.add('show');
        }

        // 显示兑换弹窗
        function showExchangeModal(rewardId) {
            const reward = rewards.find(r => r.id === rewardId);
            if (reward) {
                currentExchangeReward = reward;
                document.getElementById('exchange-reward-name').textContent = reward.name;
                document.getElementById('exchange-reward-points').textContent = reward.points + '积分';
                document.getElementById('exchange-confirm-modal').classList.add('show');
            }
        }

        // 确认兑换
        function confirmExchange() {
            if (currentExchangeReward && totalPoints >= currentExchangeReward.points) {
                totalPoints -= currentExchangeReward.points;
                addRecord('兑换:' + currentExchangeReward.name, -currentExchangeReward.points, 'expense');
                updatePointsDisplay();
                updateTodayPointsDisplay();
                saveData();
                closeModal('exchange-confirm-modal');
                showAlert('兑换成功!');
            } else {
                closeModal('exchange-confirm-modal');
                showAlert('积分不足!');
            }
        }

        // 显示补积分弹窗
        function showAddPointsModal() {
            // 设置默认日期为今天
            const today = new Date();
            const formattedDate = today.toISOString().split('T')[0];
            document.getElementById('add-points-date').value = formattedDate;
            document.getElementById('add-points-reason').value = '';
            document.getElementById('add-points-value').value = '';
            document.getElementById('add-points-modal').classList.add('show');
        }

        // 补积分
        function addPoints() {
            const reason = document.getElementById('add-points-reason').value.trim();
            const value = parseInt(document.getElementById('add-points-value').value);
            const dateStr = document.getElementById('add-points-date').value;

            if (!reason || isNaN(value) || !dateStr) {
                showAlert('请填写完整信息');
                return;
            }

            // 添加积分记录
            totalPoints += value;
            const recordTime = new Date(dateStr + 'T12:00:00').toLocaleTimeString('zh-CN', { hour: '2-digit', minute: '2-digit' });
            addRecord('补积分:' + reason, value, 'income', dateStr, recordTime);
            updatePointsDisplay();
            updateTodayPointsDisplay();
            saveData();

            // 关闭弹窗
            closeModal('add-points-modal');

            // 重新加载记录数据
            loadRecordsData();

            showAlert('补积分成功!');
        }

        // 显示清空积分弹窗
        function showClearPointsModal() {
            document.getElementById('clear-points-modal').classList.add('show');
        }

        // 确认清空积分
        function confirmClearPoints() {
            totalPoints = 0;
            records = [];
            recordIdCounter = 0;
            updatePointsDisplay();
            updateTodayPointsDisplay();
            saveData();
            closeModal('clear-points-modal');
            loadCurrentPageData();
            showAlert('积分已清空!');
        }

        // 系统重置
        function systemReset() {
            if (!confirm('确定要系统重置吗?\n\n将清空所有积分、记录,恢复默认设置项。\n此操作不可恢复!')) return;
            totalPoints = 0;
            records = [];
            recordIdCounter = 0;
            earnItems = JSON.parse(JSON.stringify(DEFAULT_EARN_ITEMS));
            deductItems = JSON.parse(JSON.stringify(DEFAULT_DEDUCT_ITEMS));
            rewards = JSON.parse(JSON.stringify(DEFAULT_REWARDS));
            saveData();
            updatePointsDisplay();
            updateTodayPointsDisplay();
            closeModal('clear-points-modal');
            loadCurrentPageData();
            showAlert('系统已重置为默认状态');
        }

        // 确认删除
        function confirmDelete() {
            if (currentDeleteType === 'earn') {
                earnItems = earnItems.filter(i => i.id !== currentDeleteItem);
                loadEarnManageList();
            } else if (currentDeleteType === 'deduct') {
                deductItems = deductItems.filter(i => i.id !== currentDeleteItem);
                loadDeductManageList();
            } else if (currentDeleteType === 'reward') {
                rewards = rewards.filter(r => r.id !== currentDeleteItem);
                loadRewardManageList();
            }

            saveData();
            closeModal('delete-confirm-modal');
        }

        // 撤销记录
        function undoRecord(recordId) {
            const idx = records.findIndex(r => r.id === recordId);
            if (idx !== -1) {
                totalPoints -= records[idx].amount;
                records.splice(idx, 1);
                updatePointsDisplay();
                updateTodayPointsDisplay();
                saveData();
                loadDayRecords();
                if (document.getElementById('records-page').classList.contains('active')) {
                    loadCurrentWeekGrid('records-week-grid', 'records-week-score-text');
                    loadHistoryWeeks();
                }
            }
        }

        // 关闭弹窗
        function closeModal(modalId) {
            document.getElementById(modalId).classList.remove('show');
        }

        // 重载当前活动页面数据
        function loadCurrentPageData() {
            if (document.getElementById('home-page').classList.contains('active')) {
                loadHomeData();
            } else if (document.getElementById('records-page').classList.contains('active')) {
                loadRecordsData();
            }
        }

        // 点击弹窗外部关闭
        document.querySelectorAll('.modal').forEach(modal => {
            modal.addEventListener('click', function(e) {
                if (e.target === this) {
                    this.classList.remove('show');
                }
            });
        });

        // 初始化
        document.addEventListener('DOMContentLoaded', function() {
            initData();
            loadHomeData();
        });
    </script>

</body>
</html>

免责声明:

本站提供的资源,都来自网络,版权争议与本站无关,所有内容及软件的文章仅限用于学习和研究目的。不得将上述内容用于商业或者非法用途,否则,一切后果请用户自负,我们不保证内容的长久可用性,通过使用本站内容随之而来的风险与本站无关,您必须在下载后的24个小时之内,从您的电脑/手机中彻底删除上述内容。如果您喜欢该程序,请支持正版软件,购买注册,得到更好的正版服务。侵删请致信E-mail: kuwanw@qq.com

同类推荐
评论列表
签到