npm package: @microplus/print-service-client
Description: 打印服务 HTTP API 客户端库
Latest version: 1.0.0

# @print-service/client

打印服务 HTTP API 客户端库，用于 TypeScript/JavaScript 项目。

## 安装

```bash
pnpm add @print-service/client
# 或
npm install @print-service/client
# 或
yarn add @print-service/client
```

## 环境要求

- Node.js >= 18.0.0（原生支持 `fetch` API）
- 或 Node.js >= 14.0.0 并安装 `node-fetch` 等 fetch polyfill

如果使用 Node.js 14-17，需要安装 fetch polyfill：

```bash
npm install node-fetch@2
```

然后在代码中导入：

```typescript
import fetch from 'node-fetch';
// @ts-ignore
global.fetch = fetch;
```

## 快速开始

```typescript
import { PrintServiceClient } from '@print-service/client';

// 创建客户端实例
const client = new PrintServiceClient({
  baseUrl: 'http://localhost:3001', // 可选，默认为 http://localhost:3001
  timeout: 30000, // 可选，默认 30 秒
});

// 健康检查
const health = await client.healthCheck();
console.log(health);

// 模板打印
const result = await client.print({
  templateName: '默认小票模板',
  variables: {
    OrderNo: 'ORD001',
    Amount: '¥100.00',
    Date: '2024-01-01 12:00:00',
    Customer: '测试客户',
  },
  printerName: 'XP-58', // 可选
  copies: 1, // 可选，默认 1
});

// 原始内容打印
const rawResult = await client.printRaw({
  content: '订单号：ORD001\n金额：¥100.00',
  printerName: 'XP-58', // 可选
  copies: 1, // 可选
  fontName: '宋体', // 可选
  fontSize: 10, // 可选
  paperWidthMm: 58, // 可选
});
```

## API 文档

### 构造函数

```typescript
new PrintServiceClient(options?: PrintServiceClientOptions)
```

**选项：**
- `baseUrl?: string` - 服务地址，默认 `http://localhost:3001`
- `timeout?: number` - 请求超时时间（毫秒），默认 `30000`

### 系统相关

#### `healthCheck()`

健康检查，检查服务是否正常运行。

```typescript
const result = await client.healthCheck();
// result: ApiResponse
```

#### `detailedHealthCheck()`

详细健康检查，获取服务的详细健康状态，包括打印机信息。

```typescript
const result = await client.detailedHealthCheck();
// result: ApiResponse
```

### 打印相关

#### `print(request: PrintRequest)`

使用服务端模板进行打印。

```typescript
const result = await client.print({
  templateName: '默认小票模板',
  variables: {
    OrderNo: 'ORD001',
    Amount: '¥100.00',
  },
  printerName: 'XP-58', // 可选
  copies: 1, // 可选，1-100，默认 1
});
```

#### `printRaw(request: RawPrintRequest)`

直接打印调用方提供的内容，无需使用模板。

```typescript
const result = await client.printRaw({
  content: '订单号：ORD001\n金额：¥100.00',
  printerName: 'XP-58', // 可选
  copies: 1, // 可选，1-100，默认 1
  fontName: '宋体', // 可选，默认 "宋体"
  fontSize: 10, // 可选，默认 10
  paperWidthMm: 58, // 可选，默认 58
  leftMarginMm: 0, // 可选，默认 0
  topMarginMm: 0, // 可选，默认 0
});
```

### 打印机管理

#### `getPrinterList()`

获取系统中所有可用的打印机列表。

```typescript
const result = await client.getPrinterList();
// result: ApiResponse<PrinterListData>
// result.data.printers: PrinterInfo[]
// result.data.count: number
```

#### `setDefaultPrinter(printerName: string)`

设置系统默认打印机。

```typescript
const result = await client.setDefaultPrinter('XP-58');
```

### 模板管理

#### `getTemplateList()`

获取所有模板的列表，包含详细信息。

```typescript
const result = await client.getTemplateList();
// result: ApiResponse<TemplateListData>
// result.data.templates: TemplateInfo[]
// result.data.count: number
```

#### `getTemplate(name: string)`

获取指定模板的完整信息，包括所有模板项。

```typescript
const result = await client.getTemplate('默认小票模板');
// result: ApiResponse<PrintTemplate>
```

#### `saveTemplate(template: PrintTemplate, overwrite?: boolean)`

创建新模板或更新现有模板。

```typescript
const result = await client.saveTemplate({
  name: '新模板',
  description: '测试模板',
  paperWidth: 220,
  paperHeight: 800,
  items: [
    {
      itemType: 'Text',
      content: '标题',
      x: 10,
      y: 20,
      width: 200,
      height: 30,
      alignment: 'Center',
      fontStyle: 'Bold',
      fontSize: 14,
      fontName: 'Arial',
    },
  ],
}, false); // overwrite 默认为 false
```

#### `deleteTemplate(templateName: string)`

删除指定的模板。

```typescript
const result = await client.deleteTemplate('旧模板');
```

#### `copyTemplate(sourceTemplateName: string, targetTemplateName: string)`

复制一个模板并创建新模板。

```typescript
const result = await client.copyTemplate(
  '默认小票模板',
  '默认小票模板-副本'
);
```

## 类型定义

### ApiResponse

```typescript
interface ApiResponse<T = any> {
  code: number; // 0=成功, 1=失败
  msg: string;
  data?: T;
  timestamp: string;
}
```

### PrintRequest

```typescript
interface PrintRequest {
  templateName: string;
  variables: Record<string, string>;
  printerName?: string | null;
  copies?: number; // 1-100, 默认 1
}
```

### RawPrintRequest

```typescript
interface RawPrintRequest {
  content: string;
  printerName?: string | null;
  copies?: number; // 1-100, 默认 1
  fontName?: string; // 默认 "宋体"
  fontSize?: number; // 默认 10
  paperWidthMm?: number; // 默认 58
  leftMarginMm?: number; // 默认 0
  topMarginMm?: number; // 默认 0
}
```

更多类型定义请参考源代码或 TypeScript 类型提示。

## 完整示例

```typescript
import { PrintServiceClient } from '@print-service/client';

async function main() {
  const client = new PrintServiceClient({
    baseUrl: 'http://localhost:3001',
  });

  try {
    // 1. 健康检查
    const health = await client.healthCheck();
    console.log('健康检查:', health);

    // 2. 获取打印机列表
    const printers = await client.getPrinterList();
    if (printers.code === 0 && printers.data) {
      console.log('可用打印机:');
      printers.data.printers.forEach((printer) => {
        console.log(`  - ${printer.name} ${printer.isDefault ? '(默认)' : ''}`);
      });
    }

    // 3. 获取模板列表
    const templates = await client.getTemplateList();
    if (templates.code === 0 && templates.data) {
      console.log('可用模板:');
      templates.data.templates.forEach((template) => {
        console.log(`  - ${template.name}`);
      });
    }

    // 4. 模板打印
    const printResult = await client.print({
      templateName: '默认小票模板',
      variables: {
        OrderNo: `ORD${Date.now()}`,
        Amount: '¥100.00',
        Date: new Date().toLocaleString('zh-CN'),
        Customer: '测试客户',
      },
      copies: 1,
    });

    if (printResult.code === 0) {
      console.log('打印成功:', printResult.msg);
    } else {
      console.error('打印失败:', printResult.msg);
    }

    // 5. 原始内容打印
    const rawResult = await client.printRaw({
      content: `========== 收据 ==========
订单号：ORD${Date.now()}
金额：¥100.00
日期：${new Date().toLocaleString('zh-CN')}
客户：测试客户
========================
感谢您的惠顾！`,
      copies: 1,
    });

    if (rawResult.code === 0) {
      console.log('原始打印成功:', rawResult.msg);
    } else {
      console.error('原始打印失败:', rawResult.msg);
    }
  } catch (error) {
    console.error('发生错误:', error);
  }
}

main();
```

## 错误处理

所有方法返回的 `ApiResponse` 对象中，`code` 字段表示操作结果：
- `code === 0`: 操作成功
- `code === 1`: 操作失败

```typescript
const result = await client.print({ ... });

if (result.code === 0) {
  console.log('成功:', result.msg);
} else {
  console.error('失败:', result.msg);
}
```

## 注意事项

1. 确保打印服务已启动并运行在指定端口
2. 确保已安装并配置了打印机
3. 确保模板文件存在于服务端的 `Templates` 目录中
4. 如果使用自定义端口，需要在创建客户端时指定正确的服务地址

## 许可证

MIT