From 4a76561a8590ed5a2ece13ff558dd39f7ea59c92 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9B=A8=E9=9C=96=E9=93=83?= Date: Wed, 10 Dec 2025 22:16:10 +0800 Subject: [PATCH] =?UTF-8?q?feat(timestamp):=20=E9=87=8D=E6=9E=84=E6=97=B6?= =?UTF-8?q?=E9=97=B4=E6=88=B3=E6=A8=A1=E5=9D=97=E5=B9=B6=E4=BC=98=E5=8C=96?= =?UTF-8?q?=E6=97=B6=E5=8C=BA=E5=A4=84=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 将时区列表提取到独立常量文件 `timezone.js` 中,便于维护和扩展 - 重构时间戳显示逻辑,将初始化功能从事件处理器中分离 - 引入 timerManager、eventManager 和 scriptManager 进行资源统一管理 - 更新 DOM 操作方式,使用 window.eventManager 替代直接 addEventListener - 改进时间戳更新函数,支持传入元素引用以提高灵活性 - 在路由加载脚本时增加调试日志,方便追踪组件加载过程 - 移除冗余的 DOM 工具函数(如 getElementById),统一使用原生方法 - 修复计时器清理问题,确保通过 timerManager 正确清除定时任务 - 初始化时间戳和日期输入框默认值,提升用户体验 --- sidepanel/js/const/timezone.js | 20 ++++ sidepanel/js/index.js | 3 + sidepanel/js/timestamp.js | 119 ++++++++++++++++++----- sidepanel/modules/Router.js | 2 + sidepanel/modules/eventHandlers.js | 148 +++++++++++------------------ sidepanel/utils/domUtils.js | 71 +------------- sidepanel/utils/scriptManager.js | 4 +- sidepanel/utils/timerManager.js | 1 + sidepanel/utils/timestampUtils.js | 10 +- 9 files changed, 186 insertions(+), 192 deletions(-) create mode 100644 sidepanel/js/const/timezone.js diff --git a/sidepanel/js/const/timezone.js b/sidepanel/js/const/timezone.js new file mode 100644 index 0000000..64bcd55 --- /dev/null +++ b/sidepanel/js/const/timezone.js @@ -0,0 +1,20 @@ +export const timeZoneList = [ + 'America/New_York', + 'America/Chicago', + 'America/Denver', + 'America/Los_Angeles', + 'America/Anchorage', + 'America/Honolulu', + 'Europe/London', + 'Europe/Paris', + 'Europe/Berlin', + 'Europe/Moscow', + 'Asia/Tokyo', + 'Asia/Shanghai', + 'Asia/Hong_Kong', + 'Asia/Singapore', + 'Asia/Dubai', + 'Asia/Kolkata', + 'Australia/Sydney', + 'Pacific/Auckland', +]; diff --git a/sidepanel/js/index.js b/sidepanel/js/index.js index 1009ac5..dea687d 100644 --- a/sidepanel/js/index.js +++ b/sidepanel/js/index.js @@ -26,8 +26,11 @@ const config = { ], }; +// 注入脚本管理器 window.scriptManager = new ScriptManager(); +// 注入定时器管理器 window.timerManager = new TimerManager(); +// 注入事件管理器 window.eventManager = new EventManager(); const router = new Router(); diff --git a/sidepanel/js/timestamp.js b/sidepanel/js/timestamp.js index 70d6d5c..434a667 100644 --- a/sidepanel/js/timestamp.js +++ b/sidepanel/js/timestamp.js @@ -1,5 +1,4 @@ import { - initTimestampDisplay, handleToggleUnit, handleStopTimer, handleStartTimer, @@ -10,30 +9,100 @@ import { handleTimezoneResult, handleTimezoneInput, } from '../modules/eventHandlers.js'; +import { updateTimestamp } from '../utils/timestampUtils.js'; import { addEventListenerById } from '../utils/domUtils.js'; +import { timeZoneList } from './const/timezone.js'; -(function (global) { - global.timestampInit = async function () { - // 初始化时间戳显示 - initTimestampDisplay(); +// 定义一个全局变量来保存是否显示毫秒 +let showMilliseconds = true; +// 定义一个全局变量来保存计时器 +let timestampInterval; +// 获取本地时区 +const localTimeZone = new Intl.DateTimeFormat().resolvedOptions().timeZone; - // 绑定事件处理器 - // 绑定时间戳相关按钮事件 - addEventListenerById('toggle-unit-btn', 'click', handleToggleUnit); - // 绑定计时器相关按钮事件 - addEventListenerById('stop-timer-btn', 'click', handleStopTimer); - addEventListenerById('start-timer-btn', 'click', handleStartTimer); - // 绑定时间戳转换按钮事件 - addEventListenerById('convert-timestamp-to-date-btn', 'click', handleConvertTimestamp); - // 绑定日期转换按钮事件 - addEventListenerById('convert-date-to-timestamp-btn', 'click', handleConvertDateToTimestamp); - // 绑定复制时间戳按钮事件 - addEventListenerById('copy-timestamp-btn', 'click', handleCopyTimestamp); - // 绑定关闭面板按钮事件 - addEventListenerById('close-panel-btn', 'click', handleClosePanel); - // 绑定切换时区事件 - addEventListenerById('timezone-result', 'change', handleTimezoneResult); - // 绑定输入时区事件 - addEventListenerById('timezone-input', 'change', handleTimezoneInput); - }; -})(window); +/** + * 初始化时间戳显示 + */ +function initTimestampDisplay() { + const currentTimestampValue = document.getElementById('current-timestamp-value'); + + // 初始化时更新一次时间戳 + updateTimestamp(currentTimestampValue, showMilliseconds); + + // 添加时间戳定时器 + if (timestampInterval) { + console.log('clearInterval'); + clearInterval(timestampInterval); + window.timerManager.clearInterval(timestampInterval); + } + timestampInterval = setInterval( + () => updateTimestamp(currentTimestampValue, showMilliseconds), + 100 + ); + window.timerManager.setInterval(timestampInterval); + + initTimeZoneList(); + initTimestampAndDate(); +} + +/** + * 初始化时区列表 + */ +function initTimeZoneList() { + const timezoneResultSelect = document.getElementById('timezone-result'); + const timezoneInputSelect = document.getElementById('timezone-input'); + + // 获取本地时区在列表中的索引 + const localTimeZoneIndex = timeZoneList.indexOf(localTimeZone); + + for (let i = 0; i < timeZoneList.length; i++) { + if (i === localTimeZoneIndex) { + // 默认选中本地时区 + timezoneResultSelect.add(new Option(timeZoneList[i], i, true, true)); + timezoneInputSelect.add(new Option(timeZoneList[i], i, true, true)); + } else { + timezoneResultSelect.add(new Option(timeZoneList[i], i)); + timezoneInputSelect.add(new Option(timeZoneList[i], i)); + } + } +} + +/** + * 初始化时间戳和日期输入框 + */ +function initTimestampAndDate() { + const timestampInput = document.getElementById('timestamp-input'); + const dateInput = document.getElementById('datetime-input'); + + timestampInput.value = Date.now(); + dateInput.value = new Date().toLocaleString('sv-SE'); +} + +// 初始化时间戳显示 +initTimestampDisplay(); + +// 绑定时间戳相关按钮事件 +addEventListenerById( + 'toggle-unit-btn', + 'click', + () => (showMilliseconds = handleToggleUnit(showMilliseconds)) +); +// 绑定计时器相关按钮事件 +addEventListenerById('stop-timer-btn', 'click', () => handleStopTimer(timestampInterval)); +addEventListenerById( + 'start-timer-btn', + 'click', + () => (timestampInterval = handleStartTimer(timestampInterval, showMilliseconds)) +); +// 绑定时间戳转换按钮事件 +addEventListenerById('convert-timestamp-to-date-btn', 'click', handleConvertTimestamp); +// 绑定日期转换按钮事件 +addEventListenerById('convert-date-to-timestamp-btn', 'click', handleConvertDateToTimestamp); +// 绑定复制时间戳按钮事件 +addEventListenerById('copy-timestamp-btn', 'click', handleCopyTimestamp); +// 绑定关闭面板按钮事件 +addEventListenerById('close-panel-btn', 'click', handleClosePanel); +// 绑定切换时区事件 +addEventListenerById('timezone-result', 'change', handleTimezoneResult); +// 绑定输入时区事件 +addEventListenerById('timezone-input', 'change', handleTimezoneInput); diff --git a/sidepanel/modules/Router.js b/sidepanel/modules/Router.js index 68fed2f..d2a86c1 100644 --- a/sidepanel/modules/Router.js +++ b/sidepanel/modules/Router.js @@ -87,6 +87,7 @@ class Router { } } + console.log('当前组件:', route.script); if (route.script) { await this.scriptManager.loadScript({ path: route.script, @@ -96,6 +97,7 @@ class Router { }); } + console.log('当前组件:', route.name); await this.scriptManager.runInit(route.name); this.currentRoute = route; diff --git a/sidepanel/modules/eventHandlers.js b/sidepanel/modules/eventHandlers.js index 1455e2d..b18b6d0 100644 --- a/sidepanel/modules/eventHandlers.js +++ b/sidepanel/modules/eventHandlers.js @@ -3,85 +3,24 @@ import { convertTimestampToDate, convertDateToTimestamp, } from '../utils/timestampUtils.js'; -import { getElementById } from '../utils/domUtils.js'; -// 定义一个全局变量来保存是否显示毫秒 -let showMilliseconds = true; -// 定义一个全局变量来保存计时器 -let timestampInterval; -// 定义时区列表 -const timeZoneList = [ - 'America/New_York', - 'America/Chicago', - 'America/Denver', - 'America/Los_Angeles', - 'America/Anchorage', - 'America/Honolulu', - 'Europe/London', - 'Europe/Paris', - 'Europe/Berlin', - 'Europe/Moscow', - 'Asia/Tokyo', - 'Asia/Shanghai', - 'Asia/Hong_Kong', - 'Asia/Singapore', - 'Asia/Dubai', - 'Asia/Kolkata', - 'Australia/Sydney', - 'Pacific/Auckland', -]; -// 获取本地时区 -const localTimeZone = new Intl.DateTimeFormat().resolvedOptions().timeZone; - -/** - * 初始化时间戳显示 - */ -export function initTimestampDisplay() { - updateTimestamp(showMilliseconds); // 初始化时更新一次时间戳 - timestampInterval = setInterval(() => updateTimestamp(showMilliseconds), 100); - initTimeZoneList(); - initTimestampAndDate(); -} - -/** - * 初始化时区列表 - */ -export function initTimeZoneList() { - const timezoneResultSelect = getElementById('timezone-result'); - const timezoneInputSelect = getElementById('timezone-input'); - - // 获取本地时区在列表中的索引 - const localTimeZoneIndex = timeZoneList.indexOf(localTimeZone); - - for (let i = 0; i < timeZoneList.length; i++) { - if (i === localTimeZoneIndex) { - timezoneResultSelect.add(new Option(timeZoneList[i], i, true, true)); - timezoneInputSelect.add(new Option(timeZoneList[i], i, true, true)); - } else { - timezoneResultSelect.add(new Option(timeZoneList[i], i)); - timezoneInputSelect.add(new Option(timeZoneList[i], i)); - } - } -} - -export function initTimestampAndDate() { - const timestampInput = getElementById('timestamp-input'); - const dateInput = getElementById('datetime-input'); - - timestampInput.value = Date.now(); - dateInput.value = new Date().toLocaleString('sv-SE'); // 使用适合的格式 -} +import { timeZoneList } from '../js/const/timezone.js'; /** * 切换单位按钮事件处理器 */ -export function handleToggleUnit() { - const currentTimestampUnit = getElementById('current-timestamp-unit'); - const toggleUnitBtn = getElementById('toggle-unit-btn'); +export function handleToggleUnit(showMilliseconds) { + const currentTimestampUnit = document.getElementById('current-timestamp-unit'); + const toggleUnitBtn = document.getElementById('toggle-unit-btn'); + // 更新showMilliseconds showMilliseconds = !showMilliseconds; + + // 更新时间戳显示 currentTimestampUnit.textContent = showMilliseconds ? '毫秒' : '秒'; - updateTimestamp(showMilliseconds); + const currentTimestamp = document.getElementById('current-timestamp-value'); + const timestamp = Date.now(); + currentTimestamp.textContent = showMilliseconds ? timestamp : Math.floor(timestamp / 1000); // 添加闪烁动画效果 toggleUnitBtn.style.transition = 'all 0.3s'; @@ -89,15 +28,23 @@ export function handleToggleUnit() { setTimeout(() => { toggleUnitBtn.style.transform = 'scale(1)'; }, 300); + + // 返回更新的showMilliseconds + return showMilliseconds; } /** * 停止计时器事件处理器 */ -export function handleStopTimer() { - clearInterval(timestampInterval); - const stopTimestampBtn = getElementById('stop-timer-btn'); - const startTimestampBtn = getElementById('start-timer-btn'); +export function handleStopTimer(timestampInterval) { + console.log('停止计时器'); + if (timestampInterval) { + clearInterval(timestampInterval); + window.timerManager.clearInterval(timestampInterval); + } + + const stopTimestampBtn = document.getElementById('stop-timer-btn'); + const startTimestampBtn = document.getElementById('start-timer-btn'); stopTimestampBtn.style.display = 'none'; startTimestampBtn.style.display = 'inline-block'; } @@ -105,27 +52,40 @@ export function handleStopTimer() { /** * 开始计时器事件处理器 */ -export function handleStartTimer() { - const startTimestampBtn = getElementById('start-timer-btn'); - const stopTimestampBtn = getElementById('stop-timer-btn'); - timestampInterval = setInterval(() => updateTimestamp(showMilliseconds), 100); +export function handleStartTimer(timestampInterval, showMilliseconds) { + const startTimestampBtn = document.getElementById('start-timer-btn'); + const stopTimestampBtn = document.getElementById('stop-timer-btn'); + const currentTimestampValue = document.getElementById('current-timestamp-value'); + + // 添加计时器 + if (timestampInterval) { + window.timerManager.clearInterval(timestampInterval); + } + timestampInterval = setInterval( + () => updateTimestamp(currentTimestampValue, showMilliseconds), + 100 + ); + window.timerManager.setInterval(timestampInterval); + + // 切换按钮样式 startTimestampBtn.style.display = 'none'; stopTimestampBtn.style.display = 'inline-block'; + + return timestampInterval; } /** * 时间戳转换事件处理器 */ export function handleConvertTimestamp() { - const inputTimestamp = getElementById('timestamp-input'); - const timestampInputResult = getElementById('timestamp-conversion-result'); + const inputTimestamp = document.getElementById('timestamp-input'); + const timestampInputResult = document.getElementById('timestamp-conversion-result'); const timestampUnitSelect = document.querySelector( '#page-timestamp #timestamp-input-unit-select' ); - const timezoneResultSelect = getElementById('timezone-result'); // 获取时区选择器 + const timezoneResultSelect = document.getElementById('timezone-result'); // 获取时区选择器 const timestamp = inputTimestamp.value.trim(); - console.log('输入时间戳:', timestamp); if (!timestamp) { timestampInputResult.value = '请输入时间戳'; @@ -167,10 +127,10 @@ export function handleConvertTimestamp() { * 日期转换事件处理器 */ export function handleConvertDateToTimestamp() { - const inputDate = getElementById('datetime-input'); - const dateInputResult = getElementById('date-conversion-result'); + const inputDate = document.getElementById('datetime-input'); + const dateInputResult = document.getElementById('date-conversion-result'); const timestampUnitSelect = document.querySelector('#page-timestamp #date-result-unit-select'); - const timezoneInputSelect = getElementById('timezone-input'); // 获取时区选择器 + const timezoneInputSelect = document.getElementById('timezone-input'); // 获取时区选择器 const dateStr = inputDate.value.trim(); console.log('输入日期字符串:', dateStr); @@ -221,8 +181,8 @@ export function handleConvertDateToTimestamp() { */ export function handleCopyTimestamp() { // 获取时间戳文本 - const currentTimestamp = getElementById('current-timestamp-value'); - const copyTimestampBtn = getElementById('copy-timestamp-btn'); + const currentTimestamp = document.getElementById('current-timestamp-value'); + const copyTimestampBtn = document.getElementById('copy-timestamp-btn'); const timestampText = currentTimestamp.textContent; copyTimestampBtn.textContent = '已复制'; @@ -259,12 +219,12 @@ export function handleClosePanel() { * 时间区域选择事件处理器 */ export function handleTimezoneResult() { - const timezoneResult = getElementById('timezone-result'); + const timezoneResult = document.getElementById('timezone-result'); console.log(timeZoneList[timezoneResult.value]); // 获取当前时间戳输入框的值 - const inputTimestamp = getElementById('timestamp-input').value.trim(); - const timestampInputResult = getElementById('timestamp-conversion-result'); + const inputTimestamp = document.getElementById('timestamp-input').value.trim(); + const timestampInputResult = document.getElementById('timestamp-conversion-result'); const timestampUnitSelect = document.querySelector( '#page-timestamp #timestamp-input-unit-select' ); @@ -283,13 +243,13 @@ export function handleTimezoneResult() { * 该函数获取时区输入元素的值,并在控制台输出对应的时区信息 */ export function handleTimezoneInput() { - const timezoneInput = getElementById('timezone-input'); + const timezoneInput = document.getElementById('timezone-input'); const selectedTimezone = timeZoneList[timezoneInput.value]; console.log('选择的时区:', selectedTimezone); // 获取当前日期输入框的值 - const inputDate = getElementById('datetime-input').value.trim(); - const dateInputResult = getElementById('date-conversion-result'); + const inputDate = document.getElementById('datetime-input').value.trim(); + const dateInputResult = document.getElementById('date-conversion-result'); const timestampUnitSelect = document.querySelector('#page-timestamp #date-result-unit-select'); // 如果有输入日期,则重新计算结果 diff --git a/sidepanel/utils/domUtils.js b/sidepanel/utils/domUtils.js index 5e9894c..86c99f8 100644 --- a/sidepanel/utils/domUtils.js +++ b/sidepanel/utils/domUtils.js @@ -2,69 +2,6 @@ * DOM工具类函数 */ -/** - * 切换页面显示(带动画效果) - * @param {string} pageName - 页面名称 - */ -export function switchPage(pageName) { - // 先隐藏当前活跃页面(如果有) - const currentPage = document.querySelector('.page.active'); - if (currentPage) { - currentPage.classList.remove('active'); - - // 添加离开动画 - currentPage.style.opacity = '0'; - currentPage.style.transform = 'translateX(20px)'; - - // 等待动画完成后真正隐藏 - setTimeout(() => { - if (!currentPage.classList.contains('active')) { - currentPage.style.display = 'none'; - } - }, 300); - } - - // 移除所有导航按钮的 active 状态 - document.querySelectorAll('.nav-button').forEach((button) => { - button.classList.remove('active'); - }); - - // 显示目标页面 - const targetPage = document.getElementById(`page-${pageName}`); - if (targetPage) { - targetPage.style.display = 'block'; - - // 触发重排以确保display变化生效 - targetPage.offsetHeight; - - // 添加进入动画 - targetPage.style.opacity = '0'; - targetPage.style.transform = 'translateX(-20px)'; - - setTimeout(() => { - targetPage.classList.add('active'); - targetPage.style.opacity = '1'; - targetPage.style.transform = 'translateX(0)'; - }, 10); - } - - // 激活对应的导航按钮 - const navButton = - document.getElementById(`nav-${pageName}-btn`) || document.getElementById(`nav-${pageName}`); - if (navButton) { - navButton.classList.add('active'); - } -} - -/** - * 根据ID获取元素的便捷方法 - * @param {string} id - 元素ID - * @returns {HTMLElement} - DOM元素 - */ -export function getElementById(id) { - return document.getElementById(id); -} - /** * 为元素添加事件监听器 * @param {string} id - 元素ID @@ -72,9 +9,9 @@ export function getElementById(id) { * @param {Function} handler - 事件处理函数 */ export function addEventListenerById(id, event, handler) { - const element = getElementById(id); - if (element) { - element.addEventListener(event, handler); + const ele = document.getElementById(id); + if (ele) { + window.eventManager.add(ele, event, handler); } } @@ -136,4 +73,4 @@ export function removeClass(elem, cls) { // 过滤多余空格 elem.className = klass.trim().replace(/\s+/g, ' '); -} \ No newline at end of file +} diff --git a/sidepanel/utils/scriptManager.js b/sidepanel/utils/scriptManager.js index 2d7397d..a944465 100644 --- a/sidepanel/utils/scriptManager.js +++ b/sidepanel/utils/scriptManager.js @@ -6,7 +6,8 @@ export class ScriptManager { } async loadScript({ path, name, isModule = false, deps = [] }) { - // 卸载现脚本 + console.log('loadScript'); + console.log({ path, name, isModule, deps }) await this.unloadScript(); for (const dep of deps) { @@ -43,6 +44,7 @@ export class ScriptManager { } async unloadScript() { + console.log('unloadScript'); try { if (this.currentName && window[this.currentName]) { const mod = window[this.currentName]; diff --git a/sidepanel/utils/timerManager.js b/sidepanel/utils/timerManager.js index c0af2cc..802eb3d 100644 --- a/sidepanel/utils/timerManager.js +++ b/sidepanel/utils/timerManager.js @@ -25,6 +25,7 @@ export class TimerManager { * @returns */ setInterval(fn, delay, ...args) { + console.log('setInterval in TimerManager'); const id = window.setInterval(fn, delay, ...args); this.timers.push(id); return id; diff --git a/sidepanel/utils/timestampUtils.js b/sidepanel/utils/timestampUtils.js index ccb3052..f41b823 100644 --- a/sidepanel/utils/timestampUtils.js +++ b/sidepanel/utils/timestampUtils.js @@ -3,13 +3,13 @@ */ /** - * 更新时间戳 - * @param {boolean} showMilliseconds - 是否显示毫秒 + * 更新时间戳显示 + * @param {*} ele + * @param {*} showMilliseconds */ -export function updateTimestamp(showMilliseconds = true) { - const currentTimestamp = document.getElementById('current-timestamp-value'); +export function updateTimestamp(ele, showMilliseconds = true) { const timestamp = Date.now(); - currentTimestamp.textContent = showMilliseconds ? timestamp : Math.floor(timestamp / 1000); + ele.textContent = showMilliseconds ? timestamp : Math.floor(timestamp / 1000); } /**