Files
membank/auto-check/pkg/report/print.go
张威33321 906bb54aaa 重构 auto-check:状态数据下沉各包,workflow 精简为纯调度
- discovery: ping 探测存活 + ARP 解析 MAC,包级 Devices map,串行扫描
- stress: 脚本生成模式(BuildScript/ParseResults),ToolSet 工具检测,包级 Results map
- report: 包级 Printed map,SaveAndPrintDeviceReport 保存+打印
- sshclient: 包级 RunCommand
- workflow: 仅持有 config,Start() 固定循环,直接调用各包方法
- config: 移除 ScanConfig.Concurrency(串行扫描无需并发数)
2026-08-12 17:11:59 +08:00

257 lines
5.9 KiB
Go
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.
package report
import (
"bufio"
"fmt"
"io"
"net"
"os"
"os/exec"
"runtime"
"strings"
"time"
"auto-check/pkg/config"
)
// Printed 打印状态表IP → 上次打印的状态),包级公开
// 用于"状态变化才重新打印"策略
var Printed = make(map[string]string)
// ============================
// Printer 接口 — 打印后端抽象
// ============================
// Printer 报告打印机
type Printer interface {
Print(text string) error
Close() error
}
// ============================
// 打印配置
// ============================
// DefaultPrintConfig 默认打印配置80mm 热敏)
func DefaultPrintConfig() config.PrintConfig {
return config.PrintConfig{
Backend: "system",
Width: 42,
}
}
// ============================
// ESC/POS 指令生成USB 与网络后端共用)
// ============================
// writeEscpos 将文本转为 ESC/POS 指令流写入 writer
func writeEscpos(w io.Writer, text string) error {
bw := bufio.NewWriter(w)
// 初始化打印机
bw.WriteString("\x1b@") // ESC @ 复位
bw.WriteString("\x1b3\x18") // 行距 24点
bw.WriteString("\x1bM\x00") // 标准字体
bw.WriteString("\x1ba\x00") // 左对齐
// 文本内容UTF-8 直发,打印机需支持)
for _, line := range strings.Split(text, "\n") {
bw.WriteString(line)
bw.WriteString("\n")
}
// 走纸 + 切纸
bw.WriteString("\n\n") // 尾部空行
bw.WriteString("\x1di") // 切纸(部分机型)
return bw.Flush()
}
// ============================
// 后端实现
// ============================
// SystemPrinter 系统打印后端lp/lpr/print
type SystemPrinter struct {
printerName string
command string
}
// NewSystemPrinter 创建系统打印机
// printerName 为空使用系统默认打印机
func NewSystemPrinter(printerName string) *SystemPrinter {
command := "lpr"
if runtime.GOOS == "windows" {
command = "print"
}
return &SystemPrinter{printerName: printerName, command: command}
}
// Print 发送文本到系统打印机
func (p *SystemPrinter) Print(text string) error {
var cmd *exec.Cmd
switch runtime.GOOS {
case "windows":
// 临时文件方式print 命令需要文件)
tmp, err := os.CreateTemp("", "auto-check-*.txt")
if err != nil {
return err
}
name := tmp.Name()
if _, err := tmp.WriteString(text); err != nil {
tmp.Close()
return err
}
tmp.Close()
defer os.Remove(name)
if p.printerName != "" {
cmd = exec.Command("cmd", "/c", "print", "/D:"+p.printerName, name)
} else {
cmd = exec.Command("cmd", "/c", "print", name)
}
default:
args := []string{}
if p.printerName != "" {
args = append(args, "-P", p.printerName)
}
cmd = exec.Command(p.command, append(args, "-")...)
cmd.Stdin = strings.NewReader(text)
}
return cmd.Run()
}
// Close 系统打印无需关闭
func (p *SystemPrinter) Close() error { return nil }
// ============================
// ESCPOSPrinter — 网络热敏直连9100
// ============================
// ESCPOSPrinter 网络 ESC/POS 打印机
type ESCPOSPrinter struct {
conn net.Conn
}
// NewESCPOSPrinter 连接网络 ESC/POS 打印机
// address 格式: 192.168.1.100:9100
func NewESCPOSPrinter(address string) (*ESCPOSPrinter, error) {
conn, err := net.DialTimeout("tcp", address, 5*time.Second)
if err != nil {
return nil, fmt.Errorf("连接打印机 %s 失败: %w", address, err)
}
return &ESCPOSPrinter{conn: conn}, nil
}
// Print 发送文本(自动转 ESC/POS 指令)
func (p *ESCPOSPrinter) Print(text string) error {
return writeEscpos(p.conn, text)
}
// Close 关闭连接
func (p *ESCPOSPrinter) Close() error {
if p.conn != nil {
return p.conn.Close()
}
return nil
}
// ============================
// USBPrinter — USB 热敏直连
// ============================
// USBPrinter USB ESC/POS 打印机
// Windows: \\.\usb001或打印机端口名
// Linux: /dev/usb/lp0或 lp1...
type USBPrinter struct {
dev *os.File
}
// defaultUSBDevice 默认 USB 设备路径
func defaultUSBDevice() string {
if runtime.GOOS == "windows" {
return `\\.\usb001`
}
return "/dev/usb/lp0"
}
// NewUSBPrinter 打开 USB 打印机设备
// device 为空时自动探测Linux /dev/usb/lp0Windows \\.\usb001
func NewUSBPrinter(device string) (*USBPrinter, error) {
if device == "" || device == "auto" {
device = defaultUSBDevice()
}
f, err := os.OpenFile(device, os.O_WRONLY, 0)
if err != nil {
return nil, fmt.Errorf("打开 USB 打印机 %s 失败: %w", device, err)
}
return &USBPrinter{dev: f}, nil
}
// Print 发送文本(自动转 ESC/POS 指令)
func (p *USBPrinter) Print(text string) error {
return writeEscpos(p.dev, text)
}
// Close 关闭设备
func (p *USBPrinter) Close() error {
if p.dev != nil {
return p.dev.Close()
}
return nil
}
// ============================
// FilePrinter — 文件后端(调试/重定向)
// ============================
// FilePrinter 文件打印后端
type FilePrinter struct {
path string
f *os.File
}
// NewFilePrinter 创建文件打印机
func NewFilePrinter(path string) (*FilePrinter, error) {
f, err := os.OpenFile(path, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
if err != nil {
return nil, err
}
return &FilePrinter{path: path, f: f}, nil
}
// Print 追加写入文件
func (p *FilePrinter) Print(text string) error {
_, err := p.f.WriteString(text + "\n\n")
return err
}
// Close 关闭文件
func (p *FilePrinter) Close() error {
return p.f.Close()
}
// ============================
// 工厂
// ============================
// NewPrinter 按配置创建打印机
func NewPrinter(cfg config.PrintConfig) (Printer, error) {
if !cfg.Enabled {
return nil, nil
}
switch cfg.Backend {
case "system":
return NewSystemPrinter(cfg.Device), nil
case "escpos":
return NewESCPOSPrinter(cfg.Device)
case "usb":
return NewUSBPrinter(cfg.Device)
case "file":
return NewFilePrinter(cfg.Device)
default:
return nil, fmt.Errorf("未知打印后端: %s", cfg.Backend)
}
}