refactor: web-to-pixso → web-to-ppt 全面改名
- 目录 web-to-pixso/ → web-to-ppt/ - 所有代码引用:PIXSO → WEB_TO_PPT, webToPixso → webToPPT - 数据格式:pixso-design-capture → web-to-ppt-capture - CSS 选择器:__web_to_pixso_ → __web_to_ppt_ - README 重写,移除 Pixso 相关描述 - docs/web-to-pixso-mapping.md → docs/web-to-ppt-mapping.md
This commit is contained in:
@@ -0,0 +1,142 @@
|
||||
const SETTINGS_KEY = 'webToPPTSettings';
|
||||
const DEFAULT_SETTINGS = { useProxy: false, concurrency: '8', captureMode: 'mixed', captureWidth: null };
|
||||
const MIN_CAPTURE_WIDTH = 320;
|
||||
const MAX_CAPTURE_WIDTH = 3840;
|
||||
|
||||
const captureWidthInput = document.getElementById('captureWidth');
|
||||
const exportBtn = document.getElementById('exportBtn');
|
||||
const btnText = document.getElementById('btnText');
|
||||
const status = document.getElementById('status');
|
||||
const statusText = document.getElementById('statusText');
|
||||
const progressFill = document.getElementById('progressFill');
|
||||
|
||||
function normalizeCaptureWidth(value, fallback = null) {
|
||||
const number = Number.parseInt(String(value || '').replace(/\D+/g, ''), 10);
|
||||
if (!Number.isFinite(number)) return fallback;
|
||||
return Math.max(MIN_CAPTURE_WIDTH, Math.min(MAX_CAPTURE_WIDTH, number));
|
||||
}
|
||||
|
||||
function normalizeSettings(value = {}) {
|
||||
return {
|
||||
useProxy: Boolean(value.useProxy),
|
||||
captureMode: 'mixed',
|
||||
captureWidth: normalizeCaptureWidth(value.captureWidth, null)
|
||||
};
|
||||
}
|
||||
|
||||
async function getSettings() {
|
||||
const result = await chrome.storage.local.get({ [SETTINGS_KEY]: DEFAULT_SETTINGS });
|
||||
return normalizeSettings(result[SETTINGS_KEY]);
|
||||
}
|
||||
|
||||
async function getCurrentViewportWidth() {
|
||||
try {
|
||||
const [tab] = await chrome.tabs.query({ active: true, currentWindow: true });
|
||||
if (!tab?.id) return null;
|
||||
const [{ result }] = await chrome.scripting.executeScript({
|
||||
target: { tabId: tab.id },
|
||||
func: () => Math.round(window.innerWidth || document.documentElement.clientWidth || 0)
|
||||
});
|
||||
return normalizeCaptureWidth(result, null);
|
||||
} catch { return null; }
|
||||
}
|
||||
|
||||
function setProgress(percent, text) {
|
||||
status.hidden = false;
|
||||
progressFill.style.width = `${Math.max(0, Math.min(100, percent))}%`;
|
||||
statusText.textContent = text;
|
||||
}
|
||||
|
||||
function setBusy(isBusy) {
|
||||
exportBtn.disabled = isBusy;
|
||||
exportBtn.classList.toggle('loading', isBusy);
|
||||
exportBtn.classList.remove('success', 'error');
|
||||
btnText.textContent = isBusy ? '处理中...' : '导出 PPTX';
|
||||
}
|
||||
|
||||
function setResult(kind, text) {
|
||||
exportBtn.classList.remove('loading', 'success', 'error');
|
||||
exportBtn.classList.add(kind);
|
||||
btnText.textContent = text;
|
||||
}
|
||||
|
||||
async function exportPptx() {
|
||||
setBusy(true);
|
||||
setProgress(5, '准备采集...');
|
||||
|
||||
const captureWidth = normalizeCaptureWidth(captureWidthInput.value, null);
|
||||
const settings = { ...DEFAULT_SETTINGS, captureWidth };
|
||||
|
||||
try {
|
||||
// 1. 抓取 DOM
|
||||
setProgress(15, '正在采集页面...');
|
||||
const response = await chrome.runtime.sendMessage({
|
||||
type: 'WEB_TO_PPT_CAPTURE_START',
|
||||
options: settings
|
||||
});
|
||||
|
||||
if (!response || !response.ok) {
|
||||
throw new Error(response?.error || '采集失败');
|
||||
}
|
||||
|
||||
// 2. 获取 JSON 数据(从 background 返回的文件路径读取不了,直接从 background 拿数据)
|
||||
// 需要让 background 返回 JSON 数据而不是文件
|
||||
setProgress(40, '采集完成,正在转化...');
|
||||
|
||||
// background 已经下载了 JSON 文件,但我们需要数据来转化
|
||||
// 用另一个消息获取数据
|
||||
const dataResponse = await chrome.runtime.sendMessage({
|
||||
type: 'WEB_TO_PPT_GET_DATA'
|
||||
});
|
||||
|
||||
if (!dataResponse || !dataResponse.ok) {
|
||||
throw new Error(dataResponse?.error || '获取数据失败');
|
||||
}
|
||||
|
||||
const jsonData = dataResponse.data;
|
||||
|
||||
// 3. 转化
|
||||
setProgress(50, '正在生成 PPTX...');
|
||||
const schema = await WebToPPT.convertToPptx(jsonData, (msg) => {
|
||||
setProgress(50 + Math.min(40, Math.floor(Math.random() * 40)), msg);
|
||||
});
|
||||
|
||||
// 4. 生成 PPTX
|
||||
setProgress(90, '正在打包...');
|
||||
const blob = await WebToPPT.schemaToPptxBlob(schema);
|
||||
|
||||
// 5. 下载
|
||||
setProgress(95, '正在下载...');
|
||||
const url = URL.createObjectURL(blob);
|
||||
const title = jsonData.source?.title || 'webpage';
|
||||
const safeTitle = title.replace(/[\\/:*?"<>|]+/g, '-').replace(/\s+/g, '-').slice(0, 64) || 'webpage';
|
||||
const filename = `web-to-ppt/${safeTitle}-${Date.now()}.pptx`;
|
||||
|
||||
await chrome.downloads.download({ url, filename, saveAs: true });
|
||||
URL.revokeObjectURL(url);
|
||||
|
||||
setProgress(100, `已导出:${filename}`);
|
||||
setResult('success', '导出完成');
|
||||
setTimeout(() => window.close(), 1500);
|
||||
|
||||
} catch (error) {
|
||||
setProgress(0, error.message || String(error));
|
||||
setResult('error', '导出失败');
|
||||
setTimeout(() => {
|
||||
setBusy(false);
|
||||
status.hidden = true;
|
||||
progressFill.style.width = '0';
|
||||
}, 3000);
|
||||
}
|
||||
}
|
||||
|
||||
// 初始化
|
||||
document.addEventListener('DOMContentLoaded', async () => {
|
||||
const currentWidth = await getCurrentViewportWidth();
|
||||
captureWidthInput.value = String(currentWidth || '');
|
||||
});
|
||||
|
||||
exportBtn.addEventListener('click', exportPptx);
|
||||
captureWidthInput.addEventListener('input', () => {
|
||||
captureWidthInput.value = captureWidthInput.value.replace(/\D+/g, '');
|
||||
});
|
||||
Reference in New Issue
Block a user