115 lines
3.7 KiB
TypeScript
115 lines
3.7 KiB
TypeScript
import { Hono } from 'hono';
|
|
import { parseTemplate } from '../engine/parser';
|
|
import { renderTemplate } from '../engine/render';
|
|
import { extractSchema } from '../engine/schema';
|
|
import { PrinterConnector } from '../printer/connector';
|
|
import type { Template } from '../types/template';
|
|
|
|
const templates = new Map<string, Template>();
|
|
let printerConnector: PrinterConnector | null = null;
|
|
|
|
function getPrinter(): PrinterConnector {
|
|
if (!printerConnector) {
|
|
const ip = process.env.PRINTER_IP || '192.168.1.100';
|
|
const port = parseInt(process.env.PRINTER_PORT || '9100');
|
|
printerConnector = new PrinterConnector({ ip, port });
|
|
}
|
|
return printerConnector;
|
|
}
|
|
|
|
const api = new Hono();
|
|
|
|
// 模板管理
|
|
api.get('/templates', (c) => {
|
|
const list = Array.from(templates.values()).map(t => ({
|
|
id: t.id,
|
|
name: t.name,
|
|
description: t.description,
|
|
}));
|
|
return c.json({ success: true, templates: list });
|
|
});
|
|
|
|
api.get('/templates/:id', (c) => {
|
|
const id = c.req.param('id');
|
|
const template = templates.get(id);
|
|
if (!template) {
|
|
return c.json({ success: false, error: { code: 'TEMPLATE_NOT_FOUND', message: `Template '${id}' not found` }}, 404);
|
|
}
|
|
return c.json({ success: true, template });
|
|
});
|
|
|
|
api.post('/templates', async (c) => {
|
|
const body = await c.req.json();
|
|
if (!body.id || !body.config) {
|
|
return c.json({ success: false, error: { code: 'INVALID_REQUEST', message: 'Missing id or config' }}, 400);
|
|
}
|
|
try {
|
|
const config = typeof body.config === 'string' ? parseTemplate(body.config) : body.config;
|
|
const template: Template = { ...config, id: body.id };
|
|
templates.set(body.id, template);
|
|
return c.json({ success: true, template: { id: template.id, name: template.name }}, 201);
|
|
} catch (error) {
|
|
return c.json({ success: false, error: { code: 'INVALID_TEMPLATE', message: String(error) }}, 400);
|
|
}
|
|
});
|
|
|
|
api.get('/templates/:id/schema', (c) => {
|
|
const id = c.req.param('id');
|
|
const template = templates.get(id);
|
|
if (!template) {
|
|
return c.json({ success: false, error: { code: 'TEMPLATE_NOT_FOUND', message: `Template '${id}' not found` }}, 404);
|
|
}
|
|
const { schema, example } = extractSchema(template);
|
|
return c.json({ success: true, templateId: id, schema, example });
|
|
});
|
|
|
|
// 打印
|
|
api.post('/print/:templateId', async (c) => {
|
|
const templateId = c.req.param('templateId');
|
|
const template = templates.get(templateId);
|
|
if (!template) {
|
|
return c.json({ success: false, error: { code: 'TEMPLATE_NOT_FOUND', message: `Template '${templateId}' not found` }}, 404);
|
|
}
|
|
const body = await c.req.json();
|
|
const { data = {} } = body;
|
|
try {
|
|
const escData = renderTemplate(template, data);
|
|
const printer = getPrinter();
|
|
const jobId = printer.queue(escData);
|
|
return c.json({ success: true, jobId, status: 'queued', estimatedTime: '5s' });
|
|
} catch (error) {
|
|
return c.json({ success: false, error: { code: 'RENDER_ERROR', message: String(error) }}, 500);
|
|
}
|
|
});
|
|
|
|
// 打印机状态
|
|
api.get('/printer/status', async (c) => {
|
|
const printer = getPrinter();
|
|
const status = await printer.getStatus();
|
|
return c.json({
|
|
success: true,
|
|
printer: {
|
|
ip: process.env.PRINTER_IP || '192.168.1.100',
|
|
port: parseInt(process.env.PRINTER_PORT || '9100'),
|
|
...status,
|
|
queueLength: printer.getQueueLength()
|
|
}
|
|
});
|
|
});
|
|
|
|
api.post('/printer/test', (c) => {
|
|
const printer = getPrinter();
|
|
const testData = new Uint8Array([
|
|
0x1B, 0x40,
|
|
0x1B, 0x61, 0x01,
|
|
...new TextEncoder().encode('Printer Test Page\n'),
|
|
...new TextEncoder().encode('================\n'),
|
|
0x1B, 0x61, 0x00,
|
|
0x0A, 0x0A,
|
|
0x1D, 0x56, 0x00,
|
|
]);
|
|
const jobId = printer.queue(testData);
|
|
return c.json({ success: true, jobId, message: 'Test page queued' });
|
|
});
|
|
|
|
export { api as apiRoutes }; |