dufaxing To be a better man

每日工作待办(周视图)

2025-08-29


KYHHbj.png

博客地址

前言

本工具只需要将下列todo_list.htmlmanifest.json保存在本地并放在同一目录下,然后浏览器打开todo_list.html即可

pVckrQg.jpg


todo_list.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>
    <meta name="description" content="零依赖的每日工作计划管理工具,支持拖拽排序、Excel导入导出、离线使用">
    
    <!-- PWA配置 -->
    <link rel="manifest" href="./manifest.json">
    <meta name="theme-color" content="#0078f5">
    
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }

        :root {
            --primary-color: #0078f5;
            --secondary-color: #f8f9fa;
            --border-color: #e1e5e9;
            --text-color: #333;
            --text-light: #666;
            --success-color: #28a745;
            --warning-color: #ffc107;
            --danger-color: #dc3545;
            --priority-high: #dc3545;
            --priority-medium: #ffc107;
            --priority-low: #28a745;
            --shadow: 0 2px 4px rgba(0,0,0,0.1);
            --border-radius: 8px;
        }

        [data-theme="dark"] {
            --primary-color: #4a9eff;
            --secondary-color: #1a1a1a;
            --border-color: #444;
            --text-color: #e1e5e9;
            --text-light: #aaa;
            --secondary-color-light: #2d2d2d;
            --shadow: 0 2px 4px rgba(255,255,255,0.1);
            --success-color: #4caf50;
            --warning-color: #ff9800;
            --danger-color: #f44336;
            --priority-high: #f44336;
            --priority-medium: #ff9800;
            --priority-low: #4caf50;
        }

        /* 深色主题专用样式 */
        [data-theme="dark"] .header {
            background: var(--secondary-color-light);
            color: var(--text-color);
        }

        [data-theme="dark"] .task-cell {
            background: #2a2a2a;
        }

        [data-theme="dark"] .task-cell:hover {
            background: linear-gradient(135deg, rgba(74, 158, 255, 0.15), rgba(74, 158, 255, 0.08));
        }

        [data-theme="dark"] .task-card {
            background: linear-gradient(135deg, #333, #2a2a2a);
            color: var(--text-color);
            border-color: var(--border-color);
        }

        [data-theme="dark"] .task-card:hover {
            background: linear-gradient(135deg, #3a3a3a, #333);
        }

        [data-theme="dark"] .modal-content {
            background: var(--secondary-color-light);
            color: var(--text-color);
        }

        [data-theme="dark"] .form-control {
            background: #333;
            color: var(--text-color);
            border-color: var(--border-color);
        }

        [data-theme="dark"] .form-control:focus {
            border-color: var(--primary-color);
        }

        [data-theme="dark"] .properties-panel {
            background: var(--secondary-color-light);
            color: var(--text-color);
        }

        [data-theme="dark"] .day-header {
            background: linear-gradient(135deg, #333, #2a2a2a);
            color: var(--text-color);
        }

        [data-theme="dark"] .day-header:hover {
            background: linear-gradient(135deg, #3a3a3a, #333);
        }

        [data-theme="dark"] .time-label {
            background: linear-gradient(135deg, #333, #2a2a2a);
            color: var(--text-color);
        }

        [data-theme="dark"] .time-label:hover {
            background: linear-gradient(135deg, #3a3a3a, #333);
        }

        [data-theme="dark"] .drop-zone {
            border-color: var(--border-color);
            color: var(--text-light);
        }

        [data-theme="dark"] .drop-zone.dragover {
            border-color: var(--primary-color);
            background: rgba(74, 158, 255, 0.1);
        }

        [data-theme="green"] {
            --primary-color: #28a745;
            --secondary-color: #f0f8f0;
            --border-color: #c3e6c3;
            --text-color: #2d5a2d;
            --text-light: #5a7a5a;
        }

        body {
            font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
            background-color: var(--secondary-color);
            color: var(--text-color);
            line-height: 1.6;
            overflow-x: hidden;
        }

        .container {
            max-width: 1400px;
            margin: 0 auto;
            padding: 20px;
            display: grid;
            grid-template-columns: 1fr;
            gap: 20px;
            height: 100vh;
        }

        .header {
            grid-column: 1 / -1;
            display: flex;
            justify-content: space-between;
            align-items: center;
            padding: 15px 20px;
            background: white;
            border-radius: var(--border-radius);
            box-shadow: var(--shadow);
            margin-bottom: 20px;
        }

        .header-info {
            display: flex;
            align-items: center;
            gap: 20px;
        }

        .date-display {
            font-size: 1.2em;
            font-weight: bold;
            color: var(--primary-color);
        }

        .week-info {
            color: var(--text-light);
        }

        .controls {
            display: flex;
            gap: 10px;
            align-items: center;
        }

        .btn {
            padding: 8px 16px;
            border: none;
            border-radius: var(--border-radius);
            cursor: pointer;
            font-size: 14px;
            transition: all 0.3s ease;
            display: flex;
            align-items: center;
            gap: 5px;
        }

        .btn-primary {
            background: var(--primary-color);
            color: white;
        }

        .btn-secondary {
            background: var(--secondary-color);
            color: var(--text-color);
            border: 1px solid var(--border-color);
        }

        .btn:hover {
            transform: translateY(-1px);
            box-shadow: var(--shadow);
        }

        @keyframes slideIn {
            from {
                transform: translateX(100%);
                opacity: 0;
            }
            to {
                transform: translateX(0);
                opacity: 1;
            }
        }

        @keyframes slideOut {
            from {
                transform: translateX(0);
                opacity: 1;
            }
            to {
                transform: translateX(100%);
                opacity: 0;
            }
        }

        @keyframes fadeIn {
            from { opacity: 0; transform: scale(0.95); }
            to { opacity: 1; transform: scale(1); }
        }

        @keyframes pulse {
            0% { transform: scale(1); }
            50% { transform: scale(1.05); }
            100% { transform: scale(1); }
        }



        .main-content {
            background: white;
            border-radius: var(--border-radius);
            box-shadow: var(--shadow);
            overflow: hidden;
        }

        .weekly-grid {
            display: grid;
            grid-template-columns: 120px repeat(7, 1fr);
            height: calc(100vh - 200px);
            min-height: 600px;
            border: 2px solid var(--border-color);
            border-radius: var(--border-radius);
            overflow: hidden;
            box-shadow: var(--shadow);
        }

        .time-slot-header {
            background: linear-gradient(135deg, var(--primary-color), #0056b3);
            color: white;
            padding: 15px 8px;
            text-align: center;
            font-weight: 600;
            border-bottom: 2px solid var(--border-color);
            border-right: 2px solid var(--border-color);
            font-size: 14px;
            letter-spacing: 0.5px;
            text-shadow: 0 1px 2px rgba(0,0,0,0.1);
            display: flex;
            align-items: center;
            justify-content: center;
        }

        .day-header {
            background: linear-gradient(135deg, #f8f9fa, #e9ecef);
            padding: 15px 8px;
            text-align: center;
            font-weight: 600;
            border-bottom: 2px solid var(--border-color);
            border-right: 2px solid var(--border-color);
            font-size: 14px;
            color: var(--text-color);
            letter-spacing: 0.5px;
            transition: all 0.3s ease;
            display: flex;
            align-items: center;
            justify-content: center;
        }

        .day-header:hover {
            background: linear-gradient(135deg, #e9ecef, #dee2e6);
            transform: translateY(-1px);
        }

        .day-header.today {
            background: linear-gradient(135deg, var(--primary-color), #0056b3);
            color: white;
            box-shadow: inset 0 2px 4px rgba(0,0,0,0.1);
            text-shadow: 0 1px 2px rgba(0,0,0,0.2);
        }

        .time-label {
            background: linear-gradient(135deg, #f1f3f4, #e8eaed);
            padding: 20px 15px;
            text-align: center;
            font-weight: 600;
            border-right: 2px solid var(--border-color);
            border-bottom: 2px solid var(--border-color);
            writing-mode: vertical-lr;
            display: flex;
            align-items: center;
            justify-content: center;
            font-size: 16px;
            color: var(--text-color);
            letter-spacing: 1px;
            min-height: 140px;
            transition: all 0.3s ease;
        }

        .time-label:hover {
            background: linear-gradient(135deg, #e8eaed, #dadce0);
            transform: translateX(-2px);
        }

        .task-cell {
            border-right: 2px solid var(--border-color);
            border-bottom: 2px solid var(--border-color);
            padding: 12px;
            min-height: 140px;
            position: relative;
            overflow-y: auto;
            background: #fafbfc;
            transition: all 0.3s ease;
        }

        .task-cell:hover {
            background: linear-gradient(135deg, rgba(0, 120, 245, 0.08), rgba(0, 120, 245, 0.04));
            box-shadow: inset 0 0 10px rgba(0, 120, 245, 0.1);
            transform: scale(1.02);
        }

        .task-card {
            background: linear-gradient(135deg, #ffffff, #f8f9fa);
            border: 1px solid var(--border-color);
            border-radius: 10px;
            padding: 12px;
            margin-bottom: 8px;
            cursor: move;
            transition: all 0.3s ease;
            position: relative;
            font-size: 13px;
            box-shadow: 0 2px 8px rgba(0,0,0,0.08);
        }

        .task-card:hover {
            box-shadow: 0 4px 16px rgba(0,0,0,0.15);
            transform: translateY(-2px) scale(1.02);
            background: linear-gradient(135deg, #ffffff, #f0f2f5);
        }

        .task-card.dragging {
            opacity: 0.5;
            transform: rotate(5deg);
        }

        .task-card.done {
            opacity: 0.6;
            text-decoration: line-through;
        }

        .task-card.high-priority {
            border-left: 3px solid var(--priority-high);
        }

        .task-card.medium-priority {
            border-left: 3px solid var(--priority-medium);
        }

        .task-card.low-priority {
            border-left: 3px solid var(--priority-low);
        }

        .task-checkbox {
            margin-right: 5px;
            cursor: pointer;
        }

        .task-title {
            font-weight: bold;
            margin-bottom: 2px;
            word-break: break-word;
        }

        .task-time {
            font-size: 11px;
            color: var(--text-light);
            margin-bottom: 2px;
        }

        .task-note {
            font-size: 11px;
            color: var(--text-light);
            word-break: break-word;
        }

        .task-actions {
            position: absolute;
            top: 2px;
            right: 2px;
            opacity: 0;
            transition: opacity 0.3s;
        }

        .task-card:hover .task-actions {
            opacity: 1;
        }

        .delete-btn {
            background: linear-gradient(135deg, var(--danger-color), #c82333);
            color: white;
            border: none;
            border-radius: 50%;
            width: 22px;
            height: 22px;
            font-size: 12px;
            cursor: pointer;
            display: flex;
            align-items: center;
            justify-content: center;
            box-shadow: 0 2px 6px rgba(220, 53, 69, 0.3);
            transition: all 0.3s ease;
        }

        .delete-btn:hover {
            transform: scale(1.1);
            box-shadow: 0 4px 12px rgba(220, 53, 69, 0.4);
        }

        .add-task-btn {
            position: absolute;
            bottom: 8px;
            right: 8px;
            background: linear-gradient(135deg, var(--primary-color), #0056b3);
            color: white;
            border: none;
            border-radius: 50%;
            width: 28px;
            height: 28px;
            font-size: 16px;
            cursor: pointer;
            opacity: 0.7;
            transition: all 0.3s ease;
            box-shadow: 0 2px 8px rgba(0, 120, 245, 0.3);
        }

        .task-cell:hover .add-task-btn {
            opacity: 1;
            transform: scale(1.1);
            box-shadow: 0 4px 12px rgba(0, 120, 245, 0.4);
        }

        .properties-panel {
            background: white;
            border-radius: var(--border-radius);
            box-shadow: var(--shadow);
            padding: 20px;
            height: fit-content;
            position: sticky;
            top: 20px;
        }

        .properties-panel h3 {
            margin-bottom: 15px;
            color: var(--primary-color);
        }

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

        .form-group label {
            display: block;
            margin-bottom: 5px;
            font-weight: bold;
            font-size: 14px;
        }

        .form-control {
            width: 100%;
            padding: 8px;
            border: 1px solid var(--border-color);
            border-radius: var(--border-radius);
            font-size: 14px;
            font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
            line-height: 1.5;
        }

        /* 统一时间输入框和备注文本框的字体样式 */
        input[type="time"].form-control,
        textarea.form-control {
            font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
            font-size: 14px;
            line-height: 1.5;
            color: var(--text-color);
        }

        /* 确保备注文本框的字体一致性 */
        #taskNote {
            font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
            font-size: 14px;
            line-height: 1.5;
            resize: vertical;
        }

        .form-control:focus {
            outline: none;
            border-color: var(--primary-color);
        }

        .priority-selector {
            display: flex;
            gap: 5px;
        }

        .priority-btn {
            flex: 1;
            padding: 5px;
            border: 1px solid var(--border-color);
            background: white;
            cursor: pointer;
            font-size: 12px;
            border-radius: var(--border-radius);
        }

        .priority-btn.active {
            background: var(--primary-color);
            color: white;
        }

        .repeat-selector {
            display: flex;
            gap: 5px;
        }

        .repeat-btn {
            flex: 1;
            padding: 5px;
            border: 1px solid var(--border-color);
            background: white;
            cursor: pointer;
            font-size: 12px;
            border-radius: var(--border-radius);
        }

        .repeat-btn.active {
            background: var(--primary-color);
            color: white;
        }

        .weekday-selector {
            display: flex;
            gap: 5px;
            flex-wrap: wrap;
        }

        .weekday-btn {
            flex: 1;
            min-width: 50px;
            padding: 5px;
            border: 1px solid var(--border-color);
            background: white;
            cursor: pointer;
            font-size: 12px;
            border-radius: var(--border-radius);
        }

        .weekday-btn.active {
            background: var(--primary-color);
            color: white;
        }

        .modal {
            display: none;
            position: fixed;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background: rgba(0,0,0,0.5);
            z-index: 1000;
        }

        .modal-content {
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            background: white;
            padding: 30px;
            border-radius: var(--border-radius);
            max-width: 500px;
            width: 90%;
            max-height: 80vh;
            overflow-y: auto;
        }

        .modal-header {
            display: flex;
            justify-content: space-between;
            align-items: center;
            margin-bottom: 20px;
        }

        .close-btn {
            background: none;
            border: none;
            font-size: 24px;
            cursor: pointer;
            color: var(--text-light);
        }

        .theme-selector {
            display: flex;
            gap: 10px;
            margin-bottom: 15px;
        }

        .theme-btn {
            width: 30px;
            height: 30px;
            border-radius: 50%;
            border: 2px solid var(--border-color);
            cursor: pointer;
        }

        .theme-btn.active {
            border-color: var(--primary-color);
        }

        .drop-zone {
            border: 2px dashed var(--border-color);
            border-radius: var(--border-radius);
            padding: 20px;
            text-align: center;
            color: var(--text-light);
            margin-bottom: 15px;
        }

        .drop-zone.dragover {
            border-color: var(--primary-color);
            background: rgba(0, 120, 245, 0.1);
        }

        @media (max-width: 768px) {
            .container {
                grid-template-columns: 1fr;
                padding: 10px;
            }



            .weekly-grid {
                grid-template-columns: 80px repeat(7, 1fr);
                font-size: 12px;
                min-height: 500px;
            }

            .time-label {
                padding: 15px 8px;
                font-size: 14px;
                min-height: 120px;
            }

            .task-cell {
                padding: 8px;
                min-height: 120px;
            }

            .day-header, .time-slot-header {
                padding: 12px 6px;
                font-size: 12px;
            }

            .task-card {
                padding: 8px;
                font-size: 12px;
                margin-bottom: 6px;
            }

            .add-task-btn {
                width: 24px;
                height: 24px;
                font-size: 14px;
                bottom: 6px;
                right: 6px;
            }

            .header {
                flex-direction: column;
                gap: 10px;
                align-items: stretch;
            }

            .controls {
                justify-content: center;
                flex-wrap: wrap;
            }


        }

        .toast {
            position: fixed;
            top: 20px;
            right: 20px;
            padding: 12px 20px;
            border-radius: 4px;
            color: white;
            font-weight: 500;
            z-index: 10000;
            opacity: 0;
            transform: translateX(100%);
            transition: all 0.3s ease;
        }

        .toast.show {
            opacity: 1;
            transform: translateX(0);
        }

        .loading {
            display: inline-block;
            width: 20px;
            height: 20px;
            border: 3px solid #f3f3f3;
            border-top: 3px solid var(--primary-color);
            border-radius: 50%;
            animation: spin 1s linear infinite;
        }

        @keyframes spin {
            0% { transform: rotate(0deg); }
            100% { transform: rotate(360deg); }
        }

        .hidden {
            display: none !important;
        }
    </style>
</head>
<body>
    <div class="container">
        <header class="header">
            <div class="header-info">
                <div class="date-display" id="currentDate"></div>
                <div class="week-info" id="weekInfo"></div>
            </div>
            <div class="controls">
                <button class="btn btn-primary" onclick="addTaskToPool()">+ 添加任务</button>
                <button class="btn btn-secondary" onclick="clearWeek()">清空本周</button>
                <button class="btn btn-primary" onclick="exportToExcel()">📊 CSV导出</button>
                <button class="btn btn-secondary" onclick="showImportModal()">📥 CSV导入</button>
                <button class="btn btn-outline" onclick="showSettingsModal()">⚙️ 设置</button>
            </div>
        </header>



        <main class="main-content">
            <div class="weekly-grid" id="weeklyGrid">
                <div class="time-slot-header">时间</div>
                <div class="day-header" data-day="1">周一</div>
                <div class="day-header" data-day="2">周二</div>
                <div class="day-header" data-day="3">周三</div>
                <div class="day-header" data-day="4">周四</div>
                <div class="day-header" data-day="5">周五</div>
                <div class="day-header" data-day="6">周六</div>
                <div class="day-header" data-day="7">周日</div>

                <div class="time-label">上午<br>08:00-12:00</div>
                <div class="task-cell" data-day="1" data-slot="AM" onclick="addTask(1, 'AM')" ondrop="drop(event, 'grid')" ondragover="allowDrop(event)"></div>
                <div class="task-cell" data-day="2" data-slot="AM" onclick="addTask(2, 'AM')" ondrop="drop(event, 'grid')" ondragover="allowDrop(event)"></div>
                <div class="task-cell" data-day="3" data-slot="AM" onclick="addTask(3, 'AM')" ondrop="drop(event, 'grid')" ondragover="allowDrop(event)"></div>
                <div class="task-cell" data-day="4" data-slot="AM" onclick="addTask(4, 'AM')" ondrop="drop(event, 'grid')" ondragover="allowDrop(event)"></div>
                <div class="task-cell" data-day="5" data-slot="AM" onclick="addTask(5, 'AM')" ondrop="drop(event, 'grid')" ondragover="allowDrop(event)"></div>
                <div class="task-cell" data-day="6" data-slot="AM" onclick="addTask(6, 'AM')" ondrop="drop(event, 'grid')" ondragover="allowDrop(event)"></div>
                <div class="task-cell" data-day="7" data-slot="AM" onclick="addTask(7, 'AM')" ondrop="drop(event, 'grid')" ondragover="allowDrop(event)"></div>

                <div class="time-label">下午<br>13:00-18:00</div>
                <div class="task-cell" data-day="1" data-slot="PM" onclick="addTask(1, 'PM')" ondrop="drop(event, 'grid')" ondragover="allowDrop(event)"></div>
                <div class="task-cell" data-day="2" data-slot="PM" onclick="addTask(2, 'PM')" ondrop="drop(event, 'grid')" ondragover="allowDrop(event)"></div>
                <div class="task-cell" data-day="3" data-slot="PM" onclick="addTask(3, 'PM')" ondrop="drop(event, 'grid')" ondragover="allowDrop(event)"></div>
                <div class="task-cell" data-day="4" data-slot="PM" onclick="addTask(4, 'PM')" ondrop="drop(event, 'grid')" ondragover="allowDrop(event)"></div>
                <div class="task-cell" data-day="5" data-slot="PM" onclick="addTask(5, 'PM')" ondrop="drop(event, 'grid')" ondragover="allowDrop(event)"></div>
                <div class="task-cell" data-day="6" data-slot="PM" onclick="addTask(6, 'PM')" ondrop="drop(event, 'grid')" ondragover="allowDrop(event)"></div>
                <div class="task-cell" data-day="7" data-slot="PM" onclick="addTask(7, 'PM')" ondrop="drop(event, 'grid')" ondragover="allowDrop(event)"></div>

                <div class="time-label">晚上<br>19:00-23:00</div>
                <div class="task-cell" data-day="1" data-slot="EVENING" onclick="addTask(1, 'EVENING')" ondrop="drop(event, 'grid')" ondragover="allowDrop(event)"></div>
                <div class="task-cell" data-day="2" data-slot="EVENING" onclick="addTask(2, 'EVENING')" ondrop="drop(event, 'grid')" ondragover="allowDrop(event)"></div>
                <div class="task-cell" data-day="3" data-slot="EVENING" onclick="addTask(3, 'EVENING')" ondrop="drop(event, 'grid')" ondragover="allowDrop(event)"></div>
                <div class="task-cell" data-day="4" data-slot="EVENING" onclick="addTask(4, 'EVENING')" ondrop="drop(event, 'grid')" ondragover="allowDrop(event)"></div>
                <div class="task-cell" data-day="5" data-slot="EVENING" onclick="addTask(5, 'EVENING')" ondrop="drop(event, 'grid')" ondragover="allowDrop(event)"></div>
                <div class="task-cell" data-day="6" data-slot="EVENING" onclick="addTask(6, 'EVENING')" ondrop="drop(event, 'grid')" ondragover="allowDrop(event)"></div>
                <div class="task-cell" data-day="7" data-slot="EVENING" onclick="addTask(7, 'EVENING')" ondrop="drop(event, 'grid')" ondragover="allowDrop(event)"></div>
            </div>
        </main>

        <!-- 删除右侧面板 -->
        <!-- <aside class="properties-panel">
            <h3>任务详情</h3>
            <div id="taskProperties">
                <p style="color: var(--text-light); text-align: center;">选择任务查看详情</p>
            </div>
        </aside> -->
    </div>

    <!-- 任务编辑模态框 -->
    <div class="modal" id="taskModal">
        <div class="modal-content">
            <div class="modal-header">
                <h3 id="modalTitle">添加任务</h3>
                <button class="close-btn" onclick="closeModal()">&times;</button>
            </div>
            <form id="taskForm" onsubmit="saveTask(event)">
                <div class="form-group">
                    <label>任务标题</label>
                    <input type="text" class="form-control" id="taskTitle" required>
                </div>
                <div class="form-group">
                    <label>开始时间</label>
                    <input type="time" class="form-control" id="taskStart" required>
                </div>
                <div class="form-group">
                    <label>结束时间</label>
                    <input type="time" class="form-control" id="taskEnd" required>
                </div>

                <div class="form-group">
                    <label>优先级</label>
                    <div class="priority-selector">
                        <button type="button" class="priority-btn" data-priority="3" onclick="selectPriority(3)"></button>
                        <button type="button" class="priority-btn" data-priority="2" onclick="selectPriority(2)"></button>
                        <button type="button" class="priority-btn" data-priority="1" onclick="selectPriority(1)"></button>
                    </div>
                </div>
                <div class="form-group">
                    <label>星期选择</label>
                    <div class="weekday-selector">
                        <button type="button" class="weekday-btn" data-day="1" onclick="toggleWeekday(1)">周一</button>
                        <button type="button" class="weekday-btn" data-day="2" onclick="toggleWeekday(2)">周二</button>
                        <button type="button" class="weekday-btn" data-day="3" onclick="toggleWeekday(3)">周三</button>
                        <button type="button" class="weekday-btn" data-day="4" onclick="toggleWeekday(4)">周四</button>
                        <button type="button" class="weekday-btn" data-day="5" onclick="toggleWeekday(5)">周五</button>
                        <button type="button" class="weekday-btn" data-day="6" onclick="toggleWeekday(6)">周六</button>
                        <button type="button" class="weekday-btn" data-day="7" onclick="toggleWeekday(7)">周日</button>
                        <button type="button" class="weekday-btn" data-day="all" onclick="toggleAllWeekdays()" style="background: #ff6b6b; color: white;">每天</button>
                    </div>
                </div>
                <div class="form-group">
                    <label>备注</label>
                    <textarea class="form-control" id="taskNote" rows="3"></textarea>
                </div>
                <div style="display: flex; gap: 10px; justify-content: flex-end;">
                    <button type="button" class="btn btn-secondary" onclick="closeModal()">取消</button>
                    <button type="submit" class="btn btn-primary">保存</button>
                </div>
            </form>
        </div>
    </div>

    <!-- 导入模态框 -->
    <div class="modal" id="importModal">
        <div class="modal-content" style="max-width: 600px; width: 90%;">
            <div class="modal-header">
                <h3 style="margin: 0; color: var(--primary-color);">
                    <span style="margin-right: 8px;">📥</span>CSV任务导入
                </h3>
                <button class="close-btn" onclick="closeImportModal()" style="font-size: 24px; color: var(--text-light);">&times;</button>
            </div>
            
            <div class="modal-body" style="padding: 30px;">
                <!-- 文件上传区域 -->
                <div class="import-upload-area" style="
                    border: 2px dashed var(--border-color);
                    border-radius: 12px;
                    padding: 40px 20px;
                    text-align: center;
                    transition: all 0.3s ease;
                    margin-bottom: 25px;
                    background: linear-gradient(135deg, #f8f9ff 0%, #f0f4ff 100%);
                    display: flex;
                    flex-direction: column;
                    align-items: center;
                    justify-content: center;
                " onmouseover="this.style.borderColor='var(--primary-color)'; this.style.background='linear-gradient(135deg, #f0f4ff 0%, #e8f0ff 100%)';" 
                   onmouseout="this.style.borderColor='var(--border-color)'; this.style.background='linear-gradient(135deg, #f8f9ff 0%, #f0f4ff 100%)';">
                    
                    <div style="font-size: 48px; margin-bottom: 15px; color: var(--primary-color);">📁</div>
                    <h4 style="margin: 0 0 10px 0; color: var(--text-color);">拖拽文件到此处或点击选择</h4>
                    <p style="margin: 0 0 15px 0; color: var(--text-light); font-size: 14px;">
                        支持CSV格式文件,文件大小不超过5MB
                    </p>
                    <input type="file" id="fileInput" accept=".csv" onchange="handleFileSelect(event)" style="
                        display: none;
                    ">
                    <div style="text-align: center;">
                        <button type="button" onclick="event.stopPropagation(); document.getElementById('fileInput').click()" class="btn btn-primary" style="
                            background: linear-gradient(135deg, var(--primary-color), #0056b3);
                            border: none;
                            padding: 14px 32px;
                            border-radius: 8px;
                            font-size: 16px;
                            font-weight: 500;
                            color: white;
                            cursor: pointer;
                            transition: all 0.3s ease;
                            box-shadow: 0 2px 8px rgba(0, 123, 255, 0.2);
                            margin: 10px auto;
                            display: inline-block;
                        " onmouseover="this.style.transform='translateY(-1px)'; this.style.boxShadow='0 4px 12px rgba(0, 123, 255, 0.3)'" onmouseout="this.style.transform='translateY(0)'; this.style.boxShadow='0 2px 8px rgba(0, 123, 255, 0.2)'">
                            📁 选择CSV文件
                        </button>
                    </div>
                </div>

                <!-- 文件信息 -->
                <div id="fileInfo" style="display: none; margin-bottom: 20px; padding: 15px; background: #f8f9ff; border-radius: 8px;">
                    <div style="display: flex; align-items: center; justify-content: space-between;">
                        <div>
                            <strong id="fileName" style="color: var(--text-color);"></strong>
                            <span id="fileSize" style="color: var(--text-light); margin-left: 10px; font-size: 12px;"></span>
                        </div>
                        <button onclick="clearFile()" style="background: none; border: none; color: var(--text-light); cursor: pointer; font-size: 18px;">×</button>
                    </div>
                </div>

                <!-- 预览区域 -->
                <div id="importPreview" style="display: none;">
                    <div style="display: flex; align-items: center; margin-bottom: 15px; padding: 15px; background: linear-gradient(135deg, #e8f5e8, #f0f8f0); border-radius: 8px;">
                        <div style="font-size: 24px; margin-right: 12px;"></div>
                        <div>
                            <h4 style="margin: 0 0 5px 0; color: var(--text-color);">
                                找到 <span id="taskCount" style="color: var(--primary-color); font-weight: bold;">0</span> 个有效任务
                            </h4>
                            <p style="margin: 0; color: var(--text-light); font-size: 14px;">请确认导入内容是否正确</p>
                        </div>
                    </div>
                    
                    <div style="max-height: 300px; overflow-y: auto; border: 1px solid var(--border-color); border-radius: 8px; background: white;">
                        <div id="previewList" style="padding: 0;"></div>
                    </div>
                </div>

                <!-- 导入说明 -->
                <div style="margin-top: 20px; padding: 15px; background: #fff8e1; border-left: 4px solid #ffa726; border-radius: 4px;">
                    <h5 style="margin: 0 0 10px 0; color: #e65100;">📋 CSV文件格式说明</h5>
                    <p style="margin: 0 0 8px 0; font-size: 14px; color: #666;">
                        请确保CSV文件包含以下列:<strong>星期,时段,标题,开始时间,结束时间,优先级,备注</strong>
                    </p>
                    <p style="margin: 0 0 8px 0; font-size: 13px; color: #888;">
                        例如:周一,上午,团队会议,09:00,10:00,高,讨论项目进度
                    </p>
                    <div style="margin-top: 10px;">
                        <a href="weekly_template.csv" download="每周任务模板.csv" style="
                            display: inline-block;
                            padding: 8px 16px;
                            background: var(--primary-color);
                            color: white;
                            text-decoration: none;
                            border-radius: 6px;
                            font-size: 13px;
                            transition: all 0.3s ease;
                        " onmouseover="this.style.background='#0056b3'" onmouseout="this.style.background='var(--primary-color)'">
                            📥 下载CSV模板文件
                        </a>
                    </div>
                </div>
            </div>
            
            <div class="modal-footer" style="padding: 20px 30px; border-top: 1px solid var(--border-color); display: flex; justify-content: flex-end; gap: 12px;">
                <button class="btn btn-secondary" onclick="closeImportModal()" style="padding: 10px 20px; border-radius: 6px;">取消</button>
                <button class="btn btn-primary" onclick="confirmImport()" id="confirmImportBtn" disabled style="padding: 10px 20px; border-radius: 6px; background: linear-gradient(135deg, var(--primary-color), #0056b3);">
                    确认导入
                </button>
            </div>
        </div>
            </div>
        </div>
    </div>

    <!-- 设置模态框 -->
    <div class="modal" id="settingsModal">
        <div class="modal-content">
            <div class="modal-header">
                <h3>设置</h3>
                <button class="close-btn" onclick="closeSettingsModal()">&times;</button>
            </div>
            <div class="form-group">
                <label>主题</label>
                <div class="theme-selector">
                    <button type="button" class="theme-btn" style="background: white; border: 1px solid #ddd;" onclick="setTheme('light')" title="浅色"></button>
                    <button type="button" class="theme-btn" style="background: #1a1a1a;" onclick="setTheme('dark')" title="深色"></button>
                    <button type="button" class="theme-btn" style="background: #f0f8f0;" onclick="setTheme('green')" title="护眼绿"></button>
                </div>
            </div>
            <div class="form-group">
                <label>时段设置</label>
                <div style="margin-bottom: 10px;">
                    <label style="font-size: 14px; margin-bottom: 5px; display: block;">上午时段</label>
                    <div style="display: flex; align-items: center; gap: 10px;">
                        <select class="form-control" id="morningStart" style="width: 100px;">
                            <option value="06:00">06:00</option>
                            <option value="06:30">06:30</option>
                            <option value="07:00">07:00</option>
                            <option value="07:30">07:30</option>
                            <option value="08:00" selected>08:00</option>
                            <option value="08:30">08:30</option>
                            <option value="09:00">09:00</option>
                            <option value="09:30">09:30</option>
                            <option value="10:00">10:00</option>
                            <option value="10:30">10:30</option>
                        </select>
                        <span></span>
                        <select class="form-control" id="morningEnd" style="width: 100px;">
                            <option value="10:00">10:00</option>
                            <option value="10:30">10:30</option>
                            <option value="11:00">11:00</option>
                            <option value="11:30">11:30</option>
                            <option value="12:00" selected>12:00</option>
                            <option value="12:30">12:30</option>
                            <option value="13:00">13:00</option>
                            <option value="13:30">13:30</option>
                            <option value="14:00">14:00</option>
                            <option value="14:30">14:30</option>
                        </select>
                    </div>
                </div>
                <div style="margin-bottom: 10px;">
                    <label style="font-size: 14px; margin-bottom: 5px; display: block;">下午时段</label>
                    <div style="display: flex; align-items: center; gap: 10px;">
                        <select class="form-control" id="afternoonStart" style="width: 100px;">
                            <option value="12:00">12:00</option>
                            <option value="12:30">12:30</option>
                            <option value="13:00" selected>13:00</option>
                            <option value="13:30">13:30</option>
                            <option value="14:00">14:00</option>
                            <option value="14:30">14:30</option>
                            <option value="15:00">15:00</option>
                            <option value="15:30">15:30</option>
                        </select>
                        <span></span>
                        <select class="form-control" id="afternoonEnd" style="width: 100px;">
                            <option value="16:00">16:00</option>
                            <option value="16:30">16:30</option>
                            <option value="17:00">17:00</option>
                            <option value="17:30">17:30</option>
                            <option value="18:00" selected>18:00</option>
                            <option value="18:30">18:30</option>
                            <option value="19:00">19:00</option>
                            <option value="19:30">19:30</option>
                            <option value="20:00">20:00</option>
                            <option value="20:30">20:30</option>
                        </select>
                    </div>
                </div>
                <div style="margin-bottom: 10px;">
                    <label style="font-size: 14px; margin-bottom: 5px; display: block;">晚上时段</label>
                    <div style="display: flex; align-items: center; gap: 10px;">
                        <select class="form-control" id="eveningStart" style="width: 100px;">
                            <option value="18:00">18:00</option>
                            <option value="18:30">18:30</option>
                            <option value="19:00" selected>19:00</option>
                            <option value="19:30">19:30</option>
                            <option value="20:00">20:00</option>
                            <option value="20:30">20:30</option>
                            <option value="21:00">21:00</option>
                            <option value="21:30">21:30</option>
                        </select>
                        <span></span>
                        <select class="form-control" id="eveningEnd" style="width: 100px;">
                            <option value="21:00">21:00</option>
                            <option value="21:30">21:30</option>
                            <option value="22:00">22:00</option>
                            <option value="22:30">22:30</option>
                            <option value="23:00" selected>23:00</option>
                            <option value="23:30">23:30</option>
                            <option value="24:00">24:00</option>
                        </select>
                    </div>
                </div>
            </div>
            <div style="display: flex; gap: 10px; justify-content: flex-end;">
                <button class="btn btn-primary" onclick="saveSettings()">保存设置</button>
            </div>
        </div>
    </div>

    <!-- 提示消息 -->
    <div class="toast" id="toast"></div>



    <script>
        // 全局变量
        let tasks = [];
        let currentEditingTask = null;
        let draggedTask = null;
        let importedData = null;

        // 工具函数
        function generateId() {
            return Math.random().toString(36).substr(2, 9);
        }

        function showToast(message, type = 'success') {
            const toast = document.getElementById('toast');
            toast.textContent = message;
            toast.style.background = type === 'error' ? 'var(--danger-color)' : 'var(--success-color)';
            toast.classList.add('show');
            setTimeout(() => toast.classList.remove('show'), 3000);
        }

        function saveToLocalStorage(taskData = null) {
            const dataToSave = taskData || tasks;
            localStorage.setItem('weeklyTasks', JSON.stringify(dataToSave));
            if (taskData === null) {
                showToast('已自动保存到本地');
            }
        }

        function loadFromLocalStorage() {
            const saved = localStorage.getItem('weeklyTasks');
            if (saved) {
                try {
                    const parsed = JSON.parse(saved);
                    tasks = Array.isArray(parsed) ? parsed : [];
                    return tasks;
                } catch (error) {
                    console.error('解析本地存储数据失败:', error);
                    tasks = [];
                    return [];
                }
            }
            tasks = [];
            return [];
        }

        function updateDateDisplay() {
            const now = new Date();
            const options = { year: 'numeric', month: 'long', day: 'numeric', weekday: 'long' };
            document.getElementById('currentDate').textContent = now.toLocaleDateString('zh-CN', options);
            
            const startOfWeek = new Date(now);
            startOfWeek.setDate(now.getDate() - now.getDay() + 1);
            const endOfWeek = new Date(startOfWeek);
            endOfWeek.setDate(startOfWeek.getDate() + 6);
            
            const weekNumber = Math.ceil((now - new Date(now.getFullYear(), 0, 1)) / 604800000);
            document.getElementById('weekInfo').textContent = `第${weekNumber}${startOfWeek.getMonth()+1}/${startOfWeek.getDate()}-${endOfWeek.getMonth()+1}/${endOfWeek.getDate()}`;
            
            // 高亮今天(排除周日)
            const today = now.getDay() || 7;
            document.querySelectorAll('.day-header').forEach(header => {
                header.classList.remove('today');
                if (parseInt(header.dataset.day) === today && today !== 7) {
                    header.classList.add('today');
                }
            });
        }

        function renderTasks() {
            // 清空所有任务显示
            document.querySelectorAll('.task-card').forEach(card => card.remove());
            document.querySelectorAll('#taskPool .task-card').forEach(card => card.remove());

            tasks.forEach(task => {
                const taskElement = createTaskElement(task);
                
                if (task.slot === 'POOL') {
                    document.getElementById('taskPool').appendChild(taskElement);
                } else {
                    const cell = document.querySelector(`[data-day="${task.weekday}"][data-slot="${task.slot}"]`);
                    if (cell) {
                        cell.appendChild(taskElement);
                    }
                }
            });
        }

        function createTaskElement(task) {
            const div = document.createElement('div');
            div.className = `task-card ${task.done ? 'done' : ''} ${getPriorityClass(task.priority)}`;
            div.draggable = true;
            div.dataset.taskId = task.id;
            
            div.innerHTML = `
                <div style="display: flex; align-items: flex-start; gap: 5px;">
                    <input type="checkbox" class="task-checkbox" ${task.done ? 'checked' : ''} 
                           onchange="toggleTask('${task.id}')">
                    <div style="flex: 1;">
                        <div class="task-title">${task.title}</div>
                        ${task.start && task.end ? `<div class="task-time">${task.start}-${task.end}</div>` : ''}
                        ${task.note ? `<div class="task-note">${task.note}</div>` : ''}
                    </div>
                </div>
                <div class="task-actions">
                    <button class="delete-btn" onclick="deleteTask('${task.id}')">×</button>
                </div>
            `;

            div.addEventListener('dragstart', (e) => {
                draggedTask = task;
                e.dataTransfer.effectAllowed = 'move';
                setTimeout(() => div.classList.add('dragging'), 0);
            });

            div.addEventListener('dragend', () => {
                div.classList.remove('dragging');
                draggedTask = null;
            });

            // 确保任务卡片可点击
            div.style.cursor = 'pointer';
            div.addEventListener('click', (e) => {
                e.stopPropagation();
                if (!e.target.classList.contains('task-checkbox') && !e.target.classList.contains('delete-btn')) {
                    console.log('点击任务,准备编辑:', task);
                    editTask(task);
                }
            });

            return div;
        }

        function getPriorityClass(priority) {
            switch (priority) {
                case 1: return 'high-priority';
                case 2: return 'medium-priority';
                case 3: return 'low-priority';
                default: return '';
            }
        }

        function allowDrop(ev) {
            ev.preventDefault();
        }

        function drop(ev, targetType) {
            ev.preventDefault();
            
            if (!draggedTask) return;

            if (targetType === 'pool') {
                // 拖到任务池,只更新位置,不清除原任务
                draggedTask.slot = 'POOL';
                draggedTask.weekday = null;
            } else {
                const cell = ev.target.closest('.task-cell');
                if (cell) {
                    if (draggedTask.slot === 'POOL') {
                        // 从任务池拖到网格,创建副本
                        const newTask = {
                            ...draggedTask,
                            id: generateId(),
                            weekday: parseInt(cell.dataset.day),
                            slot: cell.dataset.slot,
                            order: Date.now()
                        };
                        tasks.push(newTask);
                    } else {
                        // 网格间移动,直接更新位置
                        draggedTask.weekday = parseInt(cell.dataset.day);
                        draggedTask.slot = cell.dataset.slot;
                    }
                }
            }

            renderTasks();
            saveToLocalStorage();
        }

        function addTask(day, slot) {
            currentEditingTask = null;
            document.getElementById('modalTitle').textContent = '添加任务';
            document.getElementById('taskForm').reset();
            
            // 设置默认时间
            if (slot) {
                const morningRange = localStorage.getItem('morningRange') || '08:00-12:00';
                const afternoonRange = localStorage.getItem('afternoonRange') || '13:00-18:00';
                const eveningRange = localStorage.getItem('eveningRange') || '19:00-23:00';
                
                let startTime, endTime;
                if (slot === 'AM') {
                    const times = morningRange.split('-');
                    startTime = times[0];
                    endTime = times[1];
                } else if (slot === 'PM') {
                    const times = afternoonRange.split('-');
                    startTime = times[0];
                    endTime = times[1];
                } else if (slot === 'EVENING') {
                    const times = eveningRange.split('-');
                    startTime = times[0];
                    endTime = times[1];
                }
                
                if (startTime && endTime) {
                    document.getElementById('taskStart').value = startTime;
                    document.getElementById('taskEnd').value = endTime;
                }
            }

            // 设置默认优先级
            selectPriority(2);

            // 设置默认星期几
            if (day) {
                // 清除所有选中状态
                document.querySelectorAll('.weekday-btn[data-day="1"], .weekday-btn[data-day="2"], .weekday-btn[data-day="3"], .weekday-btn[data-day="4"], .weekday-btn[data-day="5"], .weekday-btn[data-day="6"], .weekday-btn[data-day="7"], .weekday-btn[data-day="all"]').forEach(btn => {
                    btn.classList.remove('active');
                });
                
                // 选中对应的星期
                const weekdayBtn = document.querySelector(`.weekday-btn[data-day="${day}"]`);
                if (weekdayBtn) {
                    weekdayBtn.classList.add('active');
                }
            }

            document.getElementById('taskModal').style.display = 'block';
            
            // 存储临时位置信息
            window.tempTaskLocation = { day, slot };
        }

        function addTaskToPool() {
            addTask(null, null);
        }

        function editTask(task) {
            console.log('开始编辑任务:', task);
            if (!task) {
                console.error('任务对象为空');
                return;
            }
            currentEditingTask = task;
            document.getElementById('modalTitle').textContent = '编辑任务';
            document.getElementById('taskTitle').value = task.title;
            document.getElementById('taskStart').value = task.start || '';
            document.getElementById('taskEnd').value = task.end || '';
            document.getElementById('taskNote').value = task.note || '';
            selectPriority(task.priority || 2);
            
            // 重置星期选择
            document.querySelectorAll('.weekday-btn[data-day="1"], .weekday-btn[data-day="2"], .weekday-btn[data-day="3"], .weekday-btn[data-day="4"], .weekday-btn[data-day="5"], .weekday-btn[data-day="6"], .weekday-btn[data-day="7"], .weekday-btn[data-day="all"]').forEach(btn => {
                btn.classList.remove('active');
            });
            
            // 如果任务有星期信息,选中对应的星期
            if (task.weekday) {
                const weekdayBtn = document.querySelector(`.weekday-btn[data-day="${task.weekday}"]`);
                if (weekdayBtn) {
                    weekdayBtn.classList.add('active');
                }
            }
            
            console.log('打开模态框');
            const modal = document.getElementById('taskModal');
            modal.style.display = 'block';
            modal.style.zIndex = '10000'; // 确保模态框在最上层
            
            // 确保模态框可见
            setTimeout(() => {
                modal.style.opacity = '1';
            }, 10);
        }

        function saveTask(event) {
            event.preventDefault();
            
            const title = document.getElementById('taskTitle').value.trim();
            if (!title) {
                showToast('请输入任务标题', 'error');
                return;
            }
            
            const start = document.getElementById('taskStart').value;
            const end = document.getElementById('taskEnd').value;
            const note = document.getElementById('taskNote').value;
            const priority = parseInt(document.querySelector('.priority-btn.active').dataset.priority);
            
            if (currentEditingTask) {
                // 编辑现有任务
                currentEditingTask.title = title;
                currentEditingTask.start = start;
                currentEditingTask.end = end;
                currentEditingTask.note = note;
                currentEditingTask.priority = priority;
            } else {
                // 创建新任务 - 支持多星期选择
                const location = window.tempTaskLocation;
                const selectedWeekdays = getSelectedWeekdays();
                
                if (selectedWeekdays.length > 0) {
                    // 选择了具体星期,为每个选中的星期创建任务
                    selectedWeekdays.forEach(weekday => {
                        const newTask = {
                            id: generateId(),
                            title,
                            start,
                            end,
                            note,
                            priority,
                            done: false,
                            doneAt: null,
                            weekday: weekday,
                            slot: location?.slot || 'AM',
                            order: Date.now()
                        };
                        tasks.push(newTask);
                    });
                } else {
                    // 没有选择星期,根据位置信息创建任务
                    if (location && location.day && location.slot) {
                        // 有明确位置信息,创建到指定位置
                        const newTask = {
                            id: generateId(),
                            title,
                            start,
                            end,
                            note,
                            priority,
                            done: false,
                            doneAt: null,
                            weekday: location.day,
                            slot: location.slot,
                            order: Date.now()
                        };
                        tasks.push(newTask);
                    } else {
                        // 没有位置信息(比如从任务池添加),放到任务池
                        const newTask = {
                            id: generateId(),
                            title,
                            start,
                            end,
                            note,
                            priority,
                            done: false,
                            doneAt: null,
                            weekday: null,
                            slot: 'POOL',
                            order: Date.now()
                        };
                        tasks.push(newTask);
                    }
                }
            }

            renderTasks();
            saveToLocalStorage();
            closeModal();
            showToast('任务保存成功', 'success');
        }

        function toggleTask(taskId) {
            const task = tasks.find(t => t.id === taskId);
            if (task) {
                task.done = !task.done;
                task.doneAt = task.done ? new Date().toISOString() : null;
                renderTasks();
                saveToLocalStorage();
            }
        }

        function deleteTask(taskId) {
            if (confirm('确定要删除这个任务吗?')) {
                tasks = tasks.filter(t => t.id !== taskId);
                renderTasks();
                saveToLocalStorage();
                showToast('任务已删除');
            }
        }

        function selectPriority(priority) {
            document.querySelectorAll('.priority-btn').forEach(btn => {
                btn.classList.remove('active');
            });
            document.querySelector(`[data-priority="${priority}"]`).classList.add('active');
        }



        function toggleWeekday(day) {
            const btn = document.querySelector(`.weekday-btn[data-day="${day}"]`);
            btn.classList.toggle('active');
        }

        function toggleAllWeekdays() {
            const allBtn = document.querySelector('.weekday-btn[data-day="all"]');
            const isAllSelected = allBtn.classList.contains('active');
            
            if (isAllSelected) {
                // 取消全选
                allBtn.classList.remove('active');
                document.querySelectorAll('.weekday-btn[data-day="1"], .weekday-btn[data-day="2"], .weekday-btn[data-day="3"], .weekday-btn[data-day="4"], .weekday-btn[data-day="5"], .weekday-btn[data-day="6"], .weekday-btn[data-day="7"]').forEach(btn => {
                    btn.classList.remove('active');
                });
            } else {
                // 全选
                allBtn.classList.add('active');
                document.querySelectorAll('.weekday-btn[data-day="1"], .weekday-btn[data-day="2"], .weekday-btn[data-day="3"], .weekday-btn[data-day="4"], .weekday-btn[data-day="5"], .weekday-btn[data-day="6"], .weekday-btn[data-day="7"]').forEach(btn => {
                    btn.classList.add('active');
                });
            }
        }

        function getSelectedWeekdays() {
            const selectedBtns = document.querySelectorAll('.weekday-btn[data-day="1"].active, .weekday-btn[data-day="2"].active, .weekday-btn[data-day="3"].active, .weekday-btn[data-day="4"].active, .weekday-btn[data-day="5"].active, .weekday-btn[data-day="6"].active, .weekday-btn[data-day="7"].active');
            return Array.from(selectedBtns).map(btn => parseInt(btn.dataset.day));
        }

        function closeModal() {
            document.getElementById('taskModal').style.display = 'none';
            currentEditingTask = null;
            window.tempTaskLocation = null;
            
            // 重置星期选择
            document.querySelectorAll('.weekday-btn').forEach(btn => {
                btn.classList.remove('active');
            });
        }

        // 删除loadSampleData函数
        // 该函数已被移除,不再提供示例数据功能

        // 添加测试任务用于验证编辑功能


        function clearWeek() {
            if (confirm('确定要清空本周所有任务吗?')) {
                tasks = tasks.filter(task => task.slot === 'POOL');
                renderTasks();
                saveToLocalStorage();
                showToast('已清空本周任务');
            }
        }

        function loadSampleData() {
            if (confirm('加载示例数据会覆盖当前所有任务,确定继续吗?')) {
                tasks = [
                    {
                        id: generateId(),
                        title: '晨间会议',
                        start: '09:00',
                        end: '09:30',
                        note: '周例会,讨论本周工作计划',
                        priority: 1,
                        done: false,
                        weekday: 1,
                        slot: 'AM',
                        order: 1
                    },
                    {
                        id: generateId(),
                        title: '项目开发',
                        start: '14:00',
                        end: '17:00',
                        note: '完成新功能开发',
                        priority: 2,
                        done: false,
                        weekday: 2,
                        slot: 'PM',
                        order: 2
                    },
                    {
                        id: generateId(),
                        title: '健身运动',
                        start: '19:00',
                        end: '20:00',
                        note: '跑步30分钟',
                        priority: 3,
                        done: false,
                        weekday: 3,
                        slot: 'EVENING',
                        order: 3
                    }
                ];
                renderTasks();
                saveToLocalStorage();
                showToast('已加载示例数据');
            }
        }



        // Excel导入导出功能
        function exportToExcel() {
            const tasks = loadFromLocalStorage() || [];
            
            // 扩展CSV格式定义,包含所有任务属性
            const CSV_HEADERS = ['星期', '时段', '任务标题', '开始时间', '结束时间', '优先级', '是否完成', '备注', '重复类型', '选定星期', '任务ID'];
            
            // 映射表 - 统一标准
            const WEEKDAY_MAP = {
                1: '周一', 2: '周二', 3: '周三', 4: '周四', 5: '周五', 6: '周六', 7: '周日',
                null: '任务池'
            };
            const SLOT_MAP = {
                'AM': '上午', 'PM': '下午', 'EVENING': '晚上', 'POOL': '任务池'
            };
            const PRIORITY_MAP = {
                1: '', 2: '', 3: ''
            };
            const REPEAT_TYPE_MAP = {
                'once': '单次', 'daily': '每天', 'weekly': '每周'
            };
            
            // 构建CSV数据
            const csvData = [CSV_HEADERS];
            
            // 确保tasks是数组并过滤有效任务
            const taskArray = Array.isArray(tasks) ? tasks : [];
            const validTasks = taskArray.filter(task => 
                task && 
                typeof task === 'object' &&
                task.title && task.title.trim() !== ''
            );
            
            // 转换任务数据
            validTasks.forEach(task => {
                // 处理选定星期
                let selectedWeekdaysText = '';
                if (task.selectedWeekdays && Array.isArray(task.selectedWeekdays) && task.selectedWeekdays.length > 0) {
                    selectedWeekdaysText = task.selectedWeekdays.map(day => WEEKDAY_MAP[day] || day).join(',');
                }
                
                csvData.push([
                    WEEKDAY_MAP[task.weekday] || '任务池',
                    SLOT_MAP[task.slot] || '任务池',
                    task.title || '',
                    task.start || '',
                    task.end || '',
                    PRIORITY_MAP[task.priority] || '',
                    task.done ? '' : '',
                    task.note || '',
                    REPEAT_TYPE_MAP[task.repeatType] || '单次',
                    selectedWeekdaysText,
                    task.id || ''
                ]);
            });
            
            // 生成CSV内容
            const csvContent = csvData.map(row => 
                row.map(cell => {
                    const str = String(cell || '');
                    // 处理需要引号的字段
                    if (str.includes(',') || str.includes('"') || str.includes('\n') || str.includes('\r')) {
                        return '"' + str.replace(/"/g, '""') + '"';
                    }
                    return str;
                }).join(',')
            ).join('\r\n');
            
            // 创建并下载文件
            const blob = new Blob(['\ufeff' + csvContent], { 
                type: 'text/csv;charset=utf-8;'
            });
            
            const link = document.createElement('a');
            link.href = URL.createObjectURL(blob);
            link.download = `weekly_tasks_${new Date().toISOString().split('T')[0]}.csv`;
            link.style.display = 'none';
            
            document.body.appendChild(link);
            link.click();
            document.body.removeChild(link);
            
            showToast(`成功导出 ${validTasks.length} 个任务`);
        }

        function showImportModal() {
            document.getElementById('importModal').style.display = 'block';
            document.getElementById('importPreview').style.display = 'none';
        }

        function closeImportModal() {
            document.getElementById('importModal').style.display = 'none';
            importedData = null;
        }

        function handleFileSelect(event) {
            const file = event.target.files[0];
            if (file) {
                // 显示文件信息
                document.getElementById('fileInfo').style.display = 'block';
                document.getElementById('fileName').textContent = file.name;
                document.getElementById('fileSize').textContent = formatFileSize(file.size);
                
                parseExcelFile(file);
            }
        }

        function clearFile() {
            document.getElementById('fileInput').value = '';
            document.getElementById('fileInfo').style.display = 'none';
            document.getElementById('importPreview').style.display = 'none';
            importedData = null;
        }

        function formatFileSize(bytes) {
            if (bytes === 0) return '0 Bytes';
            const k = 1024;
            const sizes = ['Bytes', 'KB', 'MB', 'GB'];
            const i = Math.floor(Math.log(bytes) / Math.log(k));
            return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
        }

        // 统一CSV解析函数
        function parseCSVLine(line) {
            const cells = [];
            let current = '';
            let inQuotes = false;
            let i = 0;
            
            while (i < line.length) {
                const char = line[i];
                
                if (char === '"') {
                    if (inQuotes && line[i + 1] === '"') {
                        current += '"';
                        i += 2;
                    } else {
                        inQuotes = !inQuotes;
                        i++;
                    }
                } else if (char === ',' && !inQuotes) {
                    cells.push(current);
                    current = '';
                    i++;
                } else {
                    current += char;
                    i++;
                }
            }
            
            cells.push(current);
            return cells;
        }

        function parseExcelFile(file) {
            const reader = new FileReader();
            reader.onload = function(e) {
                const text = e.target.result;
                const lines = text.replace(/\r\n/g, '\n').split('\n');
                const newTasks = [];
                
                // 标准映射表 - 与导出保持一致
                const WEEKDAY_MAP = {
                    '周一': 1, '周二': 2, '周三': 3, '周四': 4, '周五': 5, '周六': 6, '周日': 7,
                    '星期一': 1, '星期二': 2, '星期三': 3, '星期四': 4, '星期五': 5, '星期六': 6, '星期日': 7,
                    '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7,
                    'monday': 1, 'tuesday': 2, 'wednesday': 3, 'thursday': 4, 'friday': 5, 'saturday': 6, 'sunday': 7,
                    'mon': 1, 'tue': 2, 'wed': 3, 'thu': 4, 'fri': 5, 'sat': 6, 'sun': 7,
                    '任务池': null
                };
                
                const SLOT_MAP = {
                    '上午': 'AM', '下午': 'PM', '晚上': 'EVENING', '任务池': 'POOL',
                    'AM': 'AM', 'PM': 'PM', 'EVENING': 'EVENING', 'POOL': 'POOL',
                    'morning': 'AM', 'afternoon': 'PM', 'evening': 'EVENING'
                };
                
                const PRIORITY_MAP = {
                    '': 1, '': 2, '': 3,
                    'high': 1, 'medium': 2, 'low': 3,
                    '1': 1, '2': 2, '3': 3
                };
                
                const COMPLETION_MAP = {
                    '': true, '': false,
                    'true': true, 'false': false,
                    '1': true, '0': false,
                    'yes': true, 'no': false
                };
                
                const REPEAT_TYPE_MAP = {
                    '单次': 'once', '每天': 'daily', '每周': 'weekly',
                    'once': 'once', 'daily': 'daily', 'weekly': 'weekly'
                };
                
                // 跳过标题行,处理数据行
                for (let i = 1; i < lines.length; i++) {
                    const line = lines[i].trim();
                    if (!line || line === '') continue;
                    
                    // 跳过表头行
                    if (line.includes('星期') && line.includes('任务标题')) {
                        continue;
                    }
                    
                    try {
                        // 解析CSV行
                        const cells = parseCSVLine(line);
                        if (!cells || cells.length < 7) {
                            console.warn(`跳过第 ${i + 1} 行: 列数不足`);
                            continue;
                        }
                        
                        // 清理数据
                        const cleanCells = cells.map(cell => cell.trim().replace(/^"|"$/g, ''));
                        
                        // 提取字段(支持新旧格式)
                        const weekdayText = cleanCells[0] || '周一';
                        const slotText = cleanCells[1] || '上午';
                        const title = cleanCells[2] || '';
                        const start = cleanCells[3] || '';
                        const end = cleanCells[4] || '';
                        const priorityText = cleanCells[5] || '';
                        const completionText = cleanCells[6] || '';
                        const note = cleanCells[7] || '';
                        const repeatTypeText = cleanCells[8] || '单次'; // 新字段
                        const selectedWeekdaysText = cleanCells[9] || ''; // 新字段
                        const taskId = cleanCells[10] || generateId(); // 新字段
                        
                        // 跳过空标题
                        if (!title || title.trim() === '') {
                            continue;
                        }
                        
                        // 解析选定星期
                        let selectedWeekdays = [];
                        if (selectedWeekdaysText && selectedWeekdaysText.trim()) {
                            const weekdayNames = selectedWeekdaysText.split(',').map(name => name.trim());
                            selectedWeekdays = weekdayNames.map(name => WEEKDAY_MAP[name]).filter(day => day !== undefined && day !== null);
                        }
                        
                        // 创建任务对象
                        const task = {
                            id: taskId.trim() || generateId(),
                            title: title.trim(),
                            start: start.trim(),
                            end: end.trim(),
                            priority: PRIORITY_MAP[priorityText.toLowerCase()] || 2,
                            done: COMPLETION_MAP[completionText.toLowerCase()] || false,
                            note: note.trim(),
                            weekday: WEEKDAY_MAP[weekdayText] !== undefined ? WEEKDAY_MAP[weekdayText] : 1,
                            slot: SLOT_MAP[slotText] || 'AM',
                            order: Date.now() + i * 1000,
                            repeatType: REPEAT_TYPE_MAP[repeatTypeText] || 'once',
                            selectedWeekdays: selectedWeekdays,
                            doneAt: null
                        };
                        
                        newTasks.push(task);
                        
                    } catch (error) {
                        console.warn(`解析第 ${i + 1} 行失败:`, error.message);
                    }
                }
                
                if (newTasks.length > 0) {
                    importedData = newTasks;
                    document.getElementById('taskCount').textContent = newTasks.length;
                    
                    // 显示预览
                    const previewList = document.getElementById('previewList');
                    if (previewList) {
                        const slots = { AM: '上午', PM: '下午', EVENING: '晚上', POOL: '任务池' };
                        const weekdays = ['', '周一', '周二', '周三', '周四', '周五', '周六', '周日'];
                        const priorityColors = { 1: '#ff5252', 2: '#ffa726', 3: '#66bb6a' };
                        const repeatTypes = { 'once': '单次', 'daily': '每天', 'weekly': '每周' };
                        
                        previewList.innerHTML = newTasks.slice(0, 10).map(task => 
                            `<div style="padding: 15px; border-bottom: 1px solid var(--border-color); display: flex; align-items: center; gap: 12px; transition: background-color 0.2s;" onmouseover="this.style.backgroundColor='#f8f9ff'" onmouseout="this.style.backgroundColor=''">
                                <div style="width: 4px; height: 40px; border-radius: 2px; background: ${priorityColors[task.priority]}; flex-shrink: 0;"></div>
                                <div style="flex: 1;">
                                    <div style="font-weight: 600; color: var(--text-color); margin-bottom: 4px;">${task.title}</div>
                                    <div style="font-size: 13px; color: var(--text-light);">
                                        ${task.weekday ? weekdays[task.weekday] : '任务池'}${slots[task.slot] || '未知时段'}${task.start} - ${task.end}${repeatTypes[task.repeatType] || '单次'}
                                    </div>
                                </div>
                                <div style="font-size: 12px; color: ${priorityColors[task.priority]}; font-weight: 500;">
                                    ${task.priority === 1 ? '' : task.priority === 2 ? '' : ''}优先级
                                </div>
                            </div>`
                        ).join('');
                        
                        if (newTasks.length > 10) {
                            previewList.innerHTML += `
                                <div style="padding: 20px; text-align: center; color: var(--text-light); font-size: 14px;">
                                    📊 还有 <strong style="color: var(--primary-color);">${newTasks.length - 10}</strong> 个任务未显示
                                </div>`;
                        }
                    }
                    
                    document.getElementById('importPreview').style.display = 'block';
                    document.getElementById('confirmImportBtn').disabled = false;
                } else {
                    showToast('未找到有效任务数据,请检查CSV格式', 'error');
                }
            };
            
            reader.onerror = function() {
                showToast('文件读取失败,请重试', 'error');
            };
            
            reader.readAsText(file, 'UTF-8');
        }

        function confirmImport() {
            if (!importedData || !Array.isArray(importedData) || importedData.length === 0) {
                showToast('没有可导入的数据', 'error');
                return;
            }
            
            try {
                // 获取现有任务
                const currentTasks = loadFromLocalStorage() || [];
                const currentTaskArray = Array.isArray(currentTasks) ? currentTasks : [];
                
                // 处理导入的任务,确保数据完整性
                const processedTasks = importedData.map(task => {
                    const processedTask = {
                        id: task.id || generateId(),
                        title: task.title || '',
                        start: task.start || '',
                        end: task.end || '',
                        priority: task.priority || 2,
                        done: task.done || false,
                        note: task.note || '',
                        weekday: task.weekday,
                        slot: task.slot || 'AM',
                        order: task.order || Date.now(),
                        repeatType: task.repeatType || 'once',
                        selectedWeekdays: task.selectedWeekdays || [],
                        doneAt: task.doneAt || null
                    };
                    
                    // 如果是重复任务且在任务池中,确保正确设置
                    if (processedTask.repeatType !== 'once' && (!processedTask.weekday || processedTask.slot === 'POOL')) {
                        processedTask.weekday = null;
                        processedTask.slot = 'POOL';
                    }
                    
                    return processedTask;
                });
                
                // 合并任务(避免重复ID)
                const existingIds = new Set(currentTaskArray.map(task => task.id));
                const newTasks = processedTasks.filter(task => !existingIds.has(task.id));
                const updatedTasks = [...currentTaskArray, ...newTasks];
                
                // 保存到本地存储并更新全局tasks变量
                tasks = updatedTasks;
                saveToLocalStorage(updatedTasks);
                closeImportModal();
                
                // 显示成功通知
                const successToast = document.createElement('div');
                successToast.style.cssText = `
                    position: fixed;
                    top: 20px;
                    right: 20px;
                    background: linear-gradient(135deg, #4caf50, #45a049);
                    color: white;
                    padding: 20px 30px;
                    border-radius: 12px;
                    box-shadow: 0 8px 32px rgba(76, 175, 80, 0.3);
                    font-size: 16px;
                    font-weight: 500;
                    z-index: 10000;
                    animation: slideIn 0.3s ease-out;
                `;
                successToast.innerHTML = `
                    <div style="display: flex; align-items: center; gap: 12px;">
                        <span style="font-size: 24px;">✅</span>
                        <div>
                            <div style="font-weight: 600;">导入成功!</div>
                            <div style="font-size: 14px; opacity: 0.9;">已添加 ${newTasks.length} 个任务${processedTasks.length > newTasks.length ? `(跳过 ${processedTasks.length - newTasks.length} 个重复任务)` : ''}</div>
                        </div>
                    </div>
                `;
                
                document.body.appendChild(successToast);
                setTimeout(() => {
                    successToast.style.animation = 'slideOut 0.3s ease-in';
                    setTimeout(() => successToast.remove(), 300);
                }, 3000);
                
                renderTasks();
                
                // 清空导入数据
                importedData = null;
                
            } catch (error) {
                console.error('导入失败:', error);
                showToast('导入失败,请重试', 'error');
            }
        }

        function showSettingsModal() {
            document.getElementById('settingsModal').style.display = 'block';
            loadSettings();
        }

        function closeSettingsModal() {
            document.getElementById('settingsModal').style.display = 'none';
        }

        function setTheme(theme) {
            document.documentElement.setAttribute('data-theme', theme);
            localStorage.setItem('theme', theme);
            
            // 更新主题按钮状态
            document.querySelectorAll('.theme-btn').forEach(function(btn) {
                btn.classList.remove('active');
            });
            if (event && event.target) {
                event.target.classList.add('active');
            }
        }

        function loadSettings() {
            const savedTheme = localStorage.getItem('theme') || 'light';
            document.documentElement.setAttribute('data-theme', savedTheme);
            
            // 高亮当前主题按钮
            const themeBtns = document.querySelectorAll('.theme-btn');
            if (savedTheme === 'light' && themeBtns[0]) themeBtns[0].classList.add('active');
            if (savedTheme === 'dark' && themeBtns[1]) themeBtns[1].classList.add('active');
            if (savedTheme === 'green' && themeBtns[2]) themeBtns[2].classList.add('active');
            
            // 加载时段设置
            const morningRange = localStorage.getItem('morningRange') || '08:00-12:00';
            const afternoonRange = localStorage.getItem('afternoonRange') || '13:00-18:00';
            const eveningRange = localStorage.getItem('eveningRange') || '19:00-23:00';
            
            // 解析并设置上午时段
            const morningTimes = morningRange.split('-');
            if (morningTimes.length === 2) {
                document.getElementById('morningStart').value = morningTimes[0];
                document.getElementById('morningEnd').value = morningTimes[1];
            }
            
            // 解析并设置下午时段
            const afternoonTimes = afternoonRange.split('-');
            if (afternoonTimes.length === 2) {
                document.getElementById('afternoonStart').value = afternoonTimes[0];
                document.getElementById('afternoonEnd').value = afternoonTimes[1];
            }
            
            // 解析并设置晚上时段
            const eveningTimes = eveningRange.split('-');
            if (eveningTimes.length === 2) {
                document.getElementById('eveningStart').value = eveningTimes[0];
                document.getElementById('eveningEnd').value = eveningTimes[1];
            }
        }

        function updateTimeLabels() {
            const morningRange = localStorage.getItem('morningRange') || '08:00-12:00';
            const afternoonRange = localStorage.getItem('afternoonRange') || '13:00-18:00';
            const eveningRange = localStorage.getItem('eveningRange') || '19:00-23:00';
            
            const timeLabels = document.querySelectorAll('.time-label');
            if (timeLabels[0]) timeLabels[0].innerHTML = `上午<br>${morningRange}`;
            if (timeLabels[1]) timeLabels[1].innerHTML = `下午<br>${afternoonRange}`;
            if (timeLabels[2]) timeLabels[2].innerHTML = `晚上<br>${eveningRange}`;
        }

        function saveSettings() {
            // 保存时段设置
            const morningStart = document.getElementById('morningStart').value;
            const morningEnd = document.getElementById('morningEnd').value;
            const afternoonStart = document.getElementById('afternoonStart').value;
            const afternoonEnd = document.getElementById('afternoonEnd').value;
            const eveningStart = document.getElementById('eveningStart').value;
            const eveningEnd = document.getElementById('eveningEnd').value;
            
            const morningRange = `${morningStart}-${morningEnd}`;
            const afternoonRange = `${afternoonStart}-${afternoonEnd}`;
            const eveningRange = `${eveningStart}-${eveningEnd}`;
            
            localStorage.setItem('morningRange', morningRange);
            localStorage.setItem('afternoonRange', afternoonRange);
            localStorage.setItem('eveningRange', eveningRange);
            
            // 更新时段标签显示
            updateTimeLabels();
            
            showToast('设置已保存');
            closeSettingsModal();
        }

        // 键盘快捷键
        // 移除不存在的dropZone事件监听器
        // 这些事件监听器引用了不存在的dropZone元素
        
        // 键盘快捷键
        document.addEventListener('keydown', (e) => {
            if (e.ctrlKey) {
                switch (e.key) {
                    case 'n':
                        e.preventDefault();
                        addTaskToPool();
                        break;
                    case 's':
                        e.preventDefault();
                        saveToLocalStorage();
                        break;
                    case 'e':
                        e.preventDefault();
                        exportToExcel();
                        break;
                }
            }
        });



        // 全局错误处理
        window.addEventListener('error', function(e) {
            console.error('JavaScript错误:', e.error);
            console.error('错误信息:', e.message);
            console.error('错误位置:', e.filename, '', e.lineno);
        });

        // 初始化
        document.addEventListener('DOMContentLoaded', () => {
            updateDateDisplay();
            loadFromLocalStorage();
            loadSettings();
            updateTimeLabels();
            renderTasks(); // 添加任务渲染,确保页面加载时显示任务
            
            // 每分钟更新日期显示
            setInterval(updateDateDisplay, 60000);
            
            console.log('页面加载完成,任务数量:', tasks.length);
            console.log('任务列表:', tasks);
        });

        // 点击模态框外部关闭
        window.onclick = function(event) {
            const modals = ['taskModal', 'importModal', 'settingsModal'];
            modals.forEach(modalId => {
                const modal = document.getElementById(modalId);
                if (event.target === modal) {
                    if (modalId === 'taskModal') {
                        closeModal();
                    } else if (modalId === 'importModal') {
                        closeImportModal();
                    } else if (modalId === 'settingsModal') {
                        closeSettingsModal();
                    }
                }
            });
        };
    </script>
</body>
</html>

manifest.json

{
  "name": "每日工作计划备忘录",
  "short_name": "工作计划",
  "description": "零依赖的每日工作计划管理工具,支持拖拽排序、Excel导入导出、离线使用",
  "start_url": "./index.html",
  "display": "standalone",
  "background_color": "#ffffff",
  "theme_color": "#0078f5",
  "icons": [
    {
      "src": "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTkyIiBoZWlnaHQ9IjE5MiIgdmlld0JveD0iMCAwIDE5MiAxOTIiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxyZWN0IHdpZHRoPSIxOTIiIGhlaWdodD0iMTkyIiByeD0iMjQiIGZpbGw9IiMwMDc4RjUiLz4KPHN2ZyB4PSI0OCIgeT0iNDgiIHdpZHRoPSI5NiIgaGVpZ2h0PSI5NiIgdmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJ3aGl0ZSI+CjxwYXRoIGQ9Ik0xOSA0SDVjLTEuMTEgMC0yIC44OS0yIDJ2MTJjMCAxLjExLjg5IDIgMiAyaDE0YzEuMTEgMCAyLS44OSAyLTJWNmMwLTEuMTEtLjg5LTItMi0yem0wIDE0SDVWNmgxNHYxMnptLTcuNTEtNC4yOUwxMiAxNGwtMi40OS0yLjI5TDcgMTIuNTEgMTIgMTlsNS01LjQ5LTEuNTEtMS41MXoiLz4KPC9zdmc+Cjwvc3ZnPgo=",
      "sizes": "192x192",
      "type": "image/svg+xml"
    },
    {
      "src": "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTEyIiBoZWlnaHQ9IjUxMiIgdmlld0JveD0iMCAwIDUxMiA1MTIiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxyZWN0IHdpZHRoPSI1MTIiIGhlaWdodD0iNTEyIiByeD0iNjQiIGZpbGw9IiMwMDc4RjUiLz4KPHN2ZyB4PSIxMjgiIHk9IjEyOCIgd2lkdGg9IjI1NiIgaGVpZ2h0PSIyNTYiIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0id2hpdGUiPgo8cGF0aCBkPSJNMTkgNEg1Yy0xLjExIDAtMiAuODktMiAydjEyYzAgMS4xMS44OSAyIDIgMmgxNGMxLjExIDAgMi0uODkgMi0yVjZjMC0xLjExLS44OS0yLTItMnptMCAxNEg1VjZoMTR2MTJ6bS03LjUxLTQuMjlMMTIgMTRsLTIuNDktMi4yOUw3IDEyLjUxIDEyIDE5bDUtNS40OS0xLjUxLTEuNTF6Ii8+Cjwvc3ZnPgo8L3N2Zz4K",
      "sizes": "512x512",
      "type": "image/svg+xml"
    }
  ],
  "categories": ["productivity", "utilities"],
  "lang": "zh-CN"
}


Comments

Content