代码 任务管理工具的HTML

2025-01-20 22:36:11 +0800 CST views 407

该文本描述了一个任务管理工具的HTML结构和功能,包括任务输入、进度条、任务列表、拖放功能以及导出链接的功能。工具使用了现代的CSS样式来创建一个科技感的界面,并通过JavaScript实现任务的添加、删除、标记完成和进度更新。所有任务数据存储在本地存储中,用户可以通过链接导出任务。


<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>任务管理工具</title>
    <style>
        /* 科技风背景和全局样式 */
        body {
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
            margin: 0;
            padding: 0;
            background: linear-gradient(135deg, #1e1e2f, #2a2a40);
            color: #e0e0e0;
            display: flex;
            justify-content: center;
            align-items: center;
            height: 100vh;
        }

        /* 任务管理容器 */
        .task-manager {
            position: relative;
            background: rgba(30, 30, 47, 0.8);
            box-shadow: 0 4px 15px rgba(0, 0, 0, 0.5);
            border-radius: 12px;
            width: 90%;
            max-width: 600px;
            max-height: 80vh;
            overflow-y: auto;
            border: 1px solid rgba(255, 255, 255, 0.1);
        }

        /* 进度条区域 */
        .progress {
            position: sticky;
            top: 0;
            background: rgba(30, 30, 47, 0.9);
            z-index: 10;
            padding: 15px;
            box-shadow: 0 2px 10px rgba(0, 0, 0, 0.3);
            text-align: center;
            border-bottom: 1px solid rgba(255, 255, 255, 0.1);
        }

        .progress-bar {
            height: 10px;
            width: 100%;
            background: rgba(255, 255, 255, 0.1);
            border-radius: 5px;
            margin-top: 10px;
            overflow: hidden;
        }

        .progress-bar span {
            display: block;
            height: 100%;
            background: linear-gradient(90deg, #00c6ff, #0072ff);
            border-radius: 5px;
            transition: width 0.3s ease;
        }

        /* 标题 */
        .task-manager h1 {
            font-size: 24px;
            color: #ffffff;
            margin: 20px 0 10px;
            text-align: center;
            text-shadow: 0 0 10px rgba(0, 194, 255, 0.7);
        }

        /* 任务输入区域 */
        .task-manager .task-input-container {
            display: flex;
            gap: 10px;
            padding: 15px;
            background: rgba(40, 40, 60, 0.8);
            border-bottom: 1px solid rgba(255, 255, 255, 0.1);
        }

        .task-manager input[type="text"] {
            flex: 1;
            padding: 10px;
            border: 1px solid rgba(255, 255, 255, 0.2);
            border-radius: 6px;
            font-size: 14px;
            outline: none;
            background: rgba(255, 255, 255, 0.1);
            color: #e0e0e0;
            transition: border-color 0.3s ease, box-shadow 0.3s ease;
        }

        .task-manager input[type="number"] {
            width: 100px;
            padding: 10px;
            border: 1px solid rgba(255, 255, 255, 0.2);
            border-radius: 6px;
            font-size: 14px;
            outline: none;
            background: rgba(255, 255, 255, 0.1);
            color: #e0e0e0;
            transition: border-color 0.3s ease, box-shadow 0.3s ease;
        }

        .task-manager input[type="text"]:focus,
        .task-manager input[type="number"]:focus {
            border-color: #00c6ff;
            box-shadow: 0 0 8px rgba(0, 198, 255, 0.6);
        }

        .task-manager button {
            padding: 10px 20px;
            background: linear-gradient(90deg, #00c6ff, #0072ff);
            color: white;
            border: none;
            border-radius: 6px;
            cursor: pointer;
            font-size: 14px;
            transition: transform 0.2s ease, box-shadow 0.2s ease;
        }

        .task-manager button:hover {
            transform: scale(1.05);
            box-shadow: 0 0 10px rgba(0, 198, 255, 0.8);
        }

        .task-manager button:active {
            transform: scale(0.95);
        }

        /* 任务列表 */
        .tasks {
            list-style: none;
            padding: 15px;
            margin: 0;
        }

        .tasks li {
            display: flex;
            justify-content: space-between;
            align-items: center;
            padding: 10px;
            border: 1px solid rgba(255, 255, 255, 0.1);
            border-radius: 6px;
            margin-bottom: 10px;
            background: rgba(40, 40, 60, 0.8);
            transition: background-color 0.3s ease, box-shadow 0.3s ease;
        }

        .tasks li:hover {
            background: rgba(50, 50, 70, 0.9);
            box-shadow: 0 0 10px rgba(0, 198, 255, 0.4);
        }

        .tasks li span {
            flex: 1;
            margin-right: 10px;
            word-break: break-word;
            font-size: 14px;
            color: #e0e0e0;
        }

        .tasks li.completed span {
            text-decoration: line-through;
            color: #888;
        }

        .tasks li div {
            display: flex;
            gap: 10px;
        }

        .tasks li button {
            padding: 5px 10px;
            font-size: 14px;
            width: 80px;
            border: none;
            border-radius: 4px;
            cursor: pointer;
            transition: transform 0.2s ease, box-shadow 0.2s ease;
        }

        .tasks li button:hover {
            transform: scale(1.05);
            box-shadow: 0 0 8px rgba(0, 198, 255, 0.6);
        }

        .tasks li button:active {
            transform: scale(0.95);
        }

        .tasks li .complete-btn {
            background: linear-gradient(90deg, #00d2ff, #3a7bd5);
            color: white;
        }

        .tasks li .delete-btn {
            background: linear-gradient(90deg, #ff416c, #ff4b2b);
            color: white;
        }

        /* 导出区域 */
        .export-container {
            padding: 15px;
            text-align: center;
            border-top: 1px solid rgba(255, 255, 255, 0.1);
        }

        .export-container button {
            margin: 5px;
        }
    </style>
</head>
<body>
<div class="task-manager">
    <div class="progress">
        <p id="progressText">任务进度:0%</p>
        <div class="progress-bar">
            <span id="progressBar" style="width: 0%;"></span>
        </div>
    </div>
    <h1>任务管理工具</h1>
    <div class="task-input-container">
        <input type="text" id="taskInput" placeholder="请输入任务名称">
        <input type="number" id="taskDuration" placeholder="预估时间(分钟)" min="0">
        <button onclick="addTask()">添加任务</button>
    </div>
    <ul class="tasks" id="taskList"></ul>
    <div class="export-container">
        <button onclick="exportTasks()">导出为链接</button>
        <button id="copyLinkButton" style="display: none;" onclick="copyLink()">复制链接</button>
    </div>
</div>
<script>
    const taskList = document.getElementById('taskList');
    const progressText = document.getElementById('progressText');
    const progressBar = document.getElementById('progressBar');
    const copyLinkButton = document.getElementById('copyLinkButton');

    let tasks = JSON.parse(localStorage.getItem('tasks')) || [];

    function addTask() {
        const taskInput = document.getElementById('taskInput');
        const taskDurationInput = document.getElementById('taskDuration');
        const taskName = taskInput.value.trim();
        const taskDuration = parseFloat(taskDurationInput.value.trim());

        if (taskName === '') {
            alert('任务名称不能为空!');
            return;
        }

        if (isNaN(taskDuration) || taskDuration < 0) {
            alert('预估时长必须是一个有效的非负数!');
            return;
        }

        tasks.push({ name: taskName, duration: taskDuration, completed: false });
        taskInput.value = '';
        taskDurationInput.value = '';
        saveTasks();
        renderTasks();
    }

    function toggleComplete(index) {
        tasks[index].completed = !tasks[index].completed;
        saveTasks();
        renderTasks();
    }

    function deleteTask(index) {
        tasks.splice(index, 1);
        saveTasks();
        renderTasks();
    }

    function saveTasks() {
        localStorage.setItem('tasks', JSON.stringify(tasks));
    }

    function renderTasks() {
        taskList.innerHTML = '';
        tasks.forEach((task, index) => {
            const taskItem = document.createElement('li');
            taskItem.className = task.completed ? 'completed' : '';
            taskItem.draggable = true;
            taskItem.dataset.index = index;
            taskItem.innerHTML = `
                    <span>${index + 1}. ${task.name} (预估时长: ${task.duration} 分钟)</span>
                    <div>
                        <button class="complete-btn" onclick="toggleComplete(${index})">
                            ${task.completed ? '撤销完成' : '标记完成'}
                        </button>
                        <button class="delete-btn" onclick="deleteTask(${index})">删除</button>
                    </div>
                `;

            taskItem.addEventListener('dragstart', handleDragStart);
            taskItem.addEventListener('dragover', handleDragOver);
            taskItem.addEventListener('drop', handleDrop);
            taskItem.addEventListener('dragend', handleDragEnd);

            taskList.appendChild(taskItem);
        });

        updateProgress();
    }

    function handleDragStart(event) {
        event.target.classList.add('dragging');
        event.dataTransfer.setData('text/plain', event.target.dataset.index);
    }

    function handleDragOver(event) {
        event.preventDefault();
        const draggingElement = document.querySelector('.dragging');
        const targetElement = event.target.closest('li');
        if (targetElement && targetElement !== draggingElement) {
            const targetIndex = parseInt(targetElement.dataset.index);
            const draggingIndex = parseInt(draggingElement.dataset.index);

            if (draggingIndex < targetIndex) {
                taskList.insertBefore(draggingElement, targetElement.nextSibling);
            } else {
                taskList.insertBefore(draggingElement, targetElement);
            }
        }
    }

    function handleDrop(event) {
        event.preventDefault();
        const draggingIndex = parseInt(event.dataTransfer.getData('text/plain'));
        const targetIndex = Array.from(taskList.children).indexOf(event.target.closest('li'));

        if (draggingIndex !== targetIndex) {
            const [draggedTask] = tasks.splice(draggingIndex, 1);
            tasks.splice(targetIndex, 0, draggedTask);
            saveTasks();
            renderTasks();
        }
    }

    function handleDragEnd(event) {
        event.target.classList.remove('dragging');
    }

    function updateProgress() {
        const totalTasks = tasks.length;
        const completedTasks = tasks.filter(task => task.completed).length;
        const progress = totalTasks === 0 ? 0 : Math.round((completedTasks / totalTasks) * 100);

        progressText.innerText = `任务进度:${progress}%`;
        progressBar.style.width = `${progress}%`;
    }

    function exportTasks() {
        const encodedTasks = btoa(encodeURIComponent(JSON.stringify(tasks)));
        const link = `${window.location.origin}${window.location.pathname}?tasks=${encodedTasks}`;
        navigator.clipboard.writeText(link).then(() => {
            alert('链接已复制到剪贴板!');
        });
    }

    function importTasksFromURL() {
        const urlParams = new URLSearchParams(window.location.search);
        const encodedTasks = urlParams.get('tasks');
        if (encodedTasks) {
            tasks = JSON.parse(decodeURIComponent(atob(encodedTasks)));
            saveTasks();
            renderTasks();
        }
    }

    importTasksFromURL();
    renderTasks();
</script>
</body>
</html>
复制全文 生成海报 Web开发 前端技术 任务管理工具

推荐文章

Vue3中如何实现状态管理?
2024-11-19 09:40:30 +0800 CST
pin.gl是基于WebRTC的屏幕共享工具
2024-11-19 06:38:05 +0800 CST
Web 端 Office 文件预览工具库
2024-11-18 22:19:16 +0800 CST
JavaScript设计模式:组合模式
2024-11-18 11:14:46 +0800 CST
mysql关于在使用中的解决方法
2024-11-18 10:18:16 +0800 CST
对多个数组或多维数组进行排序
2024-11-17 05:10:28 +0800 CST
ElasticSearch 结构
2024-11-18 10:05:24 +0800 CST
10个极其有用的前端库
2024-11-19 09:41:20 +0800 CST
从Go开发者的视角看Rust
2024-11-18 11:49:49 +0800 CST
mysql int bigint 自增索引范围
2024-11-18 07:29:12 +0800 CST
Vue 中如何处理跨组件通信?
2024-11-17 15:59:54 +0800 CST
Vue3中如何使用计算属性?
2024-11-18 10:18:12 +0800 CST
CSS 中的 `scrollbar-width` 属性
2024-11-19 01:32:55 +0800 CST
免费常用API接口分享
2024-11-19 09:25:07 +0800 CST
阿里云免sdk发送短信代码
2025-01-01 12:22:14 +0800 CST
15 个你应该了解的有用 CSS 属性
2024-11-18 15:24:50 +0800 CST
智慧加水系统
2024-11-19 06:33:36 +0800 CST
paint-board:趣味性艺术画板
2024-11-19 07:43:41 +0800 CST
Golang在整洁架构中优雅使用事务
2024-11-18 19:26:04 +0800 CST
程序员茄子在线接单