Files
qhmes/XSLPrintDot/docs/usage_guide_zh.md

264 lines
9.5 KiB
Markdown
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.
# XSL-PrintDot Client 使用指南与规范
## 1. 项目简介
**XSL-PrintDot Client** 是一个基于 Wails (Go + Vue 3) 开发的本地打印中间件。它充当浏览器(或其他客户端)与操作系统打印机之间的桥梁,通过 WebSocket 协议接收打印指令,并调用系统打印机进行打印。
主要功能:
- 自动获取操作系统已安装的打印机列表。
- 启动 WebSocket 服务监听打印请求(默认端口 1122
- 支持自定义服务端口和安全密钥Secret Key
- **打印内容要求**:接收 Base64 编码的 PDF 文件内容,并调用系统打印命令进行打印。
- 支持高级打印参数:打印份数、份数间隔,以及更多打印设置。
- 提供可视化的管理界面,实时查看日志和打印机状态。
- **日志实时监控**:支持实时查看系统日志。
---
## 2. 启动与配置
### 2.1 启动应用
可以直接运行编译后的可执行文件(如 `XSL-PrintDot.exe`),或在开发环境中使用:
```bash
wails dev
```
**注意**: 程序启动时会自动开启 WebSocket 服务(默认端口 1122
**Windows 打印说明**:
- 请确保 Windows 打印后端可用且程序有权限访问。
### 2.2 界面配置
启动后,界面提供以下配置项:
- **Port**: WebSocket 服务监听端口(默认 `1122`)。
- **Secret Key**: 安全密钥(可选)。如果设置了密钥,客户端在连接或发送请求时必须通过鉴权。
- **Start/Stop Server**: 点击按钮即可启动或停止 WebSocket 服务。
- **Connection URL**: 服务启动后,界面会显示完整的连接地址(如 `ws://localhost:1122/ws?key=...`)。
**操作说明**:
- **退出程序**: 使用菜单栏 `Menu` -> `Quit` (Ctrl+Q),或使用托盘菜单的 `Quit` 可完全退出程序。
- **后台运行**: 点击主窗口关闭按钮 (X) 不会退出程序,而是将程序最小化到系统托盘区。程序启动后会在系统托盘区显示图标,可用于快速唤起窗口或退出。
- **托盘菜单**: 在系统托盘图标上右键单击,可选择 `Show Main Window` 显示主窗口或 `Quit` 退出程序。
- **打开设置**: 使用菜单栏 `Menu` -> `Settings` (Ctrl+I) 可打开设置窗口。
- **查看日志**: 使用菜单栏 `Menu` -> `System Logs` (Ctrl+L) 可查看实时日志.
---
## 3. WebSocket 接口规范
### 3.1 连接信息
- **协议**: WebSocket (`ws://`)
- **地址**: `ws://localhost:<PORT>/ws`
- **鉴权**:
- 如果设置了 `Secret Key`,建议在连接 URL 中携带:`ws://localhost:1122/ws?key=YOUR_PASSWORD`
- 如果连接时未携带 key也可以在发送的消息体中包含 `key` 字段(但不推荐,连接可能被拒绝)。
### 3.2 消息类型
#### 3.2.1 连接成功响应 (Server -> Client)
连接建立后,服务端会立即发送当前的打印机列表:
```json
{
"type": "printer_list",
"data": [
{"name": "Microsoft Print to PDF", "isDefault": true},
{"name": "ZDesigner GK888t", "isDefault": false}
]
}
```
#### 3.2.2 获取打印机列表 (Client -> Server)
客户端可以随时发送以下 JSON 消息主动获取最新的打印机列表:
```json
{
"type": "get_printers"
}
```
服务端将回复与 **3.2.1** 相同格式的 `printer_list` 消息。
#### 3.2.3 获取打印机能力 (Client -> Server)
客户端可以请求指定打印机的可用参数:
```json
{
"type": "get_printer_caps",
"printer": "Microsoft Print to PDF"
}
```
服务端响应示例:
```json
{
"type": "printer_caps",
"printer": "Microsoft Print to PDF",
"data": {
"paperSizes": ["A4", "Letter"],
"printerPaperNames": ["A4", "Letter"],
"duplexSupported": false,
"colorSupported": true
}
}
```
> 说明不同系统返回字段会有差异Windows 返回 Win32_Printer/Win32_PrinterConfiguration 信息Linux/macOS 返回 lpoptions 解析结果。
#### 3.2.4 发送打印任务 (Client -> Server)
客户端发送的 JSON 数据包结构如下(按功能分类):
```json
{
"printer": "Microsoft Print to PDF", // [必填] 目标打印机名称
"content": "data:application/pdf;base64,JVBERi...", // [必填] Base64 编码的 PDF 内容 (支持带前缀或纯 Base64)
"key": "123456", // [选填] 鉴权密钥 (若连接时已验证可省略)
"job": {
"name": "My Print Job 001", // [选填] 任务名称 (仅用于日志记录)
"copies": 2, // [选填] 打印份数,默认 1
"intervalMs": 1000 // [选填] 份数间延迟(毫秒),用于手动隔张打印
},
"pages": {
"range": "1-3,5", // [选填] 页码范围 (支持 N / N-M / N,M / 反向区间)
"set": "odd" // [选填] odd | even
},
"layout": {
"scale": "fit", // [选填] noscale | shrink | fit
"orientation": "portrait" // [选填] portrait | landscape
},
"color": {
"mode": "color" // [选填] color | monochrome
},
"sides": {
"mode": "duplex" // [选填] simplex | duplex | duplexshort | duplexlong
},
"paper": {
"size": "A4" // [选填] A4 | letter | legal | tabloid | statement | A2 | A3 | A5 | A6
},
"tray": {
"bin": "2" // [选填] 纸盒编号或名称,例如 2 / Manual
}
}
```
> **注意**:
> 1. `content` 字段必须是 **PDF 文件的 Base64 编码字符串**。
> - 支持标准 Data URI 格式:`data:application/pdf;base64,JVBERi...`
> - 也支持纯 Base64 字符串:`JVBERi...`
> - 服务端会自动去除 `data:` 前缀(如果有)并校验解码后的内容是否以 `%PDF` 开头。
| 字段 | 类型 | 说明 |
| :--- | :--- | :--- |
| `printer` | String | 目标打印机名称。 |
| `content` | String | **Base64 编码的 PDF 内容**。 |
| `job.name` | String | 打印任务名称。 |
| `job.copies` | Integer | **打印份数**`intervalMs` 为 0 时由系统命令一次性处理。 |
| `job.intervalMs` | Integer | **隔张间隔 (ms)**。大于 0 时服务端逐份打印。 |
| `pages.range` | String | **页码范围**`N` / `N-M` / `N,M` / 反向区间。 |
| `pages.set` | String | **奇偶页**`odd` / `even`。 |
| `layout.scale` | String | **缩放**`noscale` / `shrink` / `fit`。 |
| `layout.orientation` | String | **方向**`portrait` / `landscape`。 |
| `color.mode` | String | **颜色模式**`color` / `monochrome`。 |
| `sides.mode` | String | **单双面**`simplex` / `duplex` / `duplexshort` / `duplexlong`。 |
| `paper.size` | String | **纸张**:如 `A4``letter``legal`。未提供时会尝试从 PDF 的 MediaBox 自动识别常见尺寸。 |
| `tray.bin` | String | **纸盒**:编号或名称。 |
#### 3.2.3.1 平台支持说明
**Windows**
- `pages.range` / `pages.set` / `layout.scale` / `layout.orientation` / `color.mode` / `sides.mode` / `paper.size` / `tray.bin` / `job.copies` 会被转换为 Windows 打印选项。
**Linux/macOS (lp/CUPS)**
- `pages.range` -> `-P`
- `pages.set` -> `-o page-set=odd|even`
- `layout.scale` -> `fit-to-page` / `scaling=100``shrink` 使用默认行为)。
- `layout.orientation` -> `-o orientation-requested=3|4`(驱动可能忽略)。
- `color.mode` -> `-o ColorModel=Gray` / `-o ColorModel=RGB`(部分驱动可能忽略)。
- `sides.mode` -> `-o sides=...`
- `paper.size` -> `-o media=...`
- `tray.bin` -> `-o InputSlot=...`(依赖驱动支持)。
#### 3.2.4 服务端响应 (Server -> Client)
服务端会返回每次打印的结果:
**成功响应:**
```json
{
"status": "success",
"message": "Printed successfully"
}
```
**失败响应:**
```json
{
"status": "error",
"message": "Content must be a PDF file"
}
```
**Windows 队列跟踪说明:**
Windows 下服务端会等待打印任务进入打印队列并完成后才返回 `success`
若 120 秒内未入队或 5 分钟内未完成,将返回 `error` 并给出超时提示。
---
## 4. 调用示例 (JavaScript)
```javascript
const socket = new WebSocket('ws://localhost:1122/ws?key=123456');
socket.onopen = () => {
console.log('已连接');
};
socket.onmessage = (event) => {
const msg = JSON.parse(event.data);
if (msg.type === 'printer_list') {
console.log('可用打印机:', msg.data);
const targetPrinter = msg.data.find(p => p.isDefault) || msg.data[0];
// 示例:主动刷新打印机列表
// socket.send(JSON.stringify({ type: 'get_printers' }));
// 获取打印机能力(纸张/单双面/彩色等)
socket.send(JSON.stringify({
type: 'get_printer_caps',
printer: targetPrinter?.name
}));
} else if (msg.type === 'printer_caps') {
const caps = msg.data || {};
const sizes = caps.printerPaperNames || caps.paperSizes || [];
const paperSize = sizes[0] || 'A4';
// 发送打印任务(按功能分组)
socket.send(JSON.stringify({
printer: msg.printer,
content: "JVBERi0xLjQKJ...", // Base64 PDF Data
job: {
name: "Test Job",
copies: 2,
intervalMs: 0
},
pages: {
range: "1-3,5",
set: "odd"
},
layout: {
scale: "fit",
orientation: "portrait"
},
color: {
mode: "color"
},
sides: {
mode: "duplex"
},
paper: {
size: paperSize
},
tray: {
bin: "2"
}
}));
} else {
console.log('收到回复:', msg);
}
};
```