Initial commit

This commit is contained in:
2026-03-08 01:34:54 +08:00
commit 1f104f73c8
441 changed files with 64911 additions and 0 deletions

View File

@@ -0,0 +1,69 @@
import { dialog, BrowserWindow } from 'electron'
import path from 'path'
import fs from 'fs'
import log from 'electron-log'
export interface HtmlImportResult {
success: boolean
canceled?: boolean
error?: string
htmlPath?: string
htmlDir?: string
htmlFileName?: string
assetsDirName?: string
assetsFiles?: string[]
}
export const selectHtmlFile = async (win: BrowserWindow | null): Promise<HtmlImportResult> => {
if (!win) return { success: false, error: 'No window found' }
try {
const { filePaths, canceled } = await dialog.showOpenDialog(win, {
title: '选择 HTML 文件',
filters: [
{ name: 'HTML Files', extensions: ['html', 'htm'] }
],
properties: ['openFile']
})
if (canceled || filePaths.length === 0) {
return { success: false, canceled: true }
}
const htmlPath = filePaths[0]
const htmlDir = path.dirname(htmlPath)
const htmlFileName = path.basename(htmlPath, path.extname(htmlPath))
const assetsDirName = `${htmlFileName}_files`
const assetsDirPath = path.join(htmlDir, assetsDirName)
const assetsFiles: string[] = []
if (fs.existsSync(assetsDirPath)) {
const collectFiles = (dir: string, baseDir: string) => {
const entries = fs.readdirSync(dir, { withFileTypes: true })
for (const entry of entries) {
const fullPath = path.join(dir, entry.name)
if (entry.isDirectory()) {
collectFiles(fullPath, baseDir)
} else {
const relPath = path.relative(baseDir, fullPath)
assetsFiles.push(relPath)
}
}
}
collectFiles(assetsDirPath, assetsDirPath)
}
return {
success: true,
htmlPath,
htmlDir,
htmlFileName,
assetsDirName,
assetsFiles
}
} catch (error: any) {
log.error('Select HTML file failed:', error)
return { success: false, error: error.message }
}
}

View File

@@ -0,0 +1,46 @@
import { BrowserWindow } from 'electron';
/**
* 生成 PDF 的服务
* @param htmlContent 完整的 HTML 字符串
* @returns PDF 文件的二进制数据
*/
export async function generatePdf(htmlContent: string): Promise<Uint8Array> {
const printWin = new BrowserWindow({
show: false,
webPreferences: {
nodeIntegration: false,
contextIsolation: true,
sandbox: false, // 与 main.ts 保持一致,确保脚本执行权限
}
});
try {
await printWin.loadURL(`data:text/html;charset=utf-8,${encodeURIComponent(htmlContent)}`);
// 等待资源加载完成 (由 generatePrintHtml 注入的脚本控制)
await printWin.webContents.executeJavaScript(`
new Promise(resolve => {
const check = () => {
if (window.__PRINT_READY__) {
resolve();
} else {
setTimeout(check, 100);
}
}
check();
})
`);
const pdfData = await printWin.webContents.printToPDF({
printBackground: true,
pageSize: 'A4',
margins: { top: 0, bottom: 0, left: 0, right: 0 }
});
return pdfData;
} finally {
// 确保窗口被关闭,防止内存泄漏
printWin.close();
}
}