更换使用wxt框架搭建testing tool
This commit is contained in:
@@ -0,0 +1,7 @@
|
||||
import Dexie from "dexie";
|
||||
|
||||
export const db = new Dexie("testImagesDb");
|
||||
|
||||
db.version(1).stores({
|
||||
images: '++id, created, source'
|
||||
});
|
||||
@@ -0,0 +1,7 @@
|
||||
/**
|
||||
* 判断当前是否处于 Chrome 插件环境
|
||||
* @returns {false|chrome.storage.LocalStorageArea}
|
||||
*/
|
||||
export const isExtension = () => {
|
||||
return typeof chrome !== 'undefined' && chrome.storage && chrome.storage.local;
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
// import rrwebPlayer from 'rrweb-player';
|
||||
|
||||
export const downloadHtml = (events) => {
|
||||
if (events.length === 0) return;
|
||||
|
||||
// 1. 构建 HTML 模板字符串
|
||||
// 我们将 events 数据直接注入到 <script> 标签中
|
||||
const htmlContent = `
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>RRWeb 录像回放</title>
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/rrweb-player@latest/dist/style.css" />
|
||||
</head>
|
||||
<body style="margin: 0; display: flex; justify-content: center; align-items: center; height: 100vh; background: #f0f2f5;">
|
||||
|
||||
<div id="player"></div>
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/rrweb-player@latest/dist/index.js"></script>
|
||||
|
||||
<script>
|
||||
/* 注入录制的数据 */
|
||||
const events = ${JSON.stringify(events)};
|
||||
|
||||
/* 初始化播放器 */
|
||||
new rrwebPlayer({
|
||||
target: document.getElementById('player'),
|
||||
props: {
|
||||
events: events,
|
||||
width: 1024, // 可以根据需要调整
|
||||
height: 576,
|
||||
autoPlay: true,
|
||||
showController: true,
|
||||
},
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
`;
|
||||
|
||||
// 2. 创建 Blob 并下载
|
||||
const blob = new Blob([htmlContent], {type: 'text/html'});
|
||||
const url = URL.createObjectURL(blob);
|
||||
const a = document.createElement('a');
|
||||
a.href = url;
|
||||
a.download = `replay-${Date.now()}.html`; // 保存为 .html 文件
|
||||
document.body.appendChild(a);
|
||||
a.click();
|
||||
document.body.removeChild(a);
|
||||
URL.revokeObjectURL(url);
|
||||
};
|
||||
@@ -0,0 +1,30 @@
|
||||
// 判断当前是否处于 Chrome 插件环境
|
||||
const isExtension = typeof chrome !== 'undefined' && chrome.storage && chrome.storage.local;
|
||||
|
||||
const storageAdapter = {
|
||||
// 获取数据
|
||||
get: async (key) => {
|
||||
if (isExtension) {
|
||||
const result = await chrome.storage.local.get([key]);
|
||||
return result[key];
|
||||
} else {
|
||||
const item = localStorage.getItem(key);
|
||||
try {
|
||||
return JSON.parse(item); // 保持与插件版一致的对象处理
|
||||
} catch {
|
||||
return item;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// 设置数据
|
||||
set: async (key, value) => {
|
||||
if (isExtension) {
|
||||
await chrome.storage.local.set({[key]: value});
|
||||
} else {
|
||||
localStorage.setItem(key, JSON.stringify(value));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export default storageAdapter;
|
||||
@@ -0,0 +1,69 @@
|
||||
export function formatDate(value, timezone = 'Asia/Shanghai') {
|
||||
return (new Intl.DateTimeFormat('zh-CN', {
|
||||
year: 'numeric',
|
||||
month: 'numeric',
|
||||
day: 'numeric',
|
||||
hour: 'numeric',
|
||||
minute: 'numeric',
|
||||
second: 'numeric',
|
||||
timeZone: timezone,
|
||||
})).format(value);
|
||||
}
|
||||
|
||||
export const TimezoneOptions = ({zones}) => {
|
||||
return (zones.map((zone) => (<option key={zone} value={zone}>{zone}</option>)));
|
||||
}
|
||||
|
||||
export const formatWithZone = (timestamp, zone = 'Asia/Shanghai', unit = 'milliseconds') => {
|
||||
try {
|
||||
const ms = unit === 'milliseconds' ? Number(timestamp) : Number(timestamp) * 1000;
|
||||
return new Intl.DateTimeFormat('zh-CN', {
|
||||
year: 'numeric',
|
||||
month: 'numeric',
|
||||
day: 'numeric',
|
||||
hour: 'numeric',
|
||||
minute: 'numeric',
|
||||
second: 'numeric',
|
||||
timeZone: zone,
|
||||
}).format(ms);
|
||||
} catch (e) {
|
||||
return '格式错误';
|
||||
}
|
||||
}
|
||||
|
||||
export const getTimeZoneOffset = (timeZone) => {
|
||||
const now = new Date();
|
||||
const utc = new Date(now.toLocaleString('en-US', {timeZone: 'UTC'}));
|
||||
const target = new Date(now.toLocaleString('en-US', {timeZone: timeZone}));
|
||||
return target.getTime() - utc.getTime();
|
||||
}
|
||||
|
||||
export const formatWithDate = (
|
||||
date,
|
||||
timeZone = Intl.DateTimeFormat().resolvedOptions().timeZone
|
||||
) => {
|
||||
try {
|
||||
// 创建日期对象
|
||||
const dateObj = new Date(date);
|
||||
|
||||
// 检查日期是否有效
|
||||
if (isNaN(dateObj.getTime())) {
|
||||
return '无效的日期';
|
||||
}
|
||||
|
||||
// 如果提供了时区,则需要特殊处理
|
||||
if (timeZone) {
|
||||
// 获取给定时区相对于UTC的时间差(毫秒)
|
||||
const utc = dateObj.getTime() + dateObj.getTimezoneOffset() * 60000;
|
||||
|
||||
// 计算目标时区相对于UTC的偏移量
|
||||
const targetOffset = getTimeZoneOffset(timeZone);
|
||||
|
||||
return utc + targetOffset;
|
||||
} else {
|
||||
return dateObj.getTime();
|
||||
}
|
||||
} catch (error) {
|
||||
return '日期转换错误: ' + error.message;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user