You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

341 lines
9.5 KiB

/**
* 打印工具类
* 提供统一的打印功能接口
*/
import { getUserLabelPrinters, printLabel } from '@/api/labelSetting/label_setting.js'
/**
* 打印配置类
*/
export class PrintConfig {
constructor(options = {}) {
this.zplCode = options.zplCode || ''
this.reportId = options.reportId || ''
this.paperSize = options.paperSize || ''
this.orientation = options.orientation || 'portrait'
this.dpi = options.dpi || 203
this.copies = options.copies || 1
this.printerName = options.printerName || ''
this.printerIP = options.printerIP || ''
}
/**
* 验证配置是否有效
*/
validate() {
if (!this.zplCode || this.zplCode.trim() === '') {
throw new Error('ZPL代码不能为空')
}
return true
}
}
/**
* 打印服务类
*/
export class PrintService {
constructor(vue) {
this.vue = vue
this.loading = false
}
/**
* 获取用户打印机列表
*/
async getUserPrinters() {
try {
const { data } = await getUserLabelPrinters({
userId: localStorage.getItem('userName'),
username: localStorage.getItem('userName'),
site: this.vue.$store.state.user.site
})
return data.rows || []
} catch (error) {
console.error('获取打印机列表失败:', error)
throw new Error('获取打印机列表失败')
}
}
/**
* 服务器打印
*/
async printViaServer(config) {
config.validate()
const printRequest = {
reportId: config.reportId,
zplCode: config.zplCode,
printerName: config.printerName,
copies: config.copies,
paperSize: config.paperSize,
orientation: config.orientation,
dpi: config.dpi,
userId: localStorage.getItem('userName'),
username: localStorage.getItem('userName'),
site: this.vue.$store.state.user.site
}
try {
const { data } = await printLabel(printRequest)
if (data.code === 200) {
return {
success: true,
message: `打印任务已发送!打印机: ${config.printerName}, 份数: ${config.copies}`
}
} else {
throw new Error(data.msg || '打印失败')
}
} catch (error) {
throw new Error(`服务器打印失败: ${error.message || error}`)
}
}
/**
* 网络直连打印
*/
async printViaNetwork(config) {
config.validate()
if (!config.printerIP) {
throw new Error('打印机IP地址不能为空')
}
try {
// 发送多份打印
for (let i = 0; i < config.copies; i++) {
await fetch(`http://${config.printerIP}:9100`, {
method: 'POST',
headers: {
'Content-Type': 'text/plain',
},
body: config.zplCode,
mode: 'no-cors'
})
}
return {
success: true,
message: `打印任务已发送到 ${config.printerIP}, 份数: ${config.copies}`
}
} catch (error) {
throw new Error(`网络打印失败: ${error.message}`)
}
}
/**
* 显示打印机选择对话框
*/
async showPrinterDialog(printers, defaultCopies = 1) {
return new Promise((resolve, reject) => {
const h = this.vue.$createElement
let selectedPrinter = printers.length > 0 ? printers[0].printerName : ''
let copies = defaultCopies
this.vue.$msgbox({
title: '服务器打印设置',
message: h('div', [
h('div', { style: 'margin-bottom: 15px;' }, [
h('label', { style: 'display: block; margin-bottom: 5px; font-weight: bold;' }, '选择打印机:'),
h('el-select', {
props: {
value: selectedPrinter,
placeholder: '请选择打印机',
style: 'width: 100%;'
},
on: {
input: (val) => { selectedPrinter = val }
}
}, printers.map(printer =>
h('el-option', {
props: {
key: printer.printerName,
label: `${printer.printerName} (${printer.ipAddress})`,
value: printer.printerName
}
})
))
]),
h('div', { style: 'margin-bottom: 15px;' }, [
h('label', { style: 'display: block; margin-bottom: 5px; font-weight: bold;' }, '打印份数:'),
h('el-input', {
props: {
value: copies,
min: 1,
max: 99,
size: 'mini',
style: 'width: 100%;'
},
on: {
input: (val) => { copies = val }
}
})
])
]),
showCancelButton: true,
confirmButtonText: '开始打印',
cancelButtonText: '取消'
}).then(() => {
if (!selectedPrinter) {
reject(new Error('请选择打印机'))
return
}
resolve({ printerName: selectedPrinter, copies })
}).catch(() => {
reject(new Error('用户取消打印'))
})
})
}
/**
* 显示网络打印机IP输入对话框
*/
async showNetworkDialog() {
return new Promise((resolve, reject) => {
this.vue.$prompt('请输入打印机IP地址', '直接网络打印', {
confirmButtonText: '打印',
cancelButtonText: '取消',
inputPattern: /^(\d{1,3}\.){3}\d{1,3}$/,
inputErrorMessage: '请输入正确的IP地址格式',
inputPlaceholder: '例如: 192.168.1.100',
inputValue: localStorage.getItem('localPrinterIP') || ''
}).then(({ value }) => {
localStorage.setItem('localPrinterIP', value)
resolve(value)
}).catch(() => {
reject(new Error('用户取消打印'))
})
})
}
}
/**
* 快速打印函数 - 显示打印方式选择对话框
*/
export async function quickPrint(vue, config) {
const printConfig = new PrintConfig(config)
const printService = new PrintService(vue)
return new Promise((resolve, reject) => {
// 显示打印方式选择对话框
const h = vue.$createElement
vue.$msgbox({
title: '选择打印方式',
message: h('div', { class: 'print-options' }, [
h('div', { class: 'option-description' }, [
h('i', { class: 'el-icon-info' }),
h('span', '请选择适合您环境的打印方式')
]),
h('div', { class: 'print-methods' }, [
h('div', {
class: 'print-method recommended',
on: {
click: () => handleServerPrint()
}
}, [
h('div', { class: 'method-icon' }, [
h('i', { class: 'el-icon-s-platform' })
]),
h('div', { class: 'method-content' }, [
h('h4', '服务器打印'),
h('p', '通过WMS系统管理打印任务,支持打印机配置和权限控制'),
h('div', { class: 'method-badge' }, '推荐')
]),
h('div', { class: 'method-arrow' }, [
h('i', { class: 'el-icon-arrow-right' })
])
]),
h('div', {
class: 'print-method',
on: {
click: () => handleNetworkPrint()
}
}, [
h('div', { class: 'method-icon' }, [
h('i', { class: 'el-icon-connection' })
]),
h('div', { class: 'method-content' }, [
h('h4', '直接网络打印'),
h('p', '直接连接网络打印机,适合简单的网络环境')
]),
h('div', { class: 'method-arrow' }, [
h('i', { class: 'el-icon-arrow-right' })
])
])
])
]),
showCancelButton: true,
confirmButtonText: '',
cancelButtonText: '取消',
showConfirmButton: false
}).catch(() => {
reject(new Error('用户取消打印'))
})
// 处理服务器打印
async function handleServerPrint() {
vue.$msgbox.close()
try {
const printers = await printService.getUserPrinters()
if (printers.length === 0) {
vue.$confirm(
'您还没有配置打印机,是否前往配置?',
'未找到打印机',
{
confirmButtonText: '去配置',
cancelButtonText: '取消',
type: 'warning'
}
).then(() => {
vue.$message.warning('请联系管理员配置打印机')
})
return
}
const { printerName, copies } = await printService.showPrinterDialog(printers, printConfig.copies)
printConfig.printerName = printerName
printConfig.copies = copies
const result = await printService.printViaServer(printConfig)
vue.$message.success(result.message)
resolve(result)
} catch (error) {
vue.$message.error(error.message)
reject(error)
}
}
// 处理网络打印
async function handleNetworkPrint() {
vue.$msgbox.close()
try {
const printerIP = await printService.showNetworkDialog()
printConfig.printerIP = printerIP
const result = await printService.printViaNetwork(printConfig)
vue.$message.success(result.message)
resolve(result)
} catch (error) {
vue.$message.error(error.message)
reject(error)
}
}
})
}
/**
* 创建打印服务实例
*/
export function createPrintService(vue) {
return new PrintService(vue)
}
export default {
PrintConfig,
PrintService,
quickPrint,
createPrintService
}