最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Electron內(nèi)嵌網(wǎng)頁實現(xiàn)打印預(yù)覽功能的示例代碼

 更新時間:2025年06月13日 08:58:01   作者:依了個舊  
這篇文章主要介紹了Electron內(nèi)嵌網(wǎng)頁實現(xiàn)打印預(yù)覽功能的方式,文章通過代碼示例給大家講解的非常詳細(xì),對大家的學(xué)習(xí)或工作有一定的幫助,需要的朋友可以參考下

前言

目前在業(yè)務(wù)碰到一個需求,之前是一個網(wǎng)頁的應(yīng)用,現(xiàn)在要求把這個應(yīng)用內(nèi)嵌到Electron里面打包成一個安裝包,由于之前應(yīng)用內(nèi)涉及到大量的打印功能,且采用的都是window.print()的方式來實現(xiàn)的,這種方式在谷歌等現(xiàn)代瀏覽器上本身就能夠?qū)崿F(xiàn)預(yù)覽,雖然內(nèi)嵌到Electron后還是能成功打印,但是無法進行預(yù)覽,只會出現(xiàn)如下圖的系統(tǒng)頁面

所以希望在不調(diào)整之前系統(tǒng)的打印邏輯前提下,能夠?qū)崿F(xiàn)在Electron中進行打印預(yù)覽并成功打印,經(jīng)過摸索,得出了以下的解決方案:

1. 創(chuàng)建Electron應(yīng)用,內(nèi)嵌網(wǎng)頁

首先創(chuàng)建一個electron窗口,直接通過mainWindow.loadURL()方法嵌入線上應(yīng)用,這里便于演示,我采用加載本地靜態(tài)html的方式來實現(xiàn)

// main.js
const { app, BrowserWindow, ipcMain, screen } = require('electron');

let mainWindow; // 主窗口
let previewWindow; // 預(yù)覽窗口

function createWindow() {

    // 獲取主屏幕的尺寸
    const primaryDisplay = screen.getPrimaryDisplay()
    const { width, height } = primaryDisplay.workAreaSize

    mainWindow = new BrowserWindow({
        width: width,
        height: height,
        webPreferences: {
            nodeIntegration: true,
            contextIsolation: false
        }
    });


    // 作為演示,采用本地靜態(tài)文件
    mainWindow.loadFile('index.html')
    // 可通過以下方式內(nèi)嵌網(wǎng)頁
    //mainWindow.loadURL(`http://www.example.com`)

    // 打開開發(fā)者工具
    mainWindow.webContents.openDevTools();
}

app.whenReady().then(() => {
    createWindow();

    app.on('activate', function () {
        if (BrowserWindow.getAllWindows().length === 0) createWindow();
    });
});

// 退出
app.on('window-all-closed', function () {
    if (process.platform !== 'darwin') app.quit();
});

2. 攔截系統(tǒng)打印

這里通過重寫window.print()方法,攔截系統(tǒng)自帶的打印功能,自己來寫一個在electron內(nèi)用于實現(xiàn)打印預(yù)覽的頁面,需要獲取到需要打印的dom節(jié)點,同時為了保證樣式生效,我們這里同時把當(dāng)前頁面的所有style標(biāo)簽和link樣式文件都獲取到,一并傳給預(yù)覽頁面

<!-- index.html -->
<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8">
    <title>打印預(yù)覽示例</title>
    <style>
        .print-button {
            padding: 10px 20px;
            background-color: #4CAF50;
            color: white;
            border: none;
            border-radius: 4px;
            cursor: pointer;
        }
    </style>
</head>

<body>
    <h1>打印預(yù)覽示例</h1>
    <button class="print-button" onclick="showPreview()">打印預(yù)覽</button>
    <div id="printTable">
        打印內(nèi)容
    </div>

    <script>
        const { ipcRenderer } = require('electron');

        // 攔截默認(rèn)打印行為
        const originalPrint = window.print;
        window.print = function () {
            console.log('渲染進程攔截到打印請求');
            try {
                // 獲取要打印的內(nèi)容
                const printContent = document.getElementById("printTable").innerHTML

                // 獲取所有<style>標(biāo)簽
                const styleEles = Array.from(document.querySelectorAll('style'));
                let styleTags = [];
                styleEles.forEach((style, index) => {
                    styleTags.push({
                        id: style.id || `style-${index}`,
                        content: style.textContent,
                    });
                });

                // 獲取所有<link>標(biāo)簽中的樣式表
                const linkEles = Array.from(document.querySelectorAll('link[rel="stylesheet"]'));

                let linkTags = [];
                linkEles.forEach((link, index) => {
                    linkTags.push({
                        id: link.id || `stylesheet-${index}`,
                        href: link.href,
                    });
                });

                // 調(diào)用渲染進程中的預(yù)覽方法,并把打印內(nèi)容和樣式一起傳過去
                ipcRenderer.invoke('show-preview', {
                    printContent: printContent,
                    styleTags: styleTags,
                    linkTags: linkTags
                });
            } catch (error) {
                console.error('打印錯誤:', error);
            }
        };

        function showPreview() {
            window.print();
        }
    </script>
</body>

</html>

3. 加載打印預(yù)覽界面

獲取到要打印的內(nèi)容后,單獨開啟一個無邊框和菜單欄的窗口,窗口內(nèi)加載一個用于展示要打印內(nèi)容的靜態(tài)文件preview.html,在這個靜態(tài)文件里面處理需要展示的內(nèi)容和打印的邏輯

// main.js

// 創(chuàng)建預(yù)覽窗口
function createPreviewWindow(printData) {
    // 獲取主屏幕的尺寸
    const primaryDisplay = screen.getPrimaryDisplay()
    const { width, height } = primaryDisplay.workAreaSize

    previewWindow = new BrowserWindow({
        width: parseInt(width * 0.7),
        height: parseInt(height * 0.9),
        frame: false,
        autoHideMenuBar: true,
        webPreferences: {
            nodeIntegration: true,
            contextIsolation: false
        }
    });

    // 加載預(yù)覽頁面
    previewWindow.loadFile('preview.html');

    // 等待頁面加載完成后發(fā)送打印數(shù)據(jù)
    previewWindow.webContents.on('did-finish-load', () => {
        previewWindow.webContents.send('print-data', printData);
    });

    previewWindow.webContents.openDevTools()
}

// 處理打印預(yù)覽請求
ipcMain.handle('show-preview', async (event, printData) => {
    try {
        // 調(diào)用創(chuàng)建預(yù)覽窗口
        createPreviewWindow(printData);
        return { success: true };
    } catch (error) {
        console.error('預(yù)覽錯誤:', error);
        return { success: false, error: error.message };
    }
});

4. 預(yù)覽頁面的實現(xiàn)

預(yù)覽頁面可以自由編寫布局和樣式,主要邏輯是把需要打印的內(nèi)容和樣式加入到頁面中,同時加載本地可用的打印機和其他打印配置

<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8">
    <title>打印預(yù)覽</title>
    <style>
        body {
            margin: 0;
            padding: 0;
            display: flex;
            height: 100vh;
            overflow: hidden;
            background-color: #f0f0f0;
        }

        .main-container {
            display: flex;
            width: 100%;
            height: 100%;
        }

        .print-document {
            flex-grow: 1;
            display: flex;
            justify-content: center;
            align-items: center;
            padding: 20px;
            overflow-y: auto;
        }
        
        /* 這里不能缺少,用于打印的時候不把側(cè)邊欄也打印出來 */
        @media print {
            .print-sidebar {
                display: none;
            }
        }
    </style>
</head>

<body>
    <div class="main-container">
        <div id="print-container" class="print-document">

        </div>
        <div class="print-sidebar">
            <div class="sidebar-header">
                <h2>打印</h2>
            </div>
            <div class="print-section">
                <label>目標(biāo)打印機</label>
                <div class="select-wrapper">
                    <select id="printer"></select>
                </div>
            </div>
            <div class="print-section">
                <label>頁面</label>
                <div class="select-wrapper">
                    <select id="pageSize">
                        <option value="A4">全部</option>
                        <option value="A3">A3</option>
                        <option value="B5">B5</option>
                        <option value="letter">Letter</option>
                    </select>
                </div>
            </div>
            
             <!-- 其它你需要的配置項 -->
             
            <div class="sidebar-actions">
                <button class="print-button" onclick="print()">打印</button>
                <button class="cancel-button" onclick="closePreview()">取消</button>
            </div>
        </div>
    </div>

    <script>
        const { ipcRenderer } = require('electron');

        // 接收打印數(shù)據(jù)
        ipcRenderer.on('print-data', (event, data) => {

            if (data.printContent) {
                // 把要打印的內(nèi)容放到頁面上
                const printEle = document.getElementById('print-container')
                printEle.innerHTML = data.printContent
            }

            const head = document.head || document.getElementsByTagName('head')[0];

            // 如果有style標(biāo)簽,把style標(biāo)簽放到頁面中
            if (data.styleTags && data.styleTags.length > 0) {

                data.styleTags.forEach((style, index) => {
                    const styleElement = document.createElement('style');
                    styleElement.textContent = style.content;
                    head.appendChild(styleElement);
                });
            }

            // 如果有l(wèi)ink標(biāo)簽,添加link標(biāo)簽
            if (data.linkTags && data.linkTags.length > 0) {
                data.linkTags.forEach((link, index) => {
                    const linkElement = document.createElement('link');
                    linkElement.rel = 'stylesheet';
                    linkElement.type = 'text/css';
                    linkElement.href = link.href;
                    head.appendChild(linkElement);
                });
            }

            // 加載本機可用的打印機列表
            loadPrinters();
        });

        // 加載打印機列表
        async function loadPrinters() {
            try {
                const printers = await ipcRenderer.invoke('get-printers');
                const printerSelect = document.getElementById('printer');
                printerSelect.innerHTML = '';
                printers.forEach(printer => {
                    const option = document.createElement('option');
                    option.value = printer.name;
                    option.textContent = printer.name;
                    printerSelect.appendChild(option);
                });
            } catch (error) {
                console.error('加載打印機列表失敗:', error);
            }
        }

        // 打印功能
        async function print() {
            try {
                const options = {
                    deviceName: document.getElementById('printer').value,
                    pageSize: document.getElementById('pageSize').value,
                    landscape: document.getElementById('orientation').value === 'landscape',
                    color: document.getElementById('color').value === 'true',
                    printBackground: true,
                    marginType: 'printableArea'
                };

                // 調(diào)用主線程的打印功能
                await ipcRenderer.invoke('do-print', options);

            } catch (error) {
                alert('打印錯誤:' + error.message);
            }
        }

        // 關(guān)閉預(yù)覽窗口
        function closePreview() {
            ipcRenderer.invoke('close-preview');
        }

        // 初始加載打印機
        document.addEventListener('DOMContentLoaded', () => {
            loadPrinters();
        });
    </script>
</body>

</html>

以下是獲取打印機列表和執(zhí)行打印的邏輯

// main.js

// 獲取打印機列表
ipcMain.handle('get-printers', async () => {
    try {
        const printers = await mainWindow.webContents.getPrintersAsync();
        return printers;
    } catch (error) {
        console.error('獲取打印機列表失敗:', error);
        return [];
    }
});

// 處理實際打印請求
ipcMain.handle('do-print', async (event, options) => {
    try {
        const printOptions = {
            silent: true, //靜默打印
            printBackground: true,
            deviceName: options.deviceName || '',
            copies: options.copies || 1,
            pageSize: options.pageSize || 'A4',
            margins: {
                marginType: options.marginType || 'printableArea'
            },
            landscape: options.landscape || false,
            scale: options.scale || 1.0,
            color: options.color || true,
            headerFooter: options.headerFooter || false,
            pageRanges: options.pageRanges || '',
            collate: options.collate || true,
            duplex: options.duplex || 'none'
        };

        await previewWindow.webContents.print(printOptions);
    } catch (error) {
        console.error('打印錯誤:', error);
    }
});

通過以上方式就實現(xiàn)了不改變原來應(yīng)用調(diào)用window.print()的方式,實現(xiàn)打印預(yù)覽和打印的邏輯,具體業(yè)務(wù)中,可以把重寫window.print()這一段邏輯單獨寫成一個js文件,全局加載,如果希望保留原有的打印,可以判斷一下是否在electron的環(huán)境中,如果在electron的環(huán)境才進行方法覆蓋,這樣在就能保證無論是通過瀏覽器打開或者在electron打開,都可以完成對應(yīng)的預(yù)覽功能。

以上就是Electron內(nèi)嵌網(wǎng)頁實現(xiàn)打印預(yù)覽功能的示例代碼的詳細(xì)內(nèi)容,更多關(guān)于Electron內(nèi)嵌網(wǎng)頁打印預(yù)覽的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

最新評論

万载县| 宜黄县| 洛南县| 漯河市| 漯河市| 福海县| 乌拉特后旗| 信宜市| 库伦旗| 惠来县| 莫力| 茂名市| 高阳县| 波密县| 乐平市| 开江县| 高要市| 兴义市| 石家庄市| 柳州市| 上栗县| 临安市| 元氏县| 伊通| 博湖县| 吴桥县| 巴林左旗| 天台县| 偏关县| 武威市| 皋兰县| 霞浦县| 永年县| 吉首市| 建湖县| 宝应县| 托里县| 金湖县| 荥经县| 都兰县| 定陶县|