diff --git a/rollup.config.js b/rollup.config.js index b5848dd..5536cef 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -6,9 +6,9 @@ import livereload from 'rollup-plugin-livereload'; import serve from 'rollup-plugin-serve'; export default defineConfig({ - input: 'sidepanel/index.js', + input: 'sidepanel/js/index.js', output: { - file: 'dist/sidepanel.bundle.js', + file: 'dist/bundle.js', format: 'iife', }, plugins: [ @@ -17,20 +17,20 @@ export default defineConfig({ json(), livereload({ watch: ['dist', 'sidepanel'], - verbose: false + verbose: false, }), serve({ open: true, port: 8082, contentBase: ['.', 'sidepanel'], headers: { - 'Access-Control-Allow-Origin': '*' - } + 'Access-Control-Allow-Origin': '*', + }, }), ], watch: { include: ['sidepanel/**/*'], exclude: ['node_modules/**/*'], - clearScreen: false - } -}); \ No newline at end of file + clearScreen: false, + }, +}); diff --git a/sidepanel/index.html b/sidepanel/index.html index f980356..bed4405 100644 --- a/sidepanel/index.html +++ b/sidepanel/index.html @@ -5,111 +5,17 @@ 测试工具 - + -
- - + + +
- -
- -
-

时间戳工具

-
-

当前时间戳

-

- 1762873747965 - 毫秒 -

-
- - - - -
-
- - -
-

时间戳转日期时间

-
-
- - -
- -
- -
- -
- - -
-
-
- - -
-

日期时间转时间戳

-
-
- - -
- -
- -
- -
- - -
-
-
-
- - -
-

其他工具页面

-

这里可以放置其他工具的内容。

-
-
-
- - + diff --git a/sidepanel/js/index.js b/sidepanel/js/index.js new file mode 100644 index 0000000..f3936ce --- /dev/null +++ b/sidepanel/js/index.js @@ -0,0 +1,17 @@ +// 导入时间戳工具的初始化函数和事件处理 +import './timestamp.js'; + +// 导入页面切换功能 +import { switchPage } from '../utils/domUtils.js'; + +// 页面切换逻辑 +import { addEventListenerById } from '../utils/domUtils.js'; + +addEventListenerById('nav-timestamp-btn', 'click', () => { + switchPage('timestamp'); +}); + +// 计时器页面切换 +addEventListenerById('nav-other-tools-btn', 'click', () => { + switchPage('other-tools'); +}); \ No newline at end of file diff --git a/sidepanel/index.js b/sidepanel/js/timestamp.js similarity index 61% rename from sidepanel/index.js rename to sidepanel/js/timestamp.js index 56ad68a..692ba88 100644 --- a/sidepanel/index.js +++ b/sidepanel/js/timestamp.js @@ -1,32 +1,16 @@ -// document.getElementById('close').addEventListener('click', () => { -// window.parent.postMessage({ action: 'indexind' }, '*'); -// }); - -// sidepanel/index.js -import { switchPage } from './utils/domUtils.js'; -import { - initTimestampDisplay, - handleToggleUnit, - handleStopTimer, - handleStartTimer, - handleConvertTimestamp, +import { + initTimestampDisplay, + handleToggleUnit, + handleStopTimer, + handleStartTimer, + handleConvertTimestamp, handleConvertDateToTimestamp, handleCopyTimestamp, handleClosePanel, handleTimezoneResult, - handleTimezoneInput -} from './modules/eventHandlers.js'; -import { addEventListenerById } from './utils/domUtils.js'; - -// 页面切换逻辑 -addEventListenerById('nav-timestamp-btn', 'click', () => { - switchPage('timestamp'); -}); - -// 计时器页面切换 -addEventListenerById('nav-other-tools-btn', 'click', () => { - switchPage('other-tools'); -}); + handleTimezoneInput, +} from '../modules/eventHandlers.js'; +import { addEventListenerById } from '../utils/domUtils.js'; // 初始化时间戳显示 initTimestampDisplay(); @@ -46,6 +30,6 @@ addEventListenerById('copy-timestamp-btn', 'click', handleCopyTimestamp); // 绑定关闭面板按钮事件 addEventListenerById('close-panel-btn', 'click', handleClosePanel); // 绑定切换时区事件 -addEventListenerById('timezone-result', 'change', handleTimezoneResult) +addEventListenerById('timezone-result', 'change', handleTimezoneResult); // 绑定输入时区事件 -addEventListenerById('timezone-input', 'change', handleTimezoneInput) +addEventListenerById('timezone-input', 'change', handleTimezoneInput); diff --git a/sidepanel/modules/Router.js b/sidepanel/modules/Router.js new file mode 100644 index 0000000..63074bf --- /dev/null +++ b/sidepanel/modules/Router.js @@ -0,0 +1,229 @@ +import { + RouteUtils, + addClass, + removeClass, + hasClass, + getParamsUrl, + closure, + genKey, +} from '../utils/routeUtils.js'; +class Router { + constructor() { + // 路由表 + this.routes = {}; + // 路由跳转前执行 + this.beforeFun = null; + // 路由跳转后执行 + this.afterFun = null; + // 路由挂载点 + this.routerViewId = 'router-view'; + // 路由重定向hash + this.redirectRoute = null; + // 多级页面缓存 + this.stackPages = true; + // 路由遍历 + this.routerMap = []; + // 路由状态 + this.historyFlag = ''; + // 路由历史 + this.history = []; + // 动画名称 + this.animationName = 'fade'; + } + + init(config) { + this.routerMap = config ? config.routers : this.routerMap; + this.routerViewId = config ? config.routerViewId : this.routerViewId; + this.stackPages = config ? config.stackPages : this.stackPages; + + if (!this.routerMap.length) { + let selector = this.routerViewId + '.page'; + let pages = document.querySelectorAll(selector); + for (let i = 0; i < pages.length; i++) { + let page = pages[i]; + let hash = page.getAttribute('hash'); + let name = hash.substring(1); + this.routerMap.push({ + name: name, + path: hash, + callback: closure(name), + }); + } + } + + window.linkTo = (path) => { + console.log('path', path); + if (path.indexOf('?') !== -1) { + window.location.hash = path + '&key=' + genKey(); + } else { + window.location.hash = path + '?key=' + genKey(); + } + }; + + window.addEventListener( + 'load', + function (event) { + this.historyChange(event); + }, + false + ); + } + + /** + * 路由历史纪录变化 + * @param {*} event + */ + historyChange(event) { + const currentHash = getParamsUrl(); + const nameString = 'router-' + this.routerViewId + '-history'; + this.history = window.sessionStorage[nameString] + ? JSON.parse(window.sessionStorage[nameString]) + : []; + + let back = false, + refresh = false, + forward = false, + index = 0, + len = this.history.length; + + for (let i = 0; i < len; i++) { + let h = this.history[i]; + if (h.hash === currentHash.path && h.key === currentHash.query.key) { + index = i; + if (i === len - 1) { + refresh = true; + } else { + back = true; + } + break; + } else { + forward = true; + } + } + + if (back) { + this.historyFlag = 'back'; + this.history.length = index + 1; + } else if (refresh) { + this.historyFlag = 'refresh'; + } else { + this.historyFlag = 'forward'; + this.history.push({ + key: currentHash.query.key, + hash: currentHash.path, + query: currentHash.query, + }); + } + + console.log('historyFlag', this.historyFlag); + + if (!this.stackPages) { + this.historyFlag = 'forward'; + } + window.sessionStorage[nameString] = JSON.stringify(this.history); + this.urlChange(); + } + + changeView(currentHash) { + const pages = document.querySelectorAll('.page'); + const previousPage = document.querySelector('.' + this.routerViewId + ' .page.active'); + let currentPage = null; + let currentHash = null; + + for (let i = 0; i < pages.length; i++) { + let page = pages[i]; + let hash = page.getAttribute('hash'); + page.setAttribute('class', 'page'); + if (hash === currentHash.path) { + currentHash = hash; + currentPage = page; + } + } + + const enterName = 'enter-' + this.animationName; + const leaveName = 'leave-' + this.animationName; + + if (this.historyFlag === 'back') { + addClass(currentPage, 'current'); + if (previousPage) { + addClass(previousPage, leaveName); + } + + setTimeout(() => { + if (previousPage) { + removeClass(previousPage, leaveName); + } + }, 300); + } else if (this.historyFlag === 'forward' || this.historyFlag === 'refresh') { + if (previousPage) { + addClass(previousPage, leaveName); + } + addClass(currentPage, enterName); + setTimeout(() => { + if (previousPage) { + removeClass(previousPage, leaveName); + } + addClass(currentPage, enterName); + removeClass(currentPage, 'current'); + }, 300); + currentPage.scrollTop = 0; + this.routes[currentHash].callback ? this.routes[currentHash].callback() : null; + } + + this.afterFun ? this.afterFun(currentHash) : null; + } + + urlChange() { + const currentHash = getParamsUrl(); + if (this.routes[currentHash.path]) { + if (this.beforeFun) { + this.beforeFun({ + to: { + path: currentHash.path, + query: currentHash.query, + }, + next: () => { + this.changeView(currentHash); + }, + }); + } else { + this.changeView(currentHash); + } + } else { + location.hash = this.redirectRoute; + } + } + + map() { + for (let i = 0; i < this.routerMap.length; i++) { + let route = this.routerMap[i]; + if (route.name === 'redirect') { + this.redirectRoute = route.path; + } else { + this.redirectRoute = this.routerMap[0].path; + } + + let newPath = route.path; + let path = newPath.repalce(/\s+/g, ''); + this.routes[path] = { + callback: route.callback, + }; + } + } + + beforeEach(callback) { + if (Object.prototype.toString.call(callback) === '[object Function]') { + this.beforeFun = callback; + } else { + console.trace('beforeEach callback must be a function'); + } + } + + afterEach(callback) { + if (Object.prototype.toString.call(callback) === '[object Function]') { + this.afterFun = callback; + } else { + console.trace('afterEach callback must be a function'); + } + } +} diff --git a/sidepanel/modules/eventHandlers.js b/sidepanel/modules/eventHandlers.js index 9e8129c..1455e2d 100644 --- a/sidepanel/modules/eventHandlers.js +++ b/sidepanel/modules/eventHandlers.js @@ -227,12 +227,7 @@ export function handleCopyTimestamp() { copyTimestampBtn.textContent = '已复制'; copyTimestampBtn.style.fontWeight = 'bold'; - - // 添加闪烁动画效果 - copyTimestampBtn.style.transition = 'all 0.3s'; - copyTimestampBtn.style.transform = 'scale(1.02)'; setTimeout(() => { - copyTimestampBtn.style.transform = 'scale(1)'; copyTimestampBtn.textContent = '复制'; copyTimestampBtn.style.color = ''; copyTimestampBtn.style.fontWeight = ''; diff --git a/sidepanel/pages/timestamp.html b/sidepanel/pages/timestamp.html new file mode 100644 index 0000000..c4adf68 --- /dev/null +++ b/sidepanel/pages/timestamp.html @@ -0,0 +1,67 @@ +
+

时间戳工具

+
+

当前时间戳

+

+ 1762873747965 + 毫秒 +

+
+ + + + +
+
+ + +
+

时间戳转日期时间

+
+
+ + +
+ +
+ +
+ +
+ + +
+
+
+ + +
+

日期时间转时间戳

+
+
+ + +
+ +
+ +
+ +
+ + +
+
+
+
diff --git a/sidepanel/index.css b/sidepanel/style/style.css similarity index 100% rename from sidepanel/index.css rename to sidepanel/style/style.css diff --git a/sidepanel/utils/routeUtils.js b/sidepanel/utils/routeUtils.js new file mode 100644 index 0000000..23493bd --- /dev/null +++ b/sidepanel/utils/routeUtils.js @@ -0,0 +1,59 @@ +/** + * 获取路由的路径和详情参数 + * @returns + */ +export function getParamsUrl() { + let hasDetail = location.hash.split('?'); + let hasName = hasDetail[0].split('#')[1]; + let params = hasDetail[1] ? hasDetail[1].split('&') : []; + let query = {}; + + for (let i = 0; i < params.length; i++) { + let param = params[i].split('='); + query[param[0]] = param[1]; + } + + return { + path: hasName, + query: query, + params: params, + }; +} + +export function closure(name) { + function fun(currentHash) { + window.name&&window[name](currentHash) + } + return fun; +} + +export function genKey() { + let temp = 'xxxxxxxx'; + return temp.replace(/[xy]/g, function (c) { + let r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8); + return v.toString(16); + }); +} + +export function hasClass(elem, cls) { + cls = cls || ''; + if (cls.replace(/\s/g, '').length === 0) + return false; + return new RegExp(' ' + cls + ' ').test(' ' + elem.className + ' '); +} + +export function addClass(elem, cls) { + if (!hasClass(elem, cls)) { + elem.className = elem.className === '' ? cls : elem.className + ' ' + cls; + } +} + +export function removeClass(elem, cls) { + if (hasClass(elem, cls)) { + let newClass = ' ' + elem.className.replace(/[\t\r\n]/g, '') + ' '; + while (newClass.indexOf(' ' + cls + ' ') >= 0) { + newClass = newClass.replace(' ' + cls + ' ', ' '); + } + elem.className = newClass.replace(/^\s+|\s+$/) + } +} \ No newline at end of file