Initial commit
This commit is contained in:
69
electron/services/htmlImport.ts
Normal file
69
electron/services/htmlImport.ts
Normal 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 }
|
||||
}
|
||||
}
|
||||
46
electron/services/pdfGenerator.ts
Normal file
46
electron/services/pdfGenerator.ts
Normal 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();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user