H1-H10 优化OCR实时体验闭环

这个提交包含在:
2026-05-09 11:48:57 +08:00
父节点 549bd81e30
当前提交 c26cf9b954
共修改 34 个文件,包含 1217 行新增和 184 行删除
+52
查看文件
@@ -0,0 +1,52 @@
const { canReceiveEvent, toClientEvent } = require("../services/events");
const HEARTBEAT_INTERVAL_MS = 25_000;
function writeSseEvent(raw, event) {
const clientEvent = toClientEvent(event);
if (!clientEvent) {
return;
}
raw.write(`id: ${clientEvent.id}\n`);
raw.write(`event: ${clientEvent.type}\n`);
raw.write(`data: ${JSON.stringify(clientEvent)}\n\n`);
}
async function eventsRoutes(fastify) {
fastify.get(
"/events",
{
preHandler: fastify.authenticate,
},
async (request, reply) => {
const canManageInvoice = fastify.hasPermission(request.employee, "invoice.manage");
reply.hijack();
reply.raw.writeHead(200, {
"content-type": "text/event-stream; charset=utf-8",
"cache-control": "no-cache, no-transform",
"connection": "keep-alive",
"x-accel-buffering": "no",
});
reply.raw.write(": connected\n\n");
const unsubscribe = fastify.appEvents.subscribe((event) => {
if (!canReceiveEvent(request.employee, event, { canManageInvoice })) {
return;
}
writeSseEvent(reply.raw, event);
});
const heartbeat = setInterval(() => {
reply.raw.write(": heartbeat\n\n");
}, HEARTBEAT_INTERVAL_MS);
request.raw.on("close", () => {
clearInterval(heartbeat);
unsubscribe();
});
},
);
}
module.exports = eventsRoutes;