chore(docs): 增加关于CLodop的安装及使用说明
This commit is contained in:
670
docs/common/CLodop.md
Normal file
670
docs/common/CLodop.md
Normal file
@@ -0,0 +1,670 @@
|
||||
好的!我来详细介绍一下**Web打印服务CLodop**,这是一个非常强大的浏览器打印解决方案。
|
||||
|
||||
## 🖨️ **CLodop - 专业Web打印服务详解**
|
||||
|
||||
### **1. CLodop 是什么?**
|
||||
|
||||
**CLodop**(Cloud Lodop)是**C-Lodop 云打印服务**的简称,是 Lodop 技术的一个轻量级版本,专门为 Web 应用提供强大的打印功能。
|
||||
|
||||
#### **核心特点**
|
||||
- ✅ **跨浏览器兼容** - 支持所有主流浏览器
|
||||
- ✅ **无需安装插件** - 基于云服务架构
|
||||
- ✅ **精确打印控制** - 像素级打印精度
|
||||
- ✅ **批量打印支持** - 高效处理大量打印任务
|
||||
- ✅ **多种打印方式** - 直接打印、预览打印、设计打印
|
||||
|
||||
### **2. CLodop 与 Lodop 的区别**
|
||||
|
||||
| 特性 | CLodop(云打印) | Lodop(传统打印) |
|
||||
|------|-----------------|------------------|
|
||||
| **架构** | 云服务模式,无需安装 | 需要安装本地插件 |
|
||||
| **部署** | 服务端部署,客户端零配置 | 每台客户端都需要安装 |
|
||||
| **更新** | 服务端统一更新 | 每台客户端单独更新 |
|
||||
| **兼容性** | 支持所有现代浏览器 | 对高版本浏览器支持有限 |
|
||||
| **适用场景** | Web应用、移动端 | 企业内部系统、局域网 |
|
||||
|
||||
### **3. CLodop 核心架构**
|
||||
|
||||
#### **系统架构图**
|
||||
```
|
||||
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
|
||||
│ Web应用 │ -> │ CLodop服务 │ -> │ 打印机 │
|
||||
│ (浏览器) │ │ (服务端) │ │ (本地/网络) │
|
||||
└─────────────┘ └─────────────┘ └─────────────┘
|
||||
│ │ │
|
||||
JavaScript 打印服务 打印输出
|
||||
API 任务队列
|
||||
```
|
||||
|
||||
### **4. 完整安装和配置**
|
||||
|
||||
#### **4.1 服务端安装(Windows)**
|
||||
```bash
|
||||
# 下载CLodop服务端
|
||||
# 官方下载地址:http://www.c-lodop.com/download.html
|
||||
|
||||
# 安装步骤:
|
||||
1. 下载 CLodop_Setup.exe
|
||||
2. 以管理员身份运行安装
|
||||
3. 默认安装目录:C:\Program Files (x86)\CLodop
|
||||
4. 服务自动启动,监听端口:8000、18000
|
||||
```
|
||||
|
||||
#### **4.2 服务端配置文件**
|
||||
```json
|
||||
// CLodop 服务配置 (config.json)
|
||||
{
|
||||
"server": {
|
||||
"port": 8000,
|
||||
"sslPort": 8443,
|
||||
"host": "0.0.0.0"
|
||||
},
|
||||
"print": {
|
||||
"defaultPaper": "A4",
|
||||
"dpi": 300,
|
||||
"timeout": 30000
|
||||
},
|
||||
"security": {
|
||||
"allowedOrigins": ["http://localhost:3000", "https://yourdomain.com"],
|
||||
"authRequired": false
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### **4.3 验证安装**
|
||||
```bash
|
||||
# 检查服务状态
|
||||
netstat -ano | findstr :8000
|
||||
|
||||
# 访问测试页面
|
||||
http://localhost:8000
|
||||
```
|
||||
|
||||
### **5. 前端集成完整代码**
|
||||
|
||||
#### **5.1 基础集成方案**
|
||||
```html
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>CLodop 打印示例</title>
|
||||
<!-- 引入CLodop JS文件 -->
|
||||
<script src="http://localhost:8000/CLodopfuncs.js"></script>
|
||||
<script>
|
||||
// 检查CLodop服务状态
|
||||
function checkCLodop() {
|
||||
try {
|
||||
if (getCLodop()) {
|
||||
console.log('CLodop服务已就绪');
|
||||
return true;
|
||||
} else {
|
||||
console.warn('CLodop服务未启动');
|
||||
return false;
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('CLodop检查失败:', e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// 获取CLodop对象
|
||||
function getCLodop() {
|
||||
if (window.getCLodop) {
|
||||
return window.getLodop();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body onload="checkCLodop()">
|
||||
<!-- 打印内容 -->
|
||||
<div id="printContent">
|
||||
<h1>可打印内容</h1>
|
||||
<table border="1" style="width:100%">
|
||||
<tr><th>姓名</th><th>年龄</th><th>职位</th></tr>
|
||||
<tr><td>张三</td><td>30</td><td>工程师</td></tr>
|
||||
<tr><td>李四</td><td>25</td><td>设计师</td></tr>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<button onclick="printDirect()">直接打印</button>
|
||||
<button onclick="printPreview()">打印预览</button>
|
||||
<button onclick="printDesign()">打印设计</button>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
#### **5.2 高级打印控制器**
|
||||
```javascript
|
||||
// clodop-manager.js
|
||||
class CLodopManager {
|
||||
constructor() {
|
||||
this.lodop = null;
|
||||
this.isReady = false;
|
||||
this.init();
|
||||
}
|
||||
|
||||
// 初始化CLodop
|
||||
init() {
|
||||
if (typeof window.getCLodop === 'undefined') {
|
||||
console.error('CLodop未加载,请检查脚本引入');
|
||||
return;
|
||||
}
|
||||
|
||||
this.lodop = window.getLodop();
|
||||
if (this.lodop) {
|
||||
this.isReady = true;
|
||||
console.log('CLodop初始化成功');
|
||||
} else {
|
||||
console.error('CLodop初始化失败');
|
||||
}
|
||||
}
|
||||
|
||||
// 检查服务状态
|
||||
checkStatus() {
|
||||
if (!this.lodop) return false;
|
||||
|
||||
try {
|
||||
const status = this.lodop.PRINT_STATUS;
|
||||
return status === 'READY';
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// 创建打印任务
|
||||
createPrintJob(title = '打印文档') {
|
||||
if (!this.isReady) {
|
||||
throw new Error('CLodop未就绪');
|
||||
}
|
||||
|
||||
this.lodop.PRINT_INIT(title);
|
||||
return this;
|
||||
}
|
||||
|
||||
// 设置打印内容
|
||||
setContent(htmlContent, options = {}) {
|
||||
const config = {
|
||||
top: options.top || '10mm',
|
||||
left: options.left || '10mm',
|
||||
width: options.width || '190mm',
|
||||
height: options.height || '277mm',
|
||||
...options
|
||||
};
|
||||
|
||||
this.lodop.ADD_PRINT_HTML(
|
||||
config.top, config.left, config.width, config.height,
|
||||
htmlContent
|
||||
);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
// 设置打印机
|
||||
setPrinter(printerName = '') {
|
||||
if (printerName) {
|
||||
this.lodop.SET_PRINTER_INDEX(printerName);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
// 设置纸张大小
|
||||
setPaperSize(paperName = 'A4') {
|
||||
this.lodop.SET_PRINT_PAGESIZE(1, 0, 0, paperName);
|
||||
return this;
|
||||
}
|
||||
|
||||
// 设置打印份数
|
||||
setCopies(copies = 1) {
|
||||
this.lodop.SET_PRINT_COPIES(copies);
|
||||
return this;
|
||||
}
|
||||
|
||||
// 直接打印
|
||||
printDirect() {
|
||||
if (!this.isReady) return false;
|
||||
|
||||
try {
|
||||
this.lodop.PRINT();
|
||||
return true;
|
||||
} catch (e) {
|
||||
console.error('打印失败:', e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// 打印预览
|
||||
printPreview() {
|
||||
if (!this.isReady) return false;
|
||||
|
||||
try {
|
||||
this.lodop.PREVIEW();
|
||||
return true;
|
||||
} catch (e) {
|
||||
console.error('预览失败:', e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// 打印设计
|
||||
printDesign() {
|
||||
if (!this.isReady) return false;
|
||||
|
||||
try {
|
||||
this.lodop.PRINT_DESIGN();
|
||||
return true;
|
||||
} catch (e) {
|
||||
console.error('设计失败:', e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// 批量打印
|
||||
batchPrint(documents = []) {
|
||||
if (!this.isReady) return false;
|
||||
|
||||
try {
|
||||
documents.forEach((doc, index) => {
|
||||
this.lodop.PRINT_INIT(`文档${index + 1}`);
|
||||
this.lodop.ADD_PRINT_HTML("10mm", "10mm", "190mm", "277mm", doc);
|
||||
|
||||
if (index < documents.length - 1) {
|
||||
this.lodop.NEWPAGE(); // 分页
|
||||
}
|
||||
});
|
||||
|
||||
this.lodop.PREVIEW();
|
||||
return true;
|
||||
} catch (e) {
|
||||
console.error('批量打印失败:', e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 全局实例
|
||||
window.clodopManager = new CLodopManager();
|
||||
```
|
||||
|
||||
### **6. 实际应用示例**
|
||||
|
||||
#### **6.1 票据打印**
|
||||
```javascript
|
||||
// receipt-print.js
|
||||
function printReceipt(orderData) {
|
||||
const manager = window.clodopManager;
|
||||
if (!manager.isReady) {
|
||||
alert('打印服务未就绪');
|
||||
return;
|
||||
}
|
||||
|
||||
const receiptHTML = `
|
||||
<div style="width:80mm;font-family:'宋体';font-size:12px;">
|
||||
<h3 style="text-align:center;">销售小票</h3>
|
||||
<hr>
|
||||
<p><strong>订单号:</strong>${orderData.orderNo}</p>
|
||||
<p><strong>时间:</strong>${new Date().toLocaleString()}</p>
|
||||
<hr>
|
||||
<table style="width:100%;">
|
||||
${orderData.items.map(item => `
|
||||
<tr>
|
||||
<td>${item.name}</td>
|
||||
<td>×${item.quantity}</td>
|
||||
<td>¥${item.price}</td>
|
||||
</tr>
|
||||
`).join('')}
|
||||
</table>
|
||||
<hr>
|
||||
<p style="text-align:right;"><strong>总计:¥${orderData.total}</strong></p>
|
||||
</div>
|
||||
`;
|
||||
|
||||
manager.createPrintJob('销售小票')
|
||||
.setPaperSize(1) // 1=80mm 小票
|
||||
.setContent(receiptHTML, {
|
||||
width: '80mm',
|
||||
height: 'auto'
|
||||
})
|
||||
.printDirect();
|
||||
}
|
||||
```
|
||||
|
||||
#### **6.2 报表打印**
|
||||
```javascript
|
||||
// report-print.js
|
||||
function printReport(reportData) {
|
||||
const manager = window.clodopManager;
|
||||
|
||||
const reportHTML = `
|
||||
<div style="font-family:'微软雅黑';padding:20px;">
|
||||
<h1 style="text-align:center;">${reportData.title}</h1>
|
||||
<table border="1" style="width:100%;border-collapse:collapse;">
|
||||
<thead>
|
||||
<tr style="background:#f5f5f5;">
|
||||
${reportData.headers.map(header =>
|
||||
`<th style="padding:8px;">${header}</th>`
|
||||
).join('')}
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
${reportData.rows.map(row => `
|
||||
<tr>
|
||||
${row.map(cell =>
|
||||
`<td style="padding:6px;">${cell}</td>`
|
||||
).join('')}
|
||||
</tr>
|
||||
`).join('')}
|
||||
</tbody>
|
||||
</table>
|
||||
<div style="margin-top:20px;">
|
||||
<p>打印时间:${new Date().toLocaleString()}</p>
|
||||
<p>打印人:${reportData.printUser}</p>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
manager.createPrintJob(reportData.title)
|
||||
.setPaperSize('A4')
|
||||
.setContent(reportHTML)
|
||||
.setPrinter(reportData.printer || '')
|
||||
.printPreview();
|
||||
}
|
||||
```
|
||||
|
||||
#### **6.3 标签打印**
|
||||
```javascript
|
||||
// label-print.js
|
||||
function printLabels(labelsData) {
|
||||
const manager = window.clodopManager;
|
||||
|
||||
manager.createPrintJob('产品标签');
|
||||
|
||||
labelsData.forEach((label, index) => {
|
||||
const labelHTML = `
|
||||
<div style="width:50mm;height:30mm;border:1px dotted #ccc;padding:5mm;font-size:10px;">
|
||||
<div style="text-align:center;font-weight:bold;">${label.productName}</div>
|
||||
<div>规格:${label.spec}</div>
|
||||
<div>批次:${label.batchNo}</div>
|
||||
<div>有效期:${label.expiryDate}</div>
|
||||
<div style="text-align:center;margin-top:2mm;">
|
||||
<img src="${label.barcodeUrl}" style="height:15mm;">
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
manager.setContent(labelHTML, {
|
||||
top: `${(index % 5) * 32}mm`,
|
||||
left: `${Math.floor(index / 5) * 52}mm`,
|
||||
width: '50mm',
|
||||
height: '30mm'
|
||||
});
|
||||
|
||||
if (index < labelsData.length - 1) {
|
||||
manager.lodop.NEWPAGE();
|
||||
}
|
||||
});
|
||||
|
||||
manager.printPreview();
|
||||
}
|
||||
```
|
||||
|
||||
### **7. 高级功能实现**
|
||||
|
||||
#### **7.1 打印状态监控**
|
||||
```javascript
|
||||
// print-monitor.js
|
||||
class PrintMonitor {
|
||||
constructor() {
|
||||
this.printJobs = new Map();
|
||||
this.initEvents();
|
||||
}
|
||||
|
||||
initEvents() {
|
||||
// 监听打印开始
|
||||
window.addEventListener('beforeprint', (e) => {
|
||||
console.log('打印开始');
|
||||
this.onPrintStart(e);
|
||||
});
|
||||
|
||||
// 监听打印结束
|
||||
window.addEventListener('afterprint', (e) => {
|
||||
console.log('打印结束');
|
||||
this.onPrintEnd(e);
|
||||
});
|
||||
}
|
||||
|
||||
onPrintStart(jobId) {
|
||||
this.printJobs.set(jobId, {
|
||||
startTime: new Date(),
|
||||
status: 'printing'
|
||||
});
|
||||
}
|
||||
|
||||
onPrintEnd(jobId, success = true) {
|
||||
const job = this.printJobs.get(jobId);
|
||||
if (job) {
|
||||
job.endTime = new Date();
|
||||
job.status = success ? 'completed' : 'failed';
|
||||
job.duration = job.endTime - job.startTime;
|
||||
|
||||
// 发送打印统计
|
||||
this.sendPrintStatistics(job);
|
||||
}
|
||||
}
|
||||
|
||||
sendPrintStatistics(job) {
|
||||
// 发送到服务器记录
|
||||
fetch('/api/print/log', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(job)
|
||||
});
|
||||
}
|
||||
|
||||
// 获取打印机列表
|
||||
getPrinterList() {
|
||||
const lodop = getCLodop();
|
||||
if (!lodop) return [];
|
||||
|
||||
const printers = [];
|
||||
const count = lodop.GET_PRINTER_COUNT();
|
||||
|
||||
for (let i = 0; i < count; i++) {
|
||||
printers.push({
|
||||
name: lodop.GET_PRINTER_NAME(i),
|
||||
status: lodop.GET_PRINTER_STATUS(i)
|
||||
});
|
||||
}
|
||||
|
||||
return printers;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### **7.2 错误处理和重试机制**
|
||||
```javascript
|
||||
// error-handler.js
|
||||
class PrintErrorHandler {
|
||||
static async printWithRetry(printFunction, maxRetries = 3) {
|
||||
for (let attempt = 1; attempt <= maxRetries; attempt++) {
|
||||
try {
|
||||
const result = await printFunction();
|
||||
return result;
|
||||
} catch (error) {
|
||||
console.error(`打印尝试 ${attempt} 失败:`, error);
|
||||
|
||||
if (attempt === maxRetries) {
|
||||
throw new Error(`打印失败,已重试 ${maxRetries} 次`);
|
||||
}
|
||||
|
||||
// 等待后重试
|
||||
await this.delay(1000 * attempt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static delay(ms) {
|
||||
return new Promise(resolve => setTimeout(resolve, ms));
|
||||
}
|
||||
|
||||
static handleCommonErrors(error) {
|
||||
const errorMap = {
|
||||
'PRINTER_NOT_FOUND': '打印机未找到,请检查打印机连接',
|
||||
'OUT_OF_PAPER': '打印机缺纸,请添加纸张',
|
||||
'SERVICE_UNAVAILABLE': '打印服务不可用,请检查CLodop服务',
|
||||
'TIMEOUT': '打印超时,请重试'
|
||||
};
|
||||
|
||||
const message = errorMap[error.code] || `打印错误: ${error.message}`;
|
||||
this.showErrorDialog(message);
|
||||
}
|
||||
|
||||
static showErrorDialog(message) {
|
||||
// 可以替换为更友好的UI提示
|
||||
alert(`打印错误: ${message}`);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### **8. 部署和配置最佳实践**
|
||||
|
||||
#### **8.1 Docker 部署**
|
||||
```dockerfile
|
||||
# Dockerfile
|
||||
FROM windows/servercore:ltsc2019
|
||||
|
||||
# 安装CLodop服务
|
||||
COPY CLodop_Setup.exe /setup/
|
||||
RUN /setup/CLodop_Setup.exe /S
|
||||
|
||||
# 暴露端口
|
||||
EXPOSE 8000 18000
|
||||
|
||||
# 启动服务
|
||||
CMD ["C:\\Program Files (x86)\\CLodop\\CLodop.exe", "-start"]
|
||||
```
|
||||
|
||||
#### **8.2 Nginx 反向代理配置**
|
||||
```nginx
|
||||
# nginx.conf
|
||||
server {
|
||||
listen 80;
|
||||
server_name print.yourdomain.com;
|
||||
|
||||
location /CLodop/ {
|
||||
proxy_pass http://localhost:8000/;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
}
|
||||
|
||||
# WebSocket 支持
|
||||
location /CLodop/ws {
|
||||
proxy_pass http://localhost:8000/ws;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### **9. 安全配置**
|
||||
|
||||
#### **9.1 访问控制**
|
||||
```javascript
|
||||
// security-middleware.js
|
||||
const express = require('express');
|
||||
const app = express();
|
||||
|
||||
// IP白名单
|
||||
const allowedIPs = ['192.168.1.0/24', '10.0.0.0/8'];
|
||||
|
||||
app.use('/print', (req, res, next) => {
|
||||
const clientIP = req.ip || req.connection.remoteAddress;
|
||||
|
||||
if (!isIPAllowed(clientIP, allowedIPs)) {
|
||||
return res.status(403).json({ error: '访问被拒绝' });
|
||||
}
|
||||
|
||||
next();
|
||||
});
|
||||
|
||||
function isIPAllowed(ip, allowedRanges) {
|
||||
// IP地址验证逻辑
|
||||
return allowedRanges.some(range => {
|
||||
// 简单的IP范围检查实现
|
||||
return ip.startsWith(range.split('.')[0]);
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
### **10. 性能优化**
|
||||
|
||||
#### **10.1 打印任务队列**
|
||||
```javascript
|
||||
// print-queue.js
|
||||
class PrintQueue {
|
||||
constructor() {
|
||||
this.queue = [];
|
||||
this.isProcessing = false;
|
||||
this.maxConcurrent = 1; // 串行打印
|
||||
}
|
||||
|
||||
async addJob(printJob) {
|
||||
return new Promise((resolve, reject) => {
|
||||
this.queue.push({ printJob, resolve, reject });
|
||||
this.processQueue();
|
||||
});
|
||||
}
|
||||
|
||||
async processQueue() {
|
||||
if (this.isProcessing || this.queue.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.isProcessing = true;
|
||||
|
||||
while (this.queue.length > 0) {
|
||||
const { printJob, resolve, reject } = this.queue.shift();
|
||||
|
||||
try {
|
||||
const result = await printJob();
|
||||
resolve(result);
|
||||
} catch (error) {
|
||||
reject(error);
|
||||
}
|
||||
|
||||
// 延迟一下,避免打印机过载
|
||||
await this.delay(500);
|
||||
}
|
||||
|
||||
this.isProcessing = false;
|
||||
}
|
||||
|
||||
delay(ms) {
|
||||
return new Promise(resolve => setTimeout(resolve, ms));
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 💡 **总结**
|
||||
|
||||
### **CLodop 核心优势**
|
||||
1. **零客户端安装** - 基于云服务架构
|
||||
2. **完美浏览器兼容** - 支持所有现代浏览器
|
||||
3. **企业级功能** - 批量打印、精确控制、多种纸张支持
|
||||
4. **易于集成** - 简单的 JavaScript API
|
||||
|
||||
### **适用场景**
|
||||
- ✅ **企业ERP系统** - 报表、单据打印
|
||||
- ✅ **电商平台** - 订单、发货单打印
|
||||
- ✅ **医疗系统** - 处方、报告打印
|
||||
- ✅ **政府办公** - 公文、证件打印
|
||||
- ✅ **教育系统** - 成绩单、证书打印
|
||||
|
||||
### **部署建议**
|
||||
1. **开发环境**:本地安装CLodop服务
|
||||
2. **测试环境**:内网服务器部署
|
||||
3. **生产环境**:高可用集群部署,配合负载均衡
|
||||
|
||||
CLodop 是解决Web打印难题的优秀方案,特别适合需要精确控制打印格式的企业级应用!
|
||||
Reference in New Issue
Block a user