新增添加网口打印机

This commit is contained in:
gyq
2026-03-28 08:56:00 +08:00
parent 33be9f2cef
commit 5fab9a857a
10 changed files with 11330 additions and 1197 deletions

View File

@@ -5,6 +5,7 @@ import axios from "axios";
import os from "os";
import fs from "fs";
import { exec } from "child_process";
import { printReceipt } from "./printService";
// ===== 核心配置:单文件缓存 =====
// 固定的缓存文件路径永远只存这1个文件
@@ -106,6 +107,19 @@ app.whenReady().then(() => {
});
});
ipcMain.on('networkPrint', async (event, arg) => {
try {
let _parmas = JSON.parse(arg);
console.log(_parmas);
console.log(_parmas.orderData.carts);
await printReceipt(_parmas.printerIp, _parmas.orderData);
return { ok: true }
} catch (e) {
console.log(e);
return { ok: false, msg: e.message }
}
})
app.on("activate", () => {
// 在 macOS 系统内, 如果没有已开启的应用窗口
// 点击托盘图标时通常会重新创建一个新窗口

100
electron/printService.js Normal file
View File

@@ -0,0 +1,100 @@
import net from 'net'
import iconv from 'iconv-lite'
export function printReceipt(printerIp, order) {
return new Promise((resolve) => {
const socket = new net.Socket()
socket.setTimeout(8000)
socket.connect(9100, printerIp, () => {
// 打印机复位
socket.write(Buffer.from([0x1B, 0x40]))
// ==========================================
// 全局配置58mm 一行固定 32 个字符
// ==========================================
const lineWidth = 32
const line = '================================'.substring(0, lineWidth)
const lineMin = '--------------------------------'.substring(0, lineWidth)
// 居中函数
const center = (str) => {
const s = String(str)
const len = s.length
const pad = Math.max(0, Math.floor((lineWidth - len) / 2))
return ' '.repeat(pad) + s + '\n'
}
// ==========================================
// 标题:店名 + 结算单 + 桌号 → 全部居中对齐
// ==========================================
socket.write(Buffer.from([0x1B, 0x21, 0x11])) // 放大店名
socket.write(iconv.encode(center(order.shop_name), 'gbk'))
socket.write(Buffer.from([0x1B, 0x21, 0x00])) // 恢复正常
socket.write(iconv.encode(center(`结算单 #${order.orderInfo.orderNum}`), 'gbk'))
socket.write(iconv.encode(center(`桌号:${order.orderInfo.tableName || ''}`), 'gbk'))
socket.write(iconv.encode(line + '\n', 'gbk'))
// ==========================================
// 订单信息(全部撑满宽度)
// ==========================================
let content = ''
content += `订单号:${order.orderInfo.orderNo}\n`
content += `交易时间:${order.createdAt}\n`
content += `收银员:${order.loginAccount}\n`
content += lineMin + '\n'
// ==========================================
// 商品表格:完全对齐、撑满宽度
// ==========================================
content += '品名 单价 数量 小计\n'
content += lineMin + '\n'
order.carts.forEach(item => {
let name = String(item.name || '').substring(0, 10).padEnd(10, ' ')
let price = String(item.salePrice || '0.00').padStart(6, ' ')
let num = String(item.number || 1).padStart(3, ' ')
let total = String(item.totalAmount || '0.00').padStart(3, ' ')
content += name + price + num + total + '\n'
})
content += lineMin + '\n'
// ==========================================
// 金额信息
// ==========================================
content += `原价:${order.originAmount}\n`
content += `折扣:${order.discountAllAmount}\n`
// 发送前面内容
socket.write(iconv.encode(content, 'gbk'))
// 实付放大
socket.write(Buffer.from([0x1B, 0x21, 0x11]))
socket.write(iconv.encode(`实付:${order.orderAmount}\n`, 'gbk'))
socket.write(Buffer.from([0x1B, 0x21, 0x00]))
// 底部信息
let bottom = ''
bottom += `备注:${order.remark || '无'}\n`
bottom += `打印时间:${order.printTime}\n`
bottom += line + '\n'
bottom += '\n\n\n\n\n\n'
socket.write(iconv.encode(bottom, 'gbk'))
// 只切纸一次
socket.write(Buffer.from([0x1D, 0x56, 0x00]))
setTimeout(() => {
socket.end()
resolve('ok')
}, 400)
})
socket.on('error', () => { })
socket.on('close', () => { })
socket.on('timeout', () => socket.destroy())
})
}