Pinia 不管理打印机硬件,仅负责打印状态的定义、响应式同步与共享;其核心作用是统一维护“是否连接”“是否打印中”“队列任务数”“最近错误”等上下文信息,为真实打印操作提供协调依据。

Pinia 本身不直接管理打印机队列或硬件连接——它只负责状态的定义、响应式同步与跨组件共享。打印机这类涉及底层系统交互的操作,必须由浏览器 API(如 window.print())、原生能力(如 Electron、Tauri、uni-app 原生插件)或后端服务配合完成。Pinia 的作用是:把“当前是否正在打印”“队列里有几项任务”“最近一次连接状态”等信息,统一存起来、响应式暴露、方便所有页面读写。
打印机相关状态适合用 Pinia 管理的典型场景
- 用户点击「添加到打印队列」后,多个页面(如文档列表页、预览页、设置页)需要实时显示剩余待打份数
- 打印失败时,全局弹出提示,且状态能被重试按钮读取(如“上次错误:设备离线”)
- 打印机连接状态(已连接 / 正在连接 / 连接失败)需在导航栏常驻显示
- 多个打印任务按顺序执行,需记录当前执行中任务 ID、历史完成记录
这些数据本身不操作硬件,但为硬件操作提供上下文和协调依据。
如何用 Pinia 定义打印机状态仓库
// src/stores/usePrinterStore.js
import { defineStore } from 'pinia'
import { ref, computed } from 'vue'
export const usePrinterStore = defineStore('printer', () => {
// ====== state:核心状态 ======
const isConnected = ref(false) // 是否已连接到打印机(由实际连接逻辑更新)
const isPrinting = ref(false) // 是否有任务正在执行
const queue = ref([]) // 打印任务队列,每项含 id、title、content、status
const lastError = ref('') // 最近一次错误信息,如 'No printer found'
// ====== getters:派生状态 ======
const pendingCount = computed(() => queue.value.filter(t => t.status === 'pending').length)
const history = computed(() => queue.value.filter(t => t.status !== 'pending'))
const canPrint = computed(() => isConnected.value && !isPrinting.value)
// ====== actions:可调用的方法(不执行硬件操作,只改状态) ======
const addTask = (task) => {
const id = Date.now().toString(36) + Math.random().toString(36).substr(2, 5)
queue.value.push({
id,
...task,
status: 'pending',
createdAt: new Date()
})
}
const startPrint = (id) => {
const task = queue.value.find(t => t.id === id)
if (task) {
task.status = 'printing'
isPrinting.value = true
}
}
const finishPrint = (id, success = true) => {
const task = queue.value.find(t => t.id === id)
if (task) {
task.status = success ? 'success' : 'failed'
task.finishedAt = new Date()
if (!success) lastError.value = task.error || 'Unknown error'
isPrinting.value = false
}
}
const clearQueue = () => {
queue.value = queue.value.filter(t => t.status === 'success')
}
const setConnection = (connected) => {
isConnected.value = connected
if (!connected) lastError.value = 'Printer disconnected'
}
return {
isConnected,
isPrinting,
queue,
lastError,
pendingCount,
history,
canPrint,
addTask,
startPrint,
finishPrint,
clearQueue,
setConnection
}
})✅ 注意:
startPrint和finishPrint只更新状态,真正的打印动作要由业务层触发,比如:// 在某个组件中 const printer = usePrinterStore() const doActualPrint = async () => { printer.startPrint(taskId) try { await window.print() // 或调用 electron.print(), uni.getConnectedPrinter() 等 printer.finishPrint(taskId, true) } catch (err) { printer.finishPrint(taskId, false) } }
与真实硬件对接的关键点
| 场景 | 推荐方式 | Pinia 协同方式 |
|---|---|---|
| Web 浏览器内打印 |
window.print()(仅触发当前页) |
用 isPrinting 控制按钮禁用,用 queue 记录意图 |
| 检测本地打印机(桌面应用) | Electron 的 webContents.print() + systemPreferences.getMediaAccessStatus('printer')
|
setConnection(true) 由 Electron 主进程通知渲染进程后调用 |
| 小程序/APP 打印(uni-app) |
uni.getConnectedPrinter() + uni.print()
|
在 onSuccess 回调中调用 printer.setConnection(true)
|
| 后台排队打印(B/S 架构) | 前端发请求 → 后端调用 CUPS/LPD/驱动 → 返回任务 ID |
addTask() 存入队列,后端通过 WebSocket 或轮询推送状态,前端 finishPrint() 更新 |
补充建议:让状态更可靠
-
持久化队列:安装
pinia-plugin-persistedstate,避免刷新后队列丢失 -
错误隔离:每个任务独立
error字段,不覆盖全局lastError,除非是连接级异常 -
防重复提交:
canPrintgetter 可直接绑定按钮:disabled="!canPrint" -
调试友好:在 DevTools 中查看
printerstore,所有状态一目了然
不复杂但容易忽略。



















