实战:桌面资料管理工具

综合使用文件导入、IPC、状态反馈和 PDF 保存,完成一个简单的桌面资料管理工具。

🎯 实战目标

我们做一个小型资料管理工具:用户选择文本资料,页面显示资料列表和读取状态,并可以把当前资料导出为 PDF。示例不接入复杂后端,先把桌面端闭环跑通。


🧱 功能拆分

功能负责位置
页面按钮、列表和状态Vue 渲染进程
暴露 openFileexportReportpreload
打开文件、读取内容、保存 PDF主进程
应用窗口、错误处理和生命周期Electron 主进程

页面只关心“请求是否成功”,不直接接触文件路径和系统模块。


🛠 设计最小接口

electron/preload.js
const { contextBridge, ipcRenderer } = require('electron/renderer');

contextBridge.exposeInMainWorld('electronAPI', {
    openTextFile: () => ipcRenderer.invoke('file:open-text'),
    exportReport: (data) => ipcRenderer.invoke('report:export', data),
});

每个方法对应一个明确动作。主进程仍然要校验 data 的类型和长度,不能因为接口来自自己的页面就跳过检查。


🖥 Vue 页面状态

src/App.vue
<script setup>
import { ref } from 'vue';

const files = ref([]);
const status = ref('等待导入');

async function openFile() {
    status.value = '正在读取';

    try {
        const file = await window.electronAPI.openTextFile();

        if (!file) {
            status.value = '已取消';
            return;
        }

        files.value.push(file);
        status.value = '读取完成';
    } catch {
        status.value = '读取失败';
    }
}
</script>

<template>
    <main>
        <button type="button" @click="openFile">导入文本</button>
        <p>状态:{{ status }}</p>
        <ul>
            <li v-for="file in files" :key="file.name">
                {{ file.name }}
            </li>
        </ul>
    </main>
</template>

这里先关注状态变化,不加入复杂的列表编辑、数据库和权限模型。后续项目需要这些能力时,再逐步拆成独立模块。


📄 报告保存和交付检查

导出报告时,主进程负责生成 PDF,页面负责显示“导出中、成功或失败”。完成后按照下面的顺序检查:

  1. 用户取消选择时没有错误提示污染页面。
  2. 文件读取失败时,页面仍然可以继续导入其他文件。
  3. 报告内容来自当前资料,而不是写死的示例数据。
  4. 导出窗口在成功和失败后都会关闭。
  5. 打包后的应用仍然能找到 Vue 页面和报告资源。

🧾 项目总结

  • Vue 负责页面和状态,Electron 负责桌面能力。
  • preload 把系统能力整理成小接口。
  • 主进程校验参数并处理文件和 PDF。
  • 页面必须显示等待、取消、成功和失败状态。
  • 发布前要在打包应用中重新验证资源和文件流程。

❓ 知识问答

Q1:为什么不让 Vue 直接读取文件?

A:这样会破坏进程边界和安全配置。通过 preload 暴露接口,权限更容易控制。

Q2:为什么实战不一开始就接数据库?

A:本课程先练习 Electron 的核心闭环,数据库会增加额外概念,初学者应先掌握文件导入和状态反馈。

🧪 小练习

为列表中的每项增加“导出”按钮,并调用预留的 exportReport 接口:

<button type="button">
    <!-- 请在这里编写代码 -->
</button>

🎉 恭喜你完成了一个从文件导入到报告保存的桌面应用基础闭环!