JavaScript 中 Date()
可以用來取得目前時間:
const now = new Date();
now.toLocaleString(); // 顯示像「2025/10/6 下午 10:00:00」
想讓使用者下載一個檔案,可用Blob
+URL.createObjectURL()
:
const data = { name: "Test" };
const blob = new Blob([JSON.stringify(data, null, 2)], { type: "application/json" });
const url = URL.createObjectURL(blob);
const a = document.createElement("a");
a.href = url;
a.download = "todo.json";
a.click();
URL.revokeObjectURL(url);
檔名:day26_todo_pro.html
<!DOCTYPE html>
<html lang="zh-Hant">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Day26 - To-Do List 專業版</title>
<style>
:root {
--bg-light: #f5f7fa;
--bg-dark: #1e1e1e;
--text-light: #333;
--text-dark: #f5f5f5;
--card-light: white;
--card-dark: #2c2c2c;
--primary: #4caf50;
--secondary: #2196f3;
}
body {
background-color: var(--bg-light);
color: var(--text-light);
font-family: "Poppins", sans-serif;
display: flex;
flex-direction: column;
align-items: center;
padding: 40px;
transition: 0.3s;
}
body.dark {
background-color: var(--bg-dark);
color: var(--text-dark);
}
h2 {
margin-bottom: 20px;
}
.controls {
display: flex;
justify-content: center;
align-items: center;
margin-bottom: 20px;
gap: 10px;
}
input {
padding: 10px;
width: 250px;
border: 1px solid #ccc;
border-radius: 8px;
}
button {
padding: 10px 15px;
border: none;
border-radius: 8px;
cursor: pointer;
transition: 0.3s;
color: white;
}
.add { background: var(--primary); }
.clear { background: crimson; }
.export { background: var(--secondary); }
ul {
list-style: none;
padding: 0;
width: 320px;
}
li {
background: var(--card-light);
border: 1px solid #ddd;
border-radius: 8px;
padding: 10px;
margin-bottom: 10px;
display: flex;
flex-direction: column;
transition: 0.3s;
}
body.dark li {
background: var(--card-dark);
}
.top-row {
display: flex;
justify-content: space-between;
align-items: center;
}
.done {
text-decoration: line-through;
opacity: 0.6;
}
.time {
font-size: 0.85em;
opacity: 0.7;
margin-top: 4px;
}
.actions span {
cursor: pointer;
color: red;
margin-left: 10px;
}
.theme {
margin-top: 20px;
background: none;
border: 2px solid var(--secondary);
color: var(--secondary);
padding: 8px 15px;
border-radius: 8px;
cursor: pointer;
transition: 0.3s;
}
.theme:hover {
background: var(--secondary);
color: white;
}
@media (max-width: 500px) {
ul { width: 90%; }
}
</style>
</head>
<body>
<h2>📝 To-Do List 專業版</h2>
<div class="controls">
<input type="text" id="taskInput" placeholder="輸入代辦事項...">
<button class="add" id="addBtn">新增</button>
<button class="clear" id="clearBtn">清除全部</button>
<button class="export" id="exportBtn">導出 JSON</button>
</div>
<ul id="taskList"></ul>
<button class="theme" id="themeBtn">切換主題</button>
<script>
const taskInput = document.getElementById("taskInput");
const addBtn = document.getElementById("addBtn");
const clearBtn = document.getElementById("clearBtn");
const exportBtn = document.getElementById("exportBtn");
const taskList = document.getElementById("taskList");
const themeBtn = document.getElementById("themeBtn");
let tasks = JSON.parse(localStorage.getItem("tasks")) || [];
let theme = localStorage.getItem("theme") || "light";
document.body.classList.toggle("dark", theme === "dark");
function renderTasks() {
taskList.innerHTML = "";
tasks.forEach((task, index) => {
const li = document.createElement("li");
li.innerHTML = `
<div class="top-row">
<span class="${task.done ? 'done' : ''}" onclick="toggleDone(${index})">${task.text}</span>
<div class="actions">
<span onclick="deleteTask(${index})">✖</span>
</div>
</div>
<div class="time">建立時間:${task.time}</div>
`;
taskList.appendChild(li);
});
}
function updateStorage() {
localStorage.setItem("tasks", JSON.stringify(tasks));
}
addBtn.addEventListener("click", () => {
const text = taskInput.value.trim();
if (text) {
const time = new Date().toLocaleString();
tasks.push({ text, done: false, time });
updateStorage();
renderTasks();
taskInput.value = "";
}
});
function toggleDone(index) {
tasks[index].done = !tasks[index].done;
updateStorage();
renderTasks();
}
function deleteTask(index) {
tasks.splice(index, 1);
updateStorage();
renderTasks();
}
clearBtn.addEventListener("click", () => {
if (confirm("確定要清除所有任務嗎?")) {
tasks = [];
updateStorage();
renderTasks();
}
});
exportBtn.addEventListener("click", () => {
const blob = new Blob([JSON.stringify(tasks, null, 2)], { type: "application/json" });
const url = URL.createObjectURL(blob);
const a = document.createElement("a");
a.href = url;
a.download = "todo_list.json";
a.click();
URL.revokeObjectURL(url);
});
themeBtn.addEventListener("click", () => {
document.body.classList.toggle("dark");
theme = document.body.classList.contains("dark") ? "dark" : "light";
localStorage.setItem("theme", theme);
});
renderTasks();
</script>
</body>
</html>