erp-frontend/plugins/print-plugin-client.js
2026-04-06 21:14:31 +08:00

281 lines
9.1 KiB
JavaScript
Executable File

/**
* 打印插件客户端 - 模拟版本
*
* 功能:
* 1. 注册到ERP系统
* 2. 发送心跳
* 3. 获取打印任务
* 4. 模拟打印
*
* 使用方法:
* node print-plugin-client.js <命令> [参数]
*
* 示例:
* node print-plugin-client.js register cainiao
* node print-plugin-client.js heartbeat
* node print-plugin-client.js getjob
*/
const http = require('http');
// 配置
const CONFIG = {
API_BASE: 'http://localhost:10088/api', // 后端API地址
DEVICE_ID: 'PLUGIN-' + Date.now().toString(36).toUpperCase(),
DEVICE_NAME: process.env.COMPUTERNAME || 'Unknown-PC',
OS_VERSION: process.release.name + ' ' + process.platform,
POLL_INTERVAL: 5000, // 5秒轮询一次
};
// 模拟插件信息
const PLUGIN_INFO = {
cainiao: { code: 'cainiao', name: '菜鸟打印插件', version: '2.5.8' },
pdd: { code: 'pdd', name: '拼多多打印插件', version: '1.8.3' },
douyin: { code: 'douyin', name: '抖音小店打印插件', version: '3.2.1' },
kuaishou: { code: 'kuaishou', name: '快手小店打印插件', version: '2.1.5' },
};
// API请求封装
function apiRequest(method, path, data = null) {
return new Promise((resolve, reject) => {
const url = new URL(path, CONFIG.API_BASE);
const options = {
hostname: url.hostname,
port: url.port || 80,
path: url.pathname + url.search,
method: method,
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json',
}
};
const req = http.request(options, (res) => {
let body = '';
res.on('data', chunk => body += chunk);
res.on('end', () => {
try {
resolve(JSON.parse(body));
} catch {
resolve(body);
}
});
});
req.on('error', (err) => {
// API不可用时返回模拟数据
resolve({ code: 200, data: getMockResponse(method, path, data) });
});
if (data) {
req.write(JSON.stringify(data));
}
req.end();
});
}
// 模拟API响应
function getMockResponse(method, path, data) {
if (path.includes('/heartbeat')) {
return { success: true };
}
if (path.includes('/register')) {
return {
success: true,
installation_id: Date.now(),
has_update: false,
latest_version: '2.5.8'
};
}
if (path.includes('/next-job')) {
// 模拟返回打印任务
return {
id: Math.floor(Math.random() * 1000),
job_no: 'PJ' + Date.now().toString().slice(-10),
platform: 'pdd',
plugin_code: 'pdd',
print_data: {
receiverName: '张三',
receiverPhone: '138****8000',
receiverAddress: '北京市朝阳区某某街道某某小区',
expressNo: 'SF' + Math.random().toString().slice(2, 14),
goodsName: '商品测试',
quantity: 1,
},
status: 'pending',
priority: 0,
};
}
return {};
}
// 打印任务到控制台
function printJob(job) {
console.log('\n╔══════════════════════════════════════════════╗');
console.log('║ 🎯 收到打印任务 ║');
console.log('╠══════════════════════════════════════════════╣');
console.log(`║ 任务编号: ${job.job_no.padEnd(30)}`);
console.log(`║ 平台: ${job.platform.padEnd(36)}`);
console.log(`║ 收件人: ${(job.print_data?.receiverName || '-').padEnd(34)}`);
console.log(`║ 电话: ${(job.print_data?.receiverPhone || '-').padEnd(35)}`);
console.log(`║ 地址: ${(job.print_data?.receiverAddress || '-').substring(0, 30).padEnd(30)}`);
console.log(`║ 快递单号: ${(job.print_data?.expressNo || '-').padEnd(31)}`);
console.log('╠══════════════════════════════════════════════╣');
console.log('║ 📄 正在模拟打印... ║');
return new Promise((resolve) => {
setTimeout(() => {
console.log('║ ✅ 打印完成! ║');
console.log('╚══════════════════════════════════════════════╝\n');
resolve(true);
}, 1500);
});
}
// 命令处理
async function handleCommand(cmd, args) {
switch (cmd) {
case 'register':
await registerPlugin(args[0] || 'cainiao');
break;
case 'heartbeat':
await sendHeartbeat();
break;
case 'getjob':
await getNextJob();
break;
case 'daemon':
await runDaemon(args[0] || 'cainiao');
break;
case 'info':
showInfo();
break;
default:
showHelp();
}
}
// 注册插件
async function registerPlugin(pluginCode) {
const plugin = PLUGIN_INFO[pluginCode] || PLUGIN_INFO.cainiao;
console.log(`\n📦 正在注册 ${plugin.name}...`);
console.log(` 设备ID: ${CONFIG.DEVICE_ID}`);
console.log(` 设备名称: ${CONFIG.DEVICE_NAME}`);
console.log(` 插件版本: ${plugin.version}`);
const result = await apiRequest('POST', '/print-plugins/auth/register', {
plugin_code: plugin.code,
version: plugin.version,
device_id: CONFIG.DEVICE_ID,
device_name: CONFIG.DEVICE_NAME,
os_version: CONFIG.OS_VERSION,
});
if (result.success || result.code === 200) {
console.log('✅ 注册成功!');
console.log(` 安装ID: ${result.installation_id}`);
if (result.has_update) {
console.log(` ⚠️ 有新版本: ${result.latest_version}`);
}
} else {
console.log('❌ 注册失败:', result.message || '未知错误');
}
}
// 发送心跳
async function sendHeartbeat() {
const result = await apiRequest('POST', '/print-plugins/auth/heartbeat', {
device_id: CONFIG.DEVICE_ID,
});
if (result.success || result.code === 200) {
console.log('💓 心跳发送成功');
} else {
console.log('❌ 心跳失败');
}
}
// 获取打印任务
async function getNextJob() {
const result = await apiRequest('GET', `/print-device/next-job?device_id=${CONFIG.DEVICE_ID}`);
if (result && result.id) {
await printJob(result);
// 标记完成
await apiRequest('POST', '/print-device/complete', {
job_id: result.id,
device_id: CONFIG.DEVICE_ID,
});
} else {
console.log('📭 暂无打印任务');
}
}
// 运行守护进程
async function runDaemon(pluginCode) {
const plugin = PLUGIN_INFO[pluginCode] || PLUGIN_INFO.cainiao;
console.log('\n🚀 启动打印插件守护进程...');
console.log(` 插件: ${plugin.name}`);
console.log(` 轮询间隔: ${CONFIG.POLL_INTERVAL / 1000}`);
console.log(' 按 Ctrl+C 停止\n');
// 先注册
await registerPlugin(pluginCode);
// 启动心跳
setInterval(async () => {
await sendHeartbeat();
}, 30000);
// 轮询打印任务
setInterval(async () => {
await getNextJob();
}, CONFIG.POLL_INTERVAL);
}
// 显示信息
function showInfo() {
console.log('\n📋 插件客户端信息');
console.log('═══════════════════════════════');
console.log(` 设备ID: ${CONFIG.DEVICE_ID}`);
console.log(` 设备名称: ${CONFIG.DEVICE_NAME}`);
console.log(` 操作系统: ${CONFIG.OS_VERSION}`);
console.log(` API地址: ${CONFIG.API_BASE}`);
console.log(` 轮询间隔: ${CONFIG.POLL_INTERVAL / 1000}`);
console.log('═══════════════════════════════════════\n');
}
// 帮助
function showHelp() {
console.log(`
🔌 打印插件客户端 - 使用说明
用法: node print-plugin-client.js <命令> [参数]
命令:
register <插件> 注册插件 (cainiao|pdd|douyin|kuaishou)
heartbeat 发送心跳
getjob 获取一个打印任务
daemon <插件> 运行守护进程模式
info 显示客户端信息
help 显示帮助
示例:
node print-plugin-client.js register cainiao
node print-plugin-client.js daemon pdd
node print-plugin-client.js info
注意:
- 默认API地址为 http://localhost:10088/api
- 如需修改,请编辑 CONFIG.API_BASE
- 守护进程模式会自动注册并每30秒发送心跳
`);
}
// 主入口
const [,, cmd, ...args] = process.argv;
handleCommand(cmd, args).catch(console.error);