Electron实现简易番茄钟

哈喽,大家好!我是油柑,本次带来的是Electron实现简易番茄钟,包括倒计时结束铃声,切换主题,记录任务数等

代码:

1、index.html

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>油柑 番茄钟</title>
  <link rel="stylesheet" href="dark-theme.css" id="theme">
</head>
<body>
  <div class="container">
    <div class="timer">
      <h1 id="timer">00:00:00</h1>
      <select id="hours">
        <option value="1">1 小时</option>
        <option value="2">2 小时</option>
        <option value="3">3 小时</option>
        <option value="4">4 小时</option>
        <option value="5">5 小时</option>
      </select>
      <div class="buttons">
        <button id="start">开始</button>
        <button id="reset">重置</button>
        <button id="toggleTheme">切换主题</button>
      </div>
      <ul id="tasks">
      </ul>
      <div class="task-input">
        <input type="text" id="taskInput" placeholder="添加任务">
        <button id="addTask">添加</button>
      </div>
      <audio id="audio" src="bell.mp3"></audio>
    </div>
    <div class="statistics">
      <h2>统计</h2>
      <p>共完成多少任务: <span id="tomatoCount">0</span></p>
      <p>总共花费的时间: (hours): <span id="totalTime">0</span></p>
    </div>
  </div>
  <script src="app.js"></script>
</body>
</html>

2、main.js(入口文件)

// 我们需要导入两个electron模块
const { app, BrowserWindow } = require('electron')

// 创建一个createWindow()函数,用于将index.html加载到新BrowserWindow实例中
const createWindow = () => {
    const win = new BrowserWindow({
        width: 800,
        height: 600
    })

    let promise = win.loadFile('index.html');
}
// 调用这个createWindow()函数来打开你的窗口
app.whenReady().then(() => {
    createWindow()
})

3、app.js文件

let timer;
let maxTasks = 3;
let tomatoCount = 0;
let totalTime = 0;
let isDarkTheme = true;

document.getElementById('start').addEventListener('click', startTimer);
document.getElementById('reset').addEventListener('click', resetTimer);
document.getElementById('addTask').addEventListener('click', addTask);
document.getElementById('toggleTheme').addEventListener('click', toggleTheme);

function startTimer() {
  let hoursInput = document.getElementById('hours').value;
  let hours = parseInt(hoursInput);
  if (isNaN(hours) || hours <= 0) {
    alert("Please select a valid number of hours.");
    return;
  }
  let totalSeconds = hours * 60 * 60;
  startCountdown(totalSeconds);
}

function startCountdown(totalSeconds) {
  clearInterval(timer);
  timer = setInterval(function() {
    if (totalSeconds === 0) {
      clearInterval(timer);
      document.getElementById('timer').innerText = 'Time\'s up!';
      document.getElementById('audio').play();
      showNotification("Time's up!", "Your task is complete.");
      tomatoCount++;
      totalTime += parseInt(document.getElementById('hours').value);
      updateStatistics();
      return;
    }

    let hours = Math.floor(totalSeconds / 3600);
    let minutes = Math.floor((totalSeconds % 3600) / 60);
    let seconds = totalSeconds % 60;

    document.getElementById('timer').innerText = `${hours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`;


    if (totalSeconds === 300) {
      showNotification("5 minutes left", "Finish up your task!");
    }

    totalSeconds--;
  }, 1000);
}

function resetTimer() {
  clearInterval(timer);
  document.getElementById('timer').innerText = '00:00:00';
}

function addTask() {
  let taskInput = document.getElementById('taskInput').value.trim();
  if (taskInput === "") {
    alert("Please enter a task.");
    return;
  }
  let taskList = document.getElementById('tasks');
  if (taskList.children.length >= maxTasks) {
    alert("你只能添加三个任务");
    return;
  }
  let taskItem = document.createElement('li');
  taskItem.textContent = taskInput;
  taskList.appendChild(taskItem);
  let deleteButton = document.createElement('button');
  deleteButton.textContent = '删除';
  deleteButton.className = 'deleteTask';
  taskItem.appendChild(deleteButton);
  document.getElementById('taskInput').value = "";
}

document.addEventListener('click', function(event) {
  if (event.target.classList.contains('deleteTask')) {
    event.target.parentNode.remove();
  }
});

function showNotification(title, message) {
  if (!("Notification" in window)) {
    alert("This browser does not support desktop notification");
  } else if (Notification.permission === "granted") {
    new Notification(title, { body: message });
  } else if (Notification.permission !== "denied") {
    Notification.requestPermission().then(function (permission) {
      if (permission === "granted") {
        new Notification(title, { body: message });
      }
    });
  }
}

function updateStatistics() {
  document.getElementById('tomatoCount').innerText = tomatoCount;
  document.getElementById('totalTime').innerText = totalTime;
}

function toggleTheme() {
  const themeLink = document.getElementById('theme');
  if (isDarkTheme) {
    themeLink.href = 'light-theme.css';
    isDarkTheme = false;
  } else {
    themeLink.href = 'dark-theme.css';
    isDarkTheme = true;
  }
}

4、样式文件(两个)

body {
    font-family: Arial, sans-serif;
    background-color: #000;
    color: #fff;
    display: flex;
    justify-content: center;
    align-items: center;
    height: 100vh;
    margin: 0;
  }
  
  .container {
    max-width: 600px;
    padding: 20px;
    background-color: #333;
    border-radius: 10px;
    box-shadow: 0 0 10px rgba(0, 0, 0, 0.5);
    display: flex;
    justify-content: space-between;
  }
  
  .timer {
    text-align: center;
  }
  
  .timer img {
    margin-bottom: 20px;
  }
  
  .timer h1 {
    font-size: 3rem;
  }
  
  select {
    padding: 10px;
    margin: 10px;
    font-size: 1rem;
    border: none;
    border-radius: 5px;
    cursor: pointer;
  }
  
  .buttons {
    display: flex;
    justify-content: center;
    margin-bottom: 20px;
  }
  
  button {
    padding: 10px 20px;
    margin: 0 10px;
    font-size: 1rem;
    border: none;
    border-radius: 5px;
    cursor: pointer;
    background-color: #007bff;
    color: #fff;
    transition: background-color 0.3s ease;
  }
  
  button:hover {
    background-color: #0056b3;
  }
  
  ul {
    list-style-type: none;
    padding: 0;
    margin-bottom: 20px;
  }
  
  li {
    margin-bottom: 5px;
    display: flex;
    align-items: center;
  }
  
  .deleteTask {
    margin-left: auto;
  }
  
  .task-input {
    display: flex;
    justify-content: center;
    align-items: center;
  }
  
  .task-input input[type="text"] {
    flex: 1;
    padding: 10px;
    font-size: 1rem;
    border: 1px solid #ddd;
    border-radius: 5px 0 0 5px;
    border-right: none;
    background-color: #fff;
    color: #000;
  }
  
  .task-input button {
    padding: 10px 20px;
    font-size: 1rem;
    border: none;
    border-radius: 0 5px 5px 0;
    cursor: pointer;
    background-color: #007bff;
    color: #fff;
    transition: background-color 0.3s ease;
  }
  
  .task-input button:hover {
    background-color: #0056b3;
  }
  
  .statistics {
    flex: 1;
    padding: 20px;
  }
  
  .statistics h2 {
    font-size: 1.5rem;
    margin-bottom: 10px;
  }
  
  .statistics p {
    font-size: 1rem;
    margin-bottom: 5px;
  }
  
body {
    font-family: Arial, sans-serif;
    background-color: #fff;
    color: #000;
    display: flex;
    justify-content: center;
    align-items: center;
    height: 100vh;
    margin: 0;
  }
  
  .container {
    max-width: 600px;
    padding: 20px;
    background-color: #fff;
    border-radius: 10px;
    box-shadow: 0 0 10px rgba(0, 0, 0, 0.5);
    display: flex;
    justify-content: space-between;
  }
  
  .timer {
    text-align: center;
  }
  
  .timer img {
    margin-bottom: 20px;
  }
  
  .timer h1 {
    font-size: 3rem;
  }
  
  select {
    padding: 10px;
    margin: 10px;
    font-size: 1rem;
    border: none;
    border-radius: 5px;
    cursor: pointer;
  }
  
  .buttons {
    display: flex;
    justify-content: center;
    margin-bottom: 20px;
  }
  
  button {
    padding: 10px 20px;
    margin: 0 10px;
    font-size: 1rem;
    border: none;
    border-radius: 5px;
    cursor: pointer;
    background-color: #007bff;
    color: #fff;
    transition: background-color 0.3s ease;
  }
  
  button:hover {
    background-color: #0056b3;
  }
  
  ul {
    list-style-type: none;
    padding: 0;
    margin-bottom: 20px;
  }
  
  li {
    margin-bottom: 5px;
    display: flex;
    align-items: center;
  }
  
  .deleteTask {
    margin-left: auto;
  }
  
  .task-input {
    display: flex;
    justify-content: center;
    align-items: center;
  }
  
  .task-input input[type="text"] {
    flex: 1;
    padding: 10px;
    font-size: 1rem;
    border: 1px solid #ddd;
    border-radius: 5px 0 0 5px;
    border-right: none;
    background-color: #fff;
    color: #000;
  }
  
  .task-input button {
    padding: 10px 20px;
    font-size: 1rem;
    border: none;
    border-radius: 0 5px 5px 0;
    cursor: pointer;
    background-color: #007bff;
    color: #fff;
    transition: background-color 0.3s ease;
  }
  
  .task-input button:hover {
    background-color: #0056b3;
  }
  
  .statistics {
    flex: 1;
    padding: 20px;
  }
  
  .statistics h2 {
    font-size: 1.5rem;
    margin-bottom: 10px;
  }
  
  .statistics p {
    font-size: 1rem;
    margin-bottom: 5px;
  }
  

那么,本次分享就到这啦,我们下次再见!

代码下载地址:基于Electron实现简易番茄钟: 本次使用Electron实现简易番茄钟,包括倒计时结束铃声,切换主题,记录任务数等 (gitee.com)

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要在 Electron实现国际化,可以使用 Electron 提供的 i18n API。以下是实现步骤: 1. 在项目中创建一个 `locales` 文件夹,用于存放不同语言的翻译文件。 2. 在 `locales` 文件夹中创建一个 `en.json` 文件,用于存放英文翻译。 3. 在 `en.json` 文件中定义键值对,表示需要翻译的文本,如: ```json { "hello": "Hello!", "world": "World!" } ``` 4. 在 Electron 主进程中使用 `app.getPath('userData')` 获取用户数据存储路径,并在此路径下创建一个 `locales` 文件夹,用于存放用户选择的语言文件。 5. 在 Electron 渲染进程中使用 `electron.remote.app` 获取主进程实例,并使用 `app.getLocale()` 获取用户系统语言。 6. 使用 `electron.remote.require` 引入 `electron-i18n` 模块,并在 `index.html` 中使用 `data-i18n` 属性标记需要翻译的文本,如: ```html <h1 data-i18n="hello"></h1> <p data-i18n="world"></p> ``` 7. 在渲染进程中使用 `electron.remote.require('electron-i18n')` 加载翻译文件,并使用 `i18n.translator.translate()` 方法进行翻译,如: ```javascript const i18n = electron.remote.require('electron-i18n'); i18n.translator.loadLocale('en', `${app.getPath('userData')}/locales`); i18n.translator.translateDocument(document); ``` 这里使用 `loadLocale` 方法加载英文翻译文件,并使用 `translateDocument` 方法翻译整个页面。 8. 如果需要支持多语言切换,可以在渲染进程中监听 `select` 元素的 `change` 事件,并使用 `i18n.translator.setLocale()` 方法切换语言,如: ```javascript const select = document.querySelector('select'); select.addEventListener('change', () => { const locale = select.value; i18n.translator.setLocale(locale); }); ``` 这里使用 `setLocale` 方法切换语言。 以上就是在 Electron实现国际化的基本步骤。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值