diff --git a/src/background.js b/src/background.js
index 5f9aade..4d6a674 100644
--- a/src/background.js
+++ b/src/background.js
@@ -20,4 +20,6 @@ chrome.runtime.onMessage.addListener(function (message, sender, sendResponse) {
chrome.contextMenus.update(titleId, {
"title": convertStr,
});
-});
\ No newline at end of file
+});
+// 此文件在 Manifest V3 中不再需要,因为功能已移至 service-worker.js
+// 保留此文件以保持向后兼容性,但内容已清空
diff --git a/src/content.js b/src/content.js
index 7b32555..13fad46 100644
--- a/src/content.js
+++ b/src/content.js
@@ -1,5 +1,5 @@
/**
- * 发送消息到 background.js
+ * 发送消息到 service worker
*/
window.onmouseup = function () {
let selection = window.getSelection();
@@ -8,4 +8,11 @@ window.onmouseup = function () {
} else {
chrome.runtime.sendMessage("");
}
-}
\ No newline at end of file
+}
+
+// 监听来自service worker的消息
+chrome.runtime.onMessage.addListener(function (request, sender, sendResponse) {
+ if (request.action === "showAlert") {
+ alert(request.message);
+ }
+});
\ No newline at end of file
diff --git a/src/manifest.json b/src/manifest.json
index f28bec5..2b45fdc 100644
--- a/src/manifest.json
+++ b/src/manifest.json
@@ -1,10 +1,11 @@
{
- "browser_action": {
+ "manifest_version": 3,
+ "name": "时间戳转化",
+ "version": "1.0.3",
+ "description": "时间戳转换小工具。右键菜单显示转化,工具页时间戳转化",
+ "action": {
"default_popup": "popup.html"
},
- "description": "时间戳转换小工具。右键菜单显示转化,工具页时间戳转化",
- "manifest_version": 2,
- "name": "时间戳转化",
"content_scripts": [
{
"matches": [
@@ -16,15 +17,12 @@
}
],
"options_page": "popup.html",
- "version": "1.0.3",
"permissions": [
"clipboardRead",
- "contextMenus"
+ "contextMenus",
+ "storage"
],
"background": {
- "scripts": [
- "background.js",
- "utils.js"
- ]
+ "service_worker": "service-worker.js"
}
-}
+}
\ No newline at end of file
diff --git a/src/popup.html b/src/popup.html
index f41a1e9..0ee2fdb 100644
--- a/src/popup.html
+++ b/src/popup.html
@@ -77,14 +77,14 @@
- 时间戳位数判断:
+ 时间戳位数判断:
- 小提示:鼠标滚轮中键点击可以复制或者粘贴,年月日时分秒字符串的分隔符不限
+ 小提示:鼠标滚轮中键点击可以复制或者粘贴,年月日时分秒字符串的分隔符不限
diff --git a/src/scripts.js b/src/scripts.js
index 61c25ae..f63d72c 100644
--- a/src/scripts.js
+++ b/src/scripts.js
@@ -27,44 +27,79 @@ let only10Radio = document.getElementById("only-10-radio");
let only13Radio = document.getElementById("only-13-radio");
let both10_13 = document.getElementById("both-10-13-radio");
-
+/**
+ * 获取当前时间的13位时间戳
+ * @returns {number} 当前时间的13位时间戳
+ */
function getTimestamp13() {
return now.getTime();
}
+/**
+ * 刷新时间显示
+ */
function refresh() {
now = new Date();
timestampNowInput.value = getTimestamp13();
- bjTimeInput.value = getTimeString(getTimestamp13(), localStorage.timestampJudgeType);
+ bjTimeInput.value = getTimeString(getTimestamp13(), getTypeFromStorage());
+}
+
+/**
+ * 从存储中获取时间戳判断类型
+ */
+function getTypeFromStorage() {
+ // 默认返回 "3" (10/13位)
+ return localStorage.timestampJudgeType || "3";
}
+/**
+ * 刷新时间显示并重置定时器
+ */
function refreshWithInterval() {
window.clearInterval(interval);
refresh();
interval = getInterval();
}
+/**
+ * 执行转换操作
+ */
function change() {
let s = inputInput.value.trim().toString();
- resultInput.value = convert(s, localStorage.timestampJudgeType);
+ resultInput.value = convert(s, getTypeFromStorage());
}
+/**
+ * 从剪贴板粘贴内容
+ * @param item 要粘贴到的元素
+ */
function paste(item) {
item.select();
document.execCommand('paste');
msg("从剪切板获取!");
}
+/**
+ * 交换输入输出框的内容
+ */
function exchangeEachOther() {
sendStrToInput(resultInput.value);
}
+/**
+ * 复制内容到剪贴板
+ * @param item 要复制的元素
+ */
function copy(item) {
item.select();
document.execCommand('copy');
msg("已复制到剪切板");
}
+/**
+ * 显示消息并在1秒后清除
+ * @param m 要显示的消息
+ */
function msg(m) {
msgSpan.innerText = m;
setTimeout(function () {
@@ -72,6 +107,9 @@ function msg(m) {
}, 1000);
}
+/**
+ * 更新刷新间隔
+ */
function refreshGap() {
let value = gapInput.value;
if (!isNaN(value)) {
@@ -81,27 +119,36 @@ function refreshGap() {
}
}
+/**
+ * 设置输入框的值并执行转换
+ * @param text 要设置的文本
+ */
function sendStrToInput(text) {
inputInput.value = text;
change();
}
+// 绑定刷新按钮事件
refreshButton.onclick = function () {
refreshWithInterval();
};
+// 绑定转换按钮事件
changeButton.onclick = function () {
change();
};
+// 绑定输入框输入事件
inputInput.oninput = function () {
change();
};
+// 绑定刷新间隔输入框事件
gapInput.oninput = function () {
refreshGap();
};
+// 绑定刷新间隔输入框按键事件
gapInput.onkeypress = function (e) {
refreshGap();
@@ -110,60 +157,74 @@ gapInput.onkeypress = function (e) {
}
};
+// 绑定结果输入框输入事件
resultInput.oninput = function () {
let value = resultInput.value;
inputInput.value = formatTimeString(value);
};
+// 绑定输入框鼠标按下事件
inputInput.onmousedown = function (e) {
if (e.button === 1) {
paste(inputInput);
}
};
+// 绑定结果框鼠标按下事件
resultInput.onmousedown = function (e) {
if (e.button === 1) {
copy(resultInput);
}
};
+// 绑定时间戳输入框鼠标按下事件
timestampNowInput.onmousedown = function (e) {
if (e.button === 1) {
copy(timestampNowInput);
}
};
+// 绑定北京时间输入框鼠标按下事件
bjTimeInput.onmousedown = function (e) {
if (e.button === 1) {
copy(bjTimeInput);
}
};
+// 绑定"now"按钮点击事件
nowButton.onclick = function () {
sendStrToInput(new Date().getTime());
};
+// 绑定复制时间戳按钮事件
copyTimestampButton.onclick = function () {
copy(timestampNowInput);
};
+// 绑定复制时间按钮事件
copyTimeButton.onclick = function () {
copy(bjTimeInput);
};
+// 绑定粘贴按钮事件
pasteButton.onclick = function () {
paste(inputInput);
};
+// 绑定交换按钮事件
exchangeEachOtherButton.onclick = function () {
exchangeEachOther();
};
+// 绑定清空按钮事件
clearButton.onclick = function () {
resultInput.value = "";
inputInput.value = "";
};
+/**
+ * 更改自动刷新复选框状态
+ */
function changeGoCheckBox() {
goStatus = goonCheckBox.checked;
if (goStatus) {
@@ -172,12 +233,15 @@ function changeGoCheckBox() {
localStorage.goStatus = goStatus;
}
+// 绑定自动刷新复选框事件
goonCheckBox.onclick = changeGoCheckBox;
+// 绑定复制结果按钮事件
copyResultButton.onclick = function () {
copy(resultInput);
};
+// 绑定显示警告复选框事件
showAlertCheckbox.onclick = function () {
let checked = showAlertCheckbox.checked;
if (checked) {
@@ -187,18 +251,24 @@ showAlertCheckbox.onclick = function () {
}
};
+// 绑定仅10位时间戳单选框事件
only10Radio.onclick = function () {
localStorage.timestampJudgeType = "1";
};
+// 绑定仅13位时间戳单选框事件
only13Radio.onclick = function () {
localStorage.timestampJudgeType = "2";
};
+// 绑定10/13位时间戳单选框事件
both10_13.onclick = function () {
localStorage.timestampJudgeType = "3";
};
+/**
+ * 加载时间戳判断类型设置
+ */
function loadTimestampJudgeType() {
let timestampJudgeType = localStorage.timestampJudgeType;
switch (timestampJudgeType) {
@@ -217,16 +287,26 @@ function loadTimestampJudgeType() {
}
}
+/**
+ * 加载自动刷新状态
+ */
function loadGoonStatus() {
goStatus = !(localStorage.goStatus === "false");
goonCheckBox.checked = goStatus;
goonCheckBox.isChecked = goStatus;
}
+/**
+ * 加载菜单提醒操作设置
+ */
function loadMenuRadioAction() {
showAlertCheckbox.checked = !(localStorage.showAlert === "false");
}
+/**
+ * 获取定时器
+ * @returns {number} 定时器ID
+ */
function getInterval() {
return setInterval(function () {
if (goStatus) {
@@ -235,6 +315,7 @@ function getInterval() {
}, gap);
}
+// 初始化
refresh();
inputInput.focus();
@@ -242,9 +323,7 @@ inputInput.value = localStorage.selectText;
change();
loadGoonStatus();
-
loadMenuRadioAction();
-
loadTimestampJudgeType();
interval = getInterval();
\ No newline at end of file
diff --git a/src/service-worker.js b/src/service-worker.js
new file mode 100644
index 0000000..d841d71
--- /dev/null
+++ b/src/service-worker.js
@@ -0,0 +1,121 @@
+// 导入工具函数
+importScripts('utils.js');
+
+let titleId = "convert";
+
+chrome.contextMenus.create({
+ title: "时间戳转换",
+ id: titleId,
+ contexts: ["selection"]
+}, () => {
+ // 处理菜单创建可能的错误
+ if (chrome.runtime.lastError) {
+ console.error("创建上下文菜单时出错:", chrome.runtime.lastError.message);
+ }
+});
+
+// 监听菜单项点击事件
+chrome.contextMenus.onClicked.addListener((info, tab) => {
+ if (info.menuItemId === titleId) {
+ let selectionText = info.selectionText;
+
+ // 检查selectionText是否有效
+ if (!selectionText) {
+ console.warn("未找到选中的文本");
+ return;
+ }
+
+ // 获取设置
+ chrome.storage.local.get(['timestampJudgeType', 'showAlert'], function(result) {
+ // 处理可能的存储错误
+ if (chrome.runtime.lastError) {
+ console.error("读取存储时出错:", chrome.runtime.lastError.message);
+ return;
+ }
+
+ let timestampJudgeType = result.timestampJudgeType || "3";
+ let showAlert = result.showAlert !== "false";
+
+ try {
+ let convertStr = convert(selectionText, timestampJudgeType);
+
+ // 保存选中文本
+ chrome.storage.local.set({selectText: convertStr}, () => {
+ if (chrome.runtime.lastError) {
+ console.error("保存选中文本时出错:", chrome.runtime.lastError.message);
+ }
+ });
+
+ if (showAlert) {
+ // 通过 tabs.sendMessage 发送消息到内容脚本显示 alert
+ chrome.tabs.sendMessage(tab.id, {action: "showAlert", message: convertStr}, () => {
+ // 忽略发送消息可能的错误
+ if (chrome.runtime.lastError) {
+ console.warn("发送消息到内容脚本时出错:", chrome.runtime.lastError.message);
+ }
+ });
+ }
+ } catch (e) {
+ console.error("转换文本时出错:", e);
+ }
+ });
+ }
+});
+
+// 监听来自内容脚本的消息
+chrome.runtime.onMessage.addListener(function (message, sender, sendResponse) {
+ if (typeof message === 'string') {
+ // 获取设置
+ chrome.storage.local.get(['timestampJudgeType'], function(result) {
+ // 处理可能的存储错误
+ if (chrome.runtime.lastError) {
+ console.error("读取存储时出错:", chrome.runtime.lastError.message);
+ return;
+ }
+
+ let timestampJudgeType = result.timestampJudgeType || "3";
+ try {
+ let convertStr = convert(message, timestampJudgeType) + " ";
+ chrome.contextMenus.update(titleId, {
+ "title": convertStr,
+ }, () => {
+ if (chrome.runtime.lastError) {
+ console.error("更新上下文菜单时出错:", chrome.runtime.lastError.message);
+ }
+ });
+ } catch (e) {
+ console.error("转换文本时出错:", e);
+ }
+ });
+ return true;
+ } else if (message && message.action === "convert") {
+ // 检查消息完整性
+ if (!message.text) {
+ sendResponse({result: ""});
+ return false;
+ }
+
+ // 获取设置
+ chrome.storage.local.get(['timestampJudgeType'], function(result) {
+ // 处理可能的存储错误
+ if (chrome.runtime.lastError) {
+ console.error("读取存储时出错:", chrome.runtime.lastError.message);
+ sendResponse({result: "错误: 无法读取配置"});
+ return;
+ }
+
+ let timestampJudgeType = result.timestampJudgeType || "3";
+ try {
+ let convertStr = convert(message.text, timestampJudgeType);
+ sendResponse({result: convertStr});
+ } catch (e) {
+ console.error("转换文本时出错:", e);
+ sendResponse({result: "错误: 转换失败"});
+ }
+ });
+ return true; // 保持消息通道开放以进行异步响应
+ }
+
+ // 对于未处理的消息,直接返回false
+ return false;
+});
\ No newline at end of file
diff --git a/src/utils.js b/src/utils.js
index c16fe99..23335a5 100644
--- a/src/utils.js
+++ b/src/utils.js
@@ -1,10 +1,11 @@
/**
* 时间戳转字符串
- * @param timestamp 10/13 位时间戳
- * @param type 转换类型
+ * @param {number} timestamp - 10/13 位时间戳
+ * @param {string} type - 转换类型
* @returns {string} 可视化时间字符串
*/
function getTimeString(timestamp, type) {
+ // 根据类型调整时间戳
switch (type) {
case "1":
timestamp *= 1000;
@@ -19,79 +20,92 @@ function getTimeString(timestamp, type) {
break;
}
+ const date = new Date(timestamp);
+ const year = date.getFullYear();
+ const month = date.getMonth() + 1;
+ const day = date.getDate();
+ const hours = date.getHours();
+ const minutes = date.getMinutes();
+ const seconds = date.getSeconds();
+ const milliseconds = date.getMilliseconds();
- let date = new Date(timestamp);
- let year = date.getFullYear();
- let month = date.getMonth() + 1;
- let day = date.getDate();
- let hours = date.getHours();
- let minutes = date.getMinutes();
- let seconds = date.getSeconds();
- let milliseconds = date.getMilliseconds();
+ return formatDate(year, month, day, hours, minutes, seconds, milliseconds);
+}
- minutes = minutes < 10 ? "0" + minutes : minutes;
- seconds = seconds < 10 ? "0" + seconds : seconds;
- milliseconds = milliseconds < 100 ? milliseconds < 10 ? "00" + milliseconds : "0" + milliseconds : milliseconds;
+/**
+ * 格式化日期和时间
+ * @param {number} year - 年
+ * @param {number} month - 月
+ * @param {number} day - 日
+ * @param {number} hours - 时
+ * @param {number} minutes - 分
+ * @param {number} seconds - 秒
+ * @param {number} milliseconds - 毫秒
+ * @returns {string} 格式化后的日期时间字符串
+ */
+function formatDate(year, month, day, hours, minutes, seconds, milliseconds) {
+ const formattedMinutes = minutes < 10 ? `0${minutes}` : minutes;
+ const formattedSeconds = seconds < 10 ? `0${seconds}` : seconds;
+ const formattedMilliseconds = milliseconds < 100 ?
+ (milliseconds < 10 ? `00${milliseconds}` : `0${milliseconds}`) :
+ milliseconds;
- return year + "年" + month + "月" + day + "日 " + hours + ":" + minutes + ":" + seconds + "." + milliseconds;
+ return `${year}年${month}月${day}日 ${hours}:${formattedMinutes}:${formattedSeconds}.${formattedMilliseconds}`;
}
/**
* 字符串转 13 位时间戳
- * @param s 字符串
+ * @param {string} s - 字符串
* @returns {number} 13 位时间戳
*/
function formatTimeString(s) {
- // 替换非数字为 -
let value = s.replace(/[^\d]/g, "-").replace(/-+/g, "-");
- let res = "";
- // 以 - 分隔
- let split = value.split("-");
- // 组装字符串为 xx/xx/xx xx:xx:xx.xxx
- for (let i = 0; i < split.length; i++) {
- let item = split[i];
+
+ if (value.startsWith("-")) {
+ value = value.substring(1);
+ }
+ if (value.endsWith("-")) {
+ value = value.slice(0, -1);
+ }
+
+ let result = "";
+ const parts = value.split("-");
+ for (let i = 0; i < parts.length; i++) {
+ const part = parts[i];
if (i === 0) {
- // 第 1 位: 年
- res += item;
+ result += part; // 年
} else if (i <= 2) {
- // 2-3 位: 月日
- res += "/" + item;
+ result += `/${part}`; // 月日
} else if (i === 3) {
- // 第 4 位: 时
- res += " " + item;
+ result += ` ${part}`; // 时
} else if (i <= 5) {
- // 5-6 位: 分秒
- res += ":" + item;
+ result += `:${part}`; // 分秒
} else if (i === 6) {
- // 第 7 位: 毫秒
- res += "." + item;
+ result += `.${part}`; // 毫秒
}
}
- // 如果最后一位为小数点,那么应该是没有输入毫秒,去掉小数点
- if (res.endsWith(".")) {
- res = res.slice(0, value.length - 1);
+ if (result.endsWith(".")) {
+ result = result.slice(0, -1);
}
- let date = new Date(res);
+
+ const date = new Date(result);
return date.getTime();
}
/**
* 转换数字时间戳或者字符串
- * @param s 输入
- * @param type 转换类型
+ * @param {string|number} s - 输入
+ * @param {string} type - 转换类型
* @returns {string|number} 字符串或者数字时间戳
*/
function convert(s, type) {
- if (s == null) {
- return "";
- }
- if (s === "") {
+ if (s == null || s === "") {
return "";
}
if (s.indexOf(".") === -1 && !isNaN(s)) {
- return getTimeString(parseInt(s), type);
+ return getTimeString(parseInt(s, 10), type);
} else {
return formatTimeString(s);
}