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
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
|
|
}
|