Files
cashier_desktop/electron/printService.js
2026-03-28 08:56:00 +08:00

100 lines
4.0 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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())
})
}