<!DOCTYPE html>
<html lang="zh-CN">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title></title>
    <style>
        /* 通用样式重置 */
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }

        body {
            font-family: "Helvetica Neue", Arial, sans-serif;
            background-color: #f5f5f5;
            color: #333;
        }

        .container {
            max-width: 800px;
            margin: 40px auto;
            padding: 20px 30px;
            background-color: #fff;
            border-radius: 8px;
            box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
        }

        h1 {
            text-align: center;
            margin-bottom: 30px;
            font-size: 2em;
            color: #2c3e50;
        }

        .input-group {
            margin-bottom: 20px;
        }

        label {
            display: block;
            margin-bottom: 8px;
            font-weight: bold;
            color: #34495e;
        }

        input[type="date"],
        input[type="number"],
        input[type="text"],
        input[type="password"] {
            width: 100%;
            padding: 12px 15px;
            border: 1px solid #bdc3c7;
            border-radius: 4px;
            font-size: 1em;
        }

        .tasks-container {
            margin-bottom: 20px;
        }

        .single-task-input {
            display: flex;
            align-items: center;
            margin-bottom: 10px;
        }

        .single-task-input input[type="text"] {
            flex: 1;
            padding: 12px 15px;
            border: 1px solid #bdc3c7;
            border-radius: 4px;
            font-size: 1em;
        }

        .remove-task-button {
            background-color: #e74c3c;
            color: white;
            border: none;
            padding: 12px 15px;
            margin-left: 10px;
            border-radius: 4px;
            cursor: pointer;
            transition: background-color 0.3s;
        }

        .remove-task-button:hover {
            background-color: #c0392b;
        }

        .buttons-row {
            display: flex;
            flex-wrap: wrap;
            gap: 10px;
            margin-bottom: 20px;
        }

        .add-task-button,
        .generate-task-button {
            background-color: #3498db;
            color: white;
            border: none;
            padding: 12px 20px;
            border-radius: 4px;
            cursor: pointer;
            font-size: 16px;
            transition: background-color 0.3s;
        }

        .add-task-button:hover,
        .generate-task-button:hover {
            background-color: #2980b9;
        }

        .submit-button {
            background-color: #e67e22;
            color: white;
            border: none;
            padding: 14px 24px;
            border-radius: 4px;
            cursor: pointer;
            font-size: 18px;
            font-weight: bold;
            transition: background-color 0.3s;
            margin-bottom: 30px;
            display: block;
            width: 100%;
        }

        .submit-button:hover {
            background-color: #d35400;
        }

        .error {
            color: #e74c3c;
            margin-top: 10px;
            white-space: pre-line;
        }

        .task-list {
            list-style-type: none;
            padding: 0;
            margin-bottom: 30px;
        }

        .date-group {
            margin-bottom: 30px;
        }

        .date-header {
            display: flex;
            align-items: center;
            font-weight: bold;
            font-size: 1.5em;
            color: #34495e;
            margin-bottom: 15px;
            border-bottom: 2px solid #ecf0f1;
            padding-bottom: 5px;
        }

        .task-item {
            display: flex;
            align-items: center;
            margin-bottom: 10px;
            padding: 10px 15px;
            background-color: #ecf0f1;
            border-radius: 4px;
            transition: background-color 0.3s;
        }

        .task-item:hover {
            background-color: #d0d7de;
        }

        .task-item input[type="checkbox"] {
            margin-right: 15px;
            width: 20px;
            height: 20px;
            cursor: pointer;
        }

        .task-item span {
            font-size: 1em;
            cursor: pointer;
            flex: 1;
        }

        .task-item.completed span {
            text-decoration: line-through;
            color: #7f8c8d;
        }

        /* 删除任务按钮 */
        .delete-task-button {
            background-color: transparent;
            border: none;
            color: #e74c3c;
            font-size: 1em;
            cursor: pointer;
            margin-left: 10px;
        }

        /* 删除日期按钮 */
        .delete-date-button {
            background-color: transparent;
            border: none;
            color: #e74c3c;
            font-size: 0.9em;
            cursor: pointer;
            margin-left: 15px;
        }

        /* 加载指示器样式 */
        .loading-spinner {
            display: inline-block;
            width: 24px;
            height: 24px;
            border: 3px solid #3498db;
            border-top-color: transparent;
            border-radius: 50%;
            animation: spin 1s linear infinite;
            margin-right: 10px;
            vertical-align: middle;
        }

        @keyframes spin {
            to {
                transform: rotate(360deg);
            }
        }

        /* 响应式设计 */
        @media (max-width: 768px) {
            .container {
                padding: 20px;
            }

            .buttons-row {
                flex-direction: column;
            }

            .add-task-button,
            .generate-task-button {
                width: 100%;
            }

            .single-task-input {
                flex-direction: column;
            }

            .remove-task-button {
                margin-left: 0;
                margin-top: 10px;
                width: 100%;
            }

            .submit-button {
                width: 100%;
            }
        }
    </style>
    <!-- 引入CryptoJS库 -->
    <script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.1.1/crypto-js.min.js"></script>
</head>

<body>
    <div class="container">
        <h1 id="title"></h1>
        <!-- 密码设置区域 -->
        <div class="input-group" id="password-section">
            <label for="set-password" id="label-set-password"></label>
            <input type="password" id="set-password" maxlength="6" placeholder="">
            <button class="submit-button" id="button-set-password" onclick="setPassword()"></button>
        </div>

        <!-- 查看计划按钮 -->
        <button class="submit-button" id="view-plan-button" onclick="getTasks()"></button>

        <!-- 加载信息 -->
        <div id="loading-message"
            style="display: none; text-align: center; font-size: 1.2em; color: #3498db; margin-bottom: 20px;">
            <span class="loading-spinner"></span>
            <span id="loading-text"></span>
        </div>

        <!-- 将任务列表放在查看计划按钮的下方 -->
        <ul class="task-list" id="task-list"></ul>

        <!-- 添加计划区域 -->
        <div id="add-plan-section">
            <!-- 添加计划按钮放在选择日期上方 -->
            <button class="submit-button" id="button-add-plan" onclick="addTasks()"></button>

            <div class="input-group">
                <label for="task-date" id="label-task-date"></label>
                <input type="date" id="task-date">
            </div>
            <div class="input-group">
                <label for="tasks-container" id="label-task-list"></label>
                <div class="tasks-container" id="tasks-container">
                    <!-- 动态添加任务输入字段 -->
                </div>
                <div class="buttons-row">
                    <button class="add-task-button" id="button-add-task-input" onclick="addTaskInput()"></button>
                    <input type="number" id="task-quantity" min="1" placeholder="">
                    <button class="generate-task-button" id="button-generate-tasks"
                        onclick="addMultipleTaskInputs()"></button>
                </div>
            </div>
            <!-- 提交任务按钮 -->
            <button class="submit-button" id="submit-tasks-button" onclick="addTasks()"></button>
        </div>

        <div id="error-message" class="error"></div>
    </div>

    <script>
        // 语言数据
        const languageData = {
            "en": {
                "My Plan": "My Plan",
                "Set 6-digit Password": "Set 6-digit Password",
                "Please enter a 6-digit numeric password": "Please enter a 6-digit numeric password",
                "Set Password": "Set Password",
                "View Plan": "View Plan",
                "Loading Plan...": "Loading Plan...",
                "Add Plan": "Add Plan",
                "Select Date:": "Select Date:",
                "Task List:": "Task List:",
                "Add Task Input": "Add Task Input",
                "Task Quantity": "Task Quantity",
                "Generate Tasks": "Generate Tasks",
                "Delete": "Delete",
                "Enter Task Content": "Enter Task Content",
                "Submit": "Submit",
                "Please enter a valid task quantity (at least 1)!": "Please enter a valid task quantity (at least 1)!",
                "Please set a password first!": "Please set a password first!",
                "Please select a date!": "Please select a date!",
                "Please add task input fields first!": "Please add task input fields first!",
                "Please enter at least one task content!": "Please enter at least one task content!",
                "Tasks added successfully!": "Tasks added successfully!",
                "No plans yet.": "No plans yet.",
                "Delete Date": "Delete Date",
                "Delete Task": "Delete Task",
                "Today": "Today",
                "An error occurred. Please try again.": "An error occurred. Please try again."
            },
            "zh": {
                "My Plan": "我的计划",
                "Set 6-digit Password": "设置 6 位数密码",
                "Please enter a 6-digit numeric password": "请输入 6 位数字密码",
                "Set Password": "设置密码",
                "View Plan": "查看计划",
                "Loading Plan...": "正在加载计划...",
                "Add Plan": "添加计划",
                "Select Date:": "选择日期:",
                "Task List:": "任务列表:",
                "Add Task Input": "添加任务输入",
                "Task Quantity": "任务数量",
                "Generate Tasks": "批量生成任务",
                "Delete": "删除",
                "Enter Task Content": "请输入任务内容",
                "Submit": "提交",
                "Please enter a valid task quantity (at least 1)!": "请输入有效的任务数量（至少为1）！",
                "Please set a password first!": "请先设置密码！",
                "Please select a date!": "请选择日期！",
                "Please add task input fields first!": "请先添加任务输入字段！",
                "Please enter at least one task content!": "请输入至少一个任务内容！",
                "Tasks added successfully!": "计划添加成功！",
                "No plans yet.": "暂无计划。",
                "Delete Date": "删除日期",
                "Delete Task": "删除任务",
                "Today": "今天",
                "An error occurred. Please try again.": "发生错误。请重试。"
            }
        };

        // 当前语言
        let currentLanguage = 'zh'; // 默认中文

        // 存储任务的对象，键为日期，值为任务数组
        let tasksByDate = {};

        // 获取URL参数
        function getUrlParameter(name) {
            name = name.replace(/[\[]/, '\\[').replace(/[\]]/, '\\]');
            const regex = new RegExp('[\\?&]' + name + '=([^&#]*)');
            const results = regex.exec(location.search);
            return results === null ? null : decodeURIComponent(results[1].replace(/\+/g, ' '));
        }

        // 更新页面文本内容
        function updateTextContent() {
            // 更新标题
            document.title = languageData[currentLanguage]["My Plan"];
            console.info("currentLanguage", currentLanguage)
            // 更新页面中的文本
            document.getElementById('title').innerText = languageData[currentLanguage]["My Plan"];
            document.getElementById('label-set-password').innerText = languageData[currentLanguage]["Set 6-digit Password"];
            document.getElementById('set-password').placeholder = languageData[currentLanguage]["Please enter a 6-digit numeric password"];
            document.getElementById('button-set-password').innerText = languageData[currentLanguage]["Set Password"];

            document.getElementById('view-plan-button').innerText = languageData[currentLanguage]["View Plan"];
            document.getElementById('loading-text').innerText = languageData[currentLanguage]["Loading Plan..."];
            document.getElementById('button-add-plan').innerText = languageData[currentLanguage]["Add Plan"];
            document.getElementById('label-task-date').innerText = languageData[currentLanguage]["Select Date:"];
            document.getElementById('label-task-list').innerText = languageData[currentLanguage]["Task List:"];
            document.getElementById('button-add-task-input').innerText = languageData[currentLanguage]["Add Task Input"];
            document.getElementById('task-quantity').placeholder = languageData[currentLanguage]["Task Quantity"];
            document.getElementById('button-generate-tasks').innerText = languageData[currentLanguage]["Generate Tasks"];
            document.getElementById('submit-tasks-button').innerText = languageData[currentLanguage]["Submit"];

            // 更新错误信息
            document.getElementById('error-message').innerText = '';

            // 更新任务输入占位符
            const taskInputs = document.querySelectorAll('#tasks-container input[type="text"]');
            taskInputs.forEach(input => {
                input.placeholder = languageData[currentLanguage]["Enter Task Content"];
            });

            // 更新任务列表
            renderTaskList();
        }

        // 获取密码
        function getPasswordFromCookie() {
            const name = 'password=';
            const decodedCookie = decodeURIComponent(document.cookie);
            const cookieArr = decodedCookie.split(';');
            for (let i = 0; i < cookieArr.length; i++) {
                let c = cookieArr[i];
                while (c.charAt(0) === ' ') {
                    c = c.substring(1);
                }
                if (c.indexOf(name) === 0) {
                    const encryptedPassword = c.substring(name.length, c.length);
                    // 解密密码
                    const bytes = CryptoJS.AES.decrypt(encryptedPassword, 'encryptionKey');
                    const password = bytes.toString(CryptoJS.enc.Utf8);
                    return password;
                }
            }
            return '';
        }

        // 设置密码并保存到Cookie
        function setPassword() {
            const passwordInput = document.getElementById('set-password');
            const password = passwordInput.value.trim();
            const errorMessage = document.getElementById('error-message');
            errorMessage.textContent = ''; // 清除之前的错误消息

            if (password.length !== 6 || !/^\d{6}$/.test(password)) {
                errorMessage.textContent = languageData[currentLanguage]["Please enter a 6-digit numeric password"];
                return;
            }

            // 加密密码
            const encryptedPassword = CryptoJS.AES.encrypt(password, 'encryptionKey').toString();

            // 保存加密后的密码到Cookie
            document.cookie = `password=${encryptedPassword}; path=/;`;

            errorMessage.textContent = languageData[currentLanguage]["Tasks added successfully!"];

            // 清空密码输入框
            passwordInput.value = '';

            // 隐藏密码设置区域
            const passwordSection = document.getElementById('password-section');
            passwordSection.style.display = 'none';

            // 在设置密码后，自动获取计划
            getTasks();
        }

        // 获取任务列表
        function getTasks() {
            const errorMessage = document.getElementById('error-message');
            errorMessage.textContent = ''; // 清除之前的错误消息

            const password = getPasswordFromCookie();

            if (!password) {
                errorMessage.textContent = languageData[currentLanguage]["Please set a password first!"];
                return;
            }

            // 显示加载信息
            const loadingMessage = document.getElementById('loading-message');
            loadingMessage.style.display = 'block';

            // 禁用查看计划按钮，防止重复点击
            const viewPlanButton = document.getElementById('view-plan-button');
            viewPlanButton.disabled = true;

            // 清空任务列表，以防止显示过期的数据
            const taskList = document.getElementById('task-list');
            taskList.innerHTML = '';

            // 发送请求到后端获取所有计划
            fetch('http://www.zdxgames.top/planViewBackend/get_all_tasks', {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                },
                body: JSON.stringify({
                    password: password
                }),
            })
                .then(response => {
                    if (!response.ok) {
                        throw new Error(`HTTP error! 状态码: ${response.status}`);
                    }
                    return response.json();
                })
                .then(data => {
                    console.log('后端响应:', data);
                    if (data.status === 'success') {
                        // 显示计划任务
                        tasksByDate = data.tasksByDate;
                        renderTaskList();
                    } else {
                        errorMessage.textContent = data.message || languageData[currentLanguage]["An error occurred. Please try again."];
                    }
                })
                .catch((error) => {
                    console.error('从后端获取数据时出错:', error);
                    errorMessage.textContent = `${languageData[currentLanguage]["An error occurred. Please try again."]}: ${error.message}`;
                })
                .finally(() => {
                    // 无论请求成功还是失败，都隐藏加载信息
                    loadingMessage.style.display = 'none';
                    // 重新启用查看计划按钮
                    viewPlanButton.disabled = false;
                });
        }

        // 设置今日日期
        function setTodayDate() {
            const dateInput = document.getElementById('task-date');
            const today = new Date().toISOString().split('T')[0];
            dateInput.value = today;
        }

        // 添加任务输入字段
        function addTaskInput() {
            const tasksContainer = document.getElementById('tasks-container');

            const taskInputDiv = document.createElement('div');
            taskInputDiv.classList.add('single-task-input');

            const taskInput = document.createElement('input');
            taskInput.type = 'text';
            taskInput.placeholder = languageData[currentLanguage]["Enter Task Content"];

            const removeButton = document.createElement('button');
            removeButton.classList.add('remove-task-button');
            removeButton.textContent = languageData[currentLanguage]["Delete"];
            removeButton.onclick = function () {
                removeTaskInput(removeButton);
            };

            taskInputDiv.appendChild(taskInput);
            taskInputDiv.appendChild(removeButton);

            tasksContainer.appendChild(taskInputDiv);
        }

        // 批量添加任务输入字段
        function addMultipleTaskInputs() {
            const quantityInput = document.getElementById('task-quantity');
            const tasksContainer = document.getElementById('tasks-container');
            const errorMessage = document.getElementById('error-message');
            errorMessage.textContent = ''; // 清除之前的错误消息

            const quantity = parseInt(quantityInput.value.trim());

            if (isNaN(quantity) || quantity < 1) {
                errorMessage.textContent = languageData[currentLanguage]["Please enter a valid task quantity (at least 1)!"];
                return;
            }

            for (let i = 0; i < quantity; i++) {
                addTaskInput();
            }

            // 清空任务数量输入框
            quantityInput.value = '';
        }

        // 删除任务输入字段
        function removeTaskInput(button) {
            const taskInputDiv = button.parentNode;
            taskInputDiv.parentNode.removeChild(taskInputDiv);
        }

        // 添加计划
        function addTasks() {
            const taskDate = document.getElementById('task-date').value.trim();
            const tasksContainer = document.getElementById('tasks-container');
            const taskInputs = tasksContainer.getElementsByTagName('input');
            const errorMessage = document.getElementById('error-message');
            errorMessage.textContent = ''; // 清除之前的错误消息

            const password = getPasswordFromCookie();

            if (!password) {
                errorMessage.textContent = languageData[currentLanguage]["Please set a password first!"];
                return;
            }

            if (!taskDate) {
                errorMessage.textContent = languageData[currentLanguage]["Please select a date!"];
                return;
            }

            if (taskInputs.length === 0) {
                errorMessage.textContent = languageData[currentLanguage]["Please add task input fields first!"];
                return;
            }

            const taskContents = [];
            for (let input of taskInputs) {
                const taskContent = input.value.trim();
                if (taskContent !== '') {
                    taskContents.push(taskContent);
                }
            }

            if (taskContents.length === 0) {
                errorMessage.textContent = languageData[currentLanguage]["Please enter at least one task content!"];
                return;
            }

            // 清空任务输入框
            tasksContainer.innerHTML = '';

            // 将任务数据和密码发送到后端
            sendTasksToBackend(taskDate, taskContents, password);
        }

        // 渲染任务列表
        // 修改渲染任务列表的函数
        function renderTaskList() {
            const taskList = document.getElementById('task-list');
            taskList.innerHTML = '';

            const sortedDates = Object.keys(tasksByDate).sort();

            if (sortedDates.length === 0) {
                taskList.innerHTML = `<p>${languageData[currentLanguage]["No plans yet."]}</p>`;
                return;
            }

            sortedDates.forEach(date => {
                const dateGroup = document.createElement('li');
                dateGroup.classList.add('date-group');

                const dateHeader = document.createElement('div');
                dateHeader.classList.add('date-header');

                const dateText = document.createElement('span');
                dateText.textContent = date;

                const deleteDateButton = document.createElement('button');
                deleteDateButton.textContent = languageData[currentLanguage]["Delete Date"];
                deleteDateButton.classList.add('delete-date-button');
                deleteDateButton.onclick = function () {
                    deleteDate(date);
                };

                dateHeader.appendChild(dateText);
                dateHeader.appendChild(deleteDateButton);
                dateGroup.appendChild(dateHeader);

                const subList = document.createElement('ul');
                subList.classList.add('sub-task-list');

                tasksByDate[date].forEach((task) => {
                    const taskContent = typeof task === 'string' ? task : task.content;
                    const isCompleted = typeof task === 'object' ? task.completed : false;

                    const taskItem = document.createElement('li');
                    taskItem.classList.add('task-item');
                    if (isCompleted) {
                        taskItem.classList.add('completed');
                    }

                    const checkbox = document.createElement('input');
                    checkbox.type = 'checkbox';
                    checkbox.checked = isCompleted;

                    const taskSpan = document.createElement('span');
                    taskSpan.textContent = taskContent;

                    const deleteTaskButton = document.createElement('button');
                    deleteTaskButton.textContent = languageData[currentLanguage]["Delete Task"];
                    deleteTaskButton.classList.add('delete-task-button');
                    deleteTaskButton.onclick = function (event) {
                        event.stopPropagation();
                        deleteTask(date, taskContent);
                    };

                    taskItem.appendChild(checkbox);
                    taskItem.appendChild(taskSpan);
                    taskItem.appendChild(deleteTaskButton);

                    // 为整个任务项添加点击事件
                    taskItem.onclick = function (event) {
                        if (event.target !== deleteTaskButton) {
                            checkbox.checked = !checkbox.checked;
                            updateTaskStatus(date, taskContent, checkbox.checked);
                        }
                    };

                    checkbox.onclick = function (event) {
                        event.stopPropagation();
                        updateTaskStatus(date, taskContent, this.checked);
                    };

                    subList.appendChild(taskItem);
                });

                dateGroup.appendChild(subList);
                taskList.appendChild(dateGroup);
            });
        }
        // 添加更新任务状态的函数
        function updateTaskStatus(date, taskContent, isCompleted) {
            const password = getPasswordFromCookie();
            const errorMessage = document.getElementById('error-message');

            if (!password) {
                errorMessage.textContent = languageData[currentLanguage]["Please set a password first!"];
                return;
            }

            // 立即更新本地状态和视觉效果
            updateLocalTaskStatus(date, taskContent, isCompleted);

            fetch('http://www.zdxgames.top/planViewBackend/update_task_status', {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                },
                body: JSON.stringify({
                    date: date,
                    taskContent: taskContent,
                    isCompleted: isCompleted,
                    password: password
                }),
            })
                .then(response => response.json())
                .then(data => {
                    if (data.status !== 'success') {
                        // 如果更新失败，回滚本地状态
                        updateLocalTaskStatus(date, taskContent, !isCompleted);
                        errorMessage.textContent = data.message || languageData[currentLanguage]["An error occurred. Please try again."];
                    }
                })
                .catch(error => {
                    console.error('更新任务状态时出错:', error);
                    // 如果出错，回滚本地状态
                    updateLocalTaskStatus(date, taskContent, !isCompleted);
                    errorMessage.textContent = `${languageData[currentLanguage]["An error occurred. Please try again."]}: ${error.message}`;
                });
        }

        // 新增函数：更新本地任务状态和视觉效果
        function updateLocalTaskStatus(date, taskContent, isCompleted) {
            const dateTask = tasksByDate[date];
            const taskIndex = dateTask.findIndex(t =>
                (typeof t === 'string' && t === taskContent) ||
                (typeof t === 'object' && t.content === taskContent)
            );

            if (taskIndex !== -1) {
                if (typeof dateTask[taskIndex] === 'string') {
                    dateTask[taskIndex] = { content: taskContent, completed: isCompleted };
                } else {
                    dateTask[taskIndex].completed = isCompleted;
                }
            }

            // 更新视觉效果
            const taskItems = document.querySelectorAll('.task-item');
            taskItems.forEach(item => {
                const itemSpan = item.querySelector('span');
                const itemCheckbox = item.querySelector('input[type="checkbox"]');
                if (itemSpan.textContent === taskContent) {
                    itemCheckbox.checked = isCompleted;
                    if (isCompleted) {
                        item.classList.add('completed');
                    } else {
                        item.classList.remove('completed');
                    }
                }
            });
        }

        // 删除单个任务
        function deleteTask(date, taskContent) {
            const password = getPasswordFromCookie();
            const errorMessage = document.getElementById('error-message');

            if (!password) {
                errorMessage.textContent = languageData[currentLanguage]["Please set a password first!"];
                return;
            }

            fetch('http://www.zdxgames.top/planViewBackend/delete_task', {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                },
                body: JSON.stringify({
                    date: date,
                    taskContent: taskContent,
                    password: password
                }),
            })
                .then(response => {
                    if (!response.ok) {
                        throw new Error(`HTTP error! 状态码: ${response.status}`);
                    }
                    return response.json();
                })
                .then(data => {
                    console.log('删除任务响应:', data);
                    if (data.status === 'success') {
                        // 更新本地数据并重新渲染任务列表
                        const index = tasksByDate[date].indexOf(taskContent);
                        if (index > -1) {
                            tasksByDate[date].splice(index, 1);
                            if (tasksByDate[date].length === 0) {
                                delete tasksByDate[date];
                            }
                        }
                        renderTaskList();
                    } else {
                        errorMessage.textContent = data.message || languageData[currentLanguage]["An error occurred. Please try again."];
                    }
                })
                .catch((error) => {
                    console.error('删除任务时出错:', error);
                    errorMessage.textContent = `${languageData[currentLanguage]["An error occurred. Please try again."]}: ${error.message}`;
                });
        }

        // 删除整个日期的计划
        function deleteDate(date) {
            const password = getPasswordFromCookie();
            const errorMessage = document.getElementById('error-message');

            if (!password) {
                errorMessage.textContent = languageData[currentLanguage]["Please set a password first!"];
                return;
            }

            fetch('http://www.zdxgames.top/planViewBackend/delete_date', {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                },
                body: JSON.stringify({
                    date: date,
                    password: password
                }),
            })
                .then(response => {
                    if (!response.ok) {
                        throw new Error(`HTTP error! 状态码: ${response.status}`);
                    }
                    return response.json();
                })
                .then(data => {
                    console.log('删除日期响应:', data);
                    if (data.status === 'success') {
                        // 更新本地数据并重新渲染任务列表
                        delete tasksByDate[date];
                        renderTaskList();
                    } else {
                        errorMessage.textContent = data.message || languageData[currentLanguage]["An error occurred. Please try again."];
                    }
                })
                .catch((error) => {
                    console.error('删除日期时出错:', error);
                    errorMessage.textContent = `${languageData[currentLanguage]["An error occurred. Please try again."]}: ${error.message}`;
                });
        }

        // 将任务数据发送到后端
        function sendTasksToBackend(date, tasks, password) {
            fetch('http://www.zdxgames.top/planViewBackend/add_tasks', {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                },
                body: JSON.stringify({
                    date: date,
                    tasks: tasks,
                    password: password  // 添加密码
                }),
            })
                .then(response => {
                    if (!response.ok) {
                        throw new Error(`HTTP error! 状态码: ${response.status}`);
                    }
                    return response.json();
                })
                .then(data => {
                    console.log('后端响应:', data);
                    const errorMessage = document.getElementById('error-message');
                    if (data.status === 'success') {
                        errorMessage.textContent = languageData[currentLanguage]["Tasks added successfully!"];
                        // 重新获取并显示计划
                        getTasks();
                    } else {
                        errorMessage.textContent = data.message || languageData[currentLanguage]["An error occurred. Please try again."];
                    }
                })
                .catch((error) => {
                    console.error('发送数据到后端时出错:', error);
                    const errorMessage = document.getElementById('error-message');
                    errorMessage.textContent = `${languageData[currentLanguage]["An error occurred. Please try again."]}: ${error.message}`;
                });
        }

        // 初始设置日期为今天，并添加一个任务输入框
        window.onload = function () {
            // 解析URL参数
            const langParam = getUrlParameter('lang');
            console.log("langParam", langParam)
            if (langParam && (langParam === 'en' || langParam === 'zh')) {
                currentLanguage = langParam;
            } else {
                currentLanguage = 'zh'; // 默认中文
            }

            // 更新页面内容
            updateTextContent();

            setTodayDate();
            addTaskInput();

            // 检查Cookie中是否已有密码
            const password = getPasswordFromCookie();
            const passwordSection = document.getElementById('password-section');

            if (password) {
                // 隐藏密码设置区域
                passwordSection.style.display = 'none';

                // 显示加载信息
                const loadingMessage = document.getElementById('loading-message');
                loadingMessage.style.display = 'block';

                // 在页面加载时自动获取计划
                getTasks();
            } else {
                // 显示密码设置区域
                passwordSection.style.display = 'block';
            }
        };
    </script>
</body>

</html>from flask import Flask, request, jsonify
from flask_cors import CORS
from pymongo import MongoClient, errors
from datetime import datetime
import traceback
import hashlib

app = Flask(__name__)
CORS(app)

# 数据库初始化
client = None
db = None

def init_db():
    global client, db
    try:
        # 连接到 MongoDB
        client = MongoClient('mongodb://localhost:27017/', serverSelectionTimeoutMS=5000)
        client.admin.command('ping')  # 测试连接

        # 访问数据库
        db = client['mydatabase']
        print("数据库连接成功")
    except errors.ServerSelectionTimeoutError as err:
        print("连接服务器失败:", err)
        client = None
        db = None

# 在应用启动时初始化数据库连接
init_db()

@app.route('/add_tasks', methods=['POST'])
def add_tasks():
    print("访问 /add_tasks")
    if db is None:
        return jsonify({'status': 'error', 'message': '数据库未连接'}), 500

    data = request.get_json()
    if not data:
        return jsonify({'status': 'error', 'message': '无效的数据'}), 400

    date = data.get('date')
    tasks = data.get('tasks')
    password = data.get('password')

    if not date or not tasks or not password:
        return jsonify({'status': 'error', 'message': '缺少日期、任务或密码信息'}), 400

    if len(password) != 6 or not password.isdigit():
        return jsonify({'status': 'error', 'message': '密码必须是 6 位数字'}), 400

    try:
        # 将密码进行哈希处理
        password_hash = hashlib.sha256(password.encode()).hexdigest()

        # 将字符串日期转换为日期对象
        date_obj = datetime.strptime(date, '%Y-%m-%d')

        # 访问集合
        collection = db['plans']

        # 将任务转换为新格式，包含完成状态
        formatted_tasks = [{'content': task, 'completed': False} for task in tasks]

        # 查询是否存在相同日期和密码的文档
        existing_document = collection.find_one({'date': date_obj, 'password': password_hash})

        if existing_document:
            # 如果存在，追加新任务到现有任务列表中
            result = collection.update_one(
                {'_id': existing_document['_id']},
                {'$push': {'tasks': {'$each': formatted_tasks}}}
            )
            return jsonify({'status': 'success', 'message': '任务已追加到现有计划中'}), 200
        else:
            # 如果不存在，插入新的文档
            document = {
                'date': date_obj,
                'tasks': formatted_tasks,
                'password': password_hash
            }
            result = collection.insert_one(document)
            return jsonify({'status': 'success', 'inserted_id': str(result.inserted_id)}), 200

    except Exception as e:
        print("插入或更新数据时出错:", e)
        traceback.print_exc()
        return jsonify({'status': 'error', 'message': '插入或更新数据时出错'}), 500

@app.route('/get_all_tasks', methods=['POST'])
def get_all_tasks():
    print("访问 /get_all_tasks")
    if db is None:
        return jsonify({'status': 'error', 'message': '数据库未连接'}), 500

    data = request.get_json()
    if not data:
        return jsonify({'status': 'error', 'message': '无效的数据'}), 400

    password = data.get('password')

    if not password:
        return jsonify({'status': 'error', 'message': '缺少密码信息'}), 400

    if len(password) != 6 or not password.isdigit():
        return jsonify({'status': 'error', 'message': '密码必须是 6 位数字'}), 400

    try:
        # 将密码进行哈希处理
        password_hash = hashlib.sha256(password.encode()).hexdigest()

        # 查询 MongoDB，获取与密码匹配的所有文档
        collection = db['plans']
        documents = collection.find({'password': password_hash})

        tasks_by_date = {}

        for doc in documents:
            date_str = doc['date'].strftime('%Y-%m-%d')
            tasks = [
                task if isinstance(task, dict) else {'content': task, 'completed': False}
                for task in doc['tasks']
            ]
            
            if date_str in tasks_by_date:
                tasks_by_date[date_str].extend(tasks)
            else:
                tasks_by_date[date_str] = tasks

        if tasks_by_date:
            return jsonify({'status': 'success', 'tasksByDate': tasks_by_date}), 200
        else:
            return jsonify({'status': 'error', 'message': '没有找到与此密码关联的计划'}), 404

    except Exception as e:
        print("查询所有数据时出错:", e)
        traceback.print_exc()
        return jsonify({'status': 'error', 'message': '查询所有数据时出错'}), 500

@app.route('/delete_task', methods=['POST'])
def delete_task():
    print("访问 /delete_task")
    if db is None:
        return jsonify({'status': 'error', 'message': '数据库未连接'}), 500

    data = request.get_json()
    print("接收到的数据：", data)
    if not data:
        return jsonify({'status': 'error', 'message': '无效的数据'}), 400

    date_str = data.get('date')
    task_content = data.get('taskContent')
    password = data.get('password')

    if not date_str or not task_content or not password:
        return jsonify({'status': 'error', 'message': '缺少日期、任务内容或密码信息'}), 400

    if len(password) != 6 or not password.isdigit():
        return jsonify({'status': 'error', 'message': '密码必须是 6 位数字'}), 400

    try:
        date_obj = datetime.strptime(date_str, '%Y-%m-%d')
        password_hash = hashlib.sha256(password.encode()).hexdigest()

        collection = db['plans']

        # 修改删除操作以适应新的任务格式
        result = collection.update_one(
            {
                'date': date_obj,
                'password': password_hash,
            },
            {
                '$pull': {
                    'tasks': {
                        '$or': [
                            {'content': task_content},  # 新格式
                            {'$eq': task_content}       # 旧格式
                        ]
                    }
                }
            }
        )

        if result.modified_count > 0:
            return jsonify({'status': 'success', 'message': '任务已删除'}), 200
        else:
            return jsonify({'status': 'error', 'message': '任务未找到或删除失败'}), 404

    except Exception as e:
        print("删除任务时出错：", e)
        traceback.print_exc()
        return jsonify({'status': 'error', 'message': '删除任务时出错'}), 500

@app.route('/delete_date', methods=['POST'])
def delete_date():
    print("访问 /delete_date")
    if db is None:
        return jsonify({'status': 'error', 'message': '数据库未连接'}), 500

    data = request.get_json()
    if not data:
        return jsonify({'status': 'error', 'message': '无效的数据'}), 400

    date = data.get('date')
    password = data.get('password')

    if not date or not password:
        return jsonify({'status': 'error', 'message': '缺少日期或密码信息'}), 400

    if len(password) != 6 or not password.isdigit():
        return jsonify({'status': 'error', 'message': '密码必须是 6 位数字'}), 400

    try:
        password_hash = hashlib.sha256(password.encode()).hexdigest()
        date_obj = datetime.strptime(date, '%Y-%m-%d')

        collection = db['plans']

        # 删除匹配的文档
        result = collection.delete_one({'date': date_obj, 'password': password_hash})

        if result.deleted_count > 0:
            return jsonify({'status': 'success', 'message': '该日期的计划已删除'}), 200
        else:
            return jsonify({'status': 'error', 'message': '未找到匹配的计划'}), 404

    except Exception as e:
        print("删除日期计划时出错:", e)
        traceback.print_exc()
        return jsonify({'status': 'error', 'message': '删除日期计划时出错'}), 500

@app.route('/update_task_status', methods=['POST'])
def update_task_status():
    print("访问 /update_task_status")
    if db is None:
        return jsonify({'status': 'error', 'message': '数据库未连接'}), 500

    data = request.get_json()
    if not data:
        return jsonify({'status': 'error', 'message': '无效的数据'}), 400

    date_str = data.get('date')
    task_content = data.get('taskContent')
    is_completed = data.get('isCompleted')
    password = data.get('password')

    if not all([date_str, task_content, password]) or is_completed is None:
        return jsonify({'status': 'error', 'message': '缺少必要的信息'}), 400

    if len(password) != 6 or not password.isdigit():
        return jsonify({'status': 'error', 'message': '密码必须是 6 位数字'}), 400

    try:
        date_obj = datetime.strptime(date_str, '%Y-%m-%d')
        password_hash = hashlib.sha256(password.encode()).hexdigest()

        collection = db['plans']
        
        # 更新任务状态
        result = collection.update_one(
            {
                'date': date_obj,
                'password': password_hash,
                'tasks.content': task_content
            },
            {
                '$set': {
                    'tasks.$.completed': is_completed
                }
            }
        )

        if result.matched_count == 0:
            # 如果没有找到匹配的文档，可能是旧格式的任务
            result = collection.update_one(
                {
                    'date': date_obj,
                    'password': password_hash,
                    'tasks': task_content
                },
                {
                    '$set': {
                        'tasks.$': {'content': task_content, 'completed': is_completed}
                    }
                }
            )

        if result.modified_count > 0:
            return jsonify({'status': 'success', 'message': '任务状态已更新'}), 200
        else:
            return jsonify({'status': 'error', 'message': '任务未找到或状态更新失败'}), 404

    except Exception as e:
        print("更新任务状态时出错：", e)
        traceback.print_exc()
        return jsonify({'status': 'error', 'message': '更新任务状态时出错'}), 500

if __name__ == '__main__':
    app.run(debug=True, host='0.0.0.0', port=5002)File "C:\Users\Administrator\AppData\Local\Programs\Python\Python311\Lib\site-packages\pymongo\_csot.py", line 120, in csot_wrapper
    return func(self, *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\Administrator\AppData\Local\Programs\Python\Python311\Lib\site-packages\pymongo\synchronous\mongo_client.py", line 1830, in _retry_internal
    ).run()
      ^^^^^
  File "C:\Users\Administrator\AppData\Local\Programs\Python\Python311\Lib\site-packages\pymongo\synchronous\mongo_client.py", line 2554, in run
    return self._read() if self._is_read else self._write()
                                              ^^^^^^^^^^^^^
  File "C:\Users\Administrator\AppData\Local\Programs\Python\Python311\Lib\site-packages\pymongo\synchronous\mongo_client.py", line 2676, in _write
    return self._func(self._session, conn, self._retryable)  # type: ignore
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\Administrator\AppData\Local\Programs\Python\Python311\Lib\site-packages\pymongo\synchronous\collection.py", line 1067, in _update
    return self._update(
           ^^^^^^^^^^^^^
  File "C:\Users\Administrator\AppData\Local\Programs\Python\Python311\Lib\site-packages\pymongo\synchronous\collection.py", line 1029, in _update
    _check_write_command_response(result)
  File "C:\Users\Administrator\AppData\Local\Programs\Python\Python311\Lib\site-packages\pymongo\helpers_shared.py", line 285, in _check_write_command_response
    _raise_last_write_error(write_errors)
  File "C:\Users\Administrator\AppData\Local\Programs\Python\Python311\Lib\site-packages\pymongo\helpers_shared.py", line 256, in _raise_last_write_error
    raise WriteError(error.get("errmsg"), error.get("code"), error)
pymongo.errors.WriteError: unknown top level operator: $eq. If you have a field name that starts with a '$' symbol, consider using $getField or $setField., full error: {'index': 0, 'code': 2, 'errmsg': "unknown top level operator: $eq. If you have a field name that starts with a '$' symbol, consider using $getField or $setField."}