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.
543 lines
12 KiB
543 lines
12 KiB
<template>
|
|
<div class="print-service">
|
|
<!-- 打印方式选择对话框 -->
|
|
<el-dialog
|
|
title="选择打印方式"
|
|
:visible.sync="printDialogVisible"
|
|
width="480px"
|
|
:close-on-click-modal="false"
|
|
class="print-dialog"
|
|
>
|
|
<div class="print-options">
|
|
<div class="option-description">
|
|
<i class="el-icon-info"></i>
|
|
<span>请选择适合您环境的打印方式</span>
|
|
</div>
|
|
|
|
<div class="print-methods">
|
|
<div class="print-method recommended" @click="selectPrintMethod('server')">
|
|
<div class="method-icon">
|
|
<i class="el-icon-s-platform"></i>
|
|
</div>
|
|
<div class="method-content">
|
|
<h4>服务器打印</h4>
|
|
<p>通过WMS系统管理打印任务,支持打印机配置和权限控制</p>
|
|
<div class="method-badge">推荐</div>
|
|
</div>
|
|
<div class="method-arrow">
|
|
<i class="el-icon-arrow-right"></i>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="print-method" @click="selectPrintMethod('network')">
|
|
<div class="method-icon">
|
|
<i class="el-icon-connection"></i>
|
|
</div>
|
|
<div class="method-content">
|
|
<h4>直接网络打印</h4>
|
|
<p>直接连接网络打印机,适合简单的网络环境</p>
|
|
</div>
|
|
<div class="method-arrow">
|
|
<i class="el-icon-arrow-right"></i>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div slot="footer" class="dialog-footer">
|
|
<el-button @click="printDialogVisible = false">取消</el-button>
|
|
</div>
|
|
</el-dialog>
|
|
|
|
<!-- 打印机选择对话框 -->
|
|
<el-dialog
|
|
title="服务器打印设置"
|
|
:visible.sync="printerSelectionVisible"
|
|
width="350px"
|
|
:close-on-click-modal="false"
|
|
class="printer-selection-dialog"
|
|
>
|
|
<div class="printer-selection-content">
|
|
<div class="form-item">
|
|
<label class="form-label">选择打印机:</label>
|
|
<el-select
|
|
v-model="selectedPrinter"
|
|
placeholder="请选择打印机"
|
|
style="width: 100%;"
|
|
>
|
|
<el-option
|
|
v-for="printer in availablePrinters"
|
|
:key="printer.printerName"
|
|
:label="`${printer.printerName} (${printer.ipAddress})`"
|
|
:value="printer.printerName"
|
|
/>
|
|
</el-select>
|
|
</div>
|
|
|
|
<div class="form-item">
|
|
<label class="form-label">打印份数:</label>
|
|
<el-input
|
|
v-model.number="printCopies"
|
|
:min="1"
|
|
:max="1"
|
|
size="mini"
|
|
style="width: 100%;"
|
|
/>
|
|
</div>
|
|
</div>
|
|
|
|
<div slot="footer" class="dialog-footer">
|
|
<el-button @click="printerSelectionVisible = false">取消</el-button>
|
|
<el-button type="primary" @click="confirmPrint" :disabled="!selectedPrinter">开始打印</el-button>
|
|
</div>
|
|
</el-dialog>
|
|
</div>
|
|
</template>
|
|
|
|
<script>
|
|
import { getUserLabelPrinters, printLabel } from '@/api/labelSetting/label_setting.js'
|
|
|
|
export default {
|
|
name: 'PrintService',
|
|
props: {
|
|
// 是否显示打印对话框
|
|
visible: {
|
|
type: Boolean,
|
|
default: false
|
|
},
|
|
// ZPL代码
|
|
zplCode: {
|
|
type: String,
|
|
required: true
|
|
},
|
|
// 报告ID(可选)
|
|
reportId: {
|
|
type: String,
|
|
default: ''
|
|
},
|
|
// 纸张尺寸(可选)
|
|
paperSize: {
|
|
type: String,
|
|
default: ''
|
|
},
|
|
// 打印方向(可选)
|
|
orientation: {
|
|
type: String,
|
|
default: 'portrait'
|
|
},
|
|
// DPI(可选)
|
|
dpi: {
|
|
type: Number,
|
|
default: 203
|
|
}
|
|
},
|
|
data() {
|
|
return {
|
|
printLoading: false,
|
|
printerSelectionVisible: false,
|
|
availablePrinters: [],
|
|
selectedPrinter: '',
|
|
printCopies: 1
|
|
}
|
|
},
|
|
computed: {
|
|
printDialogVisible: {
|
|
get() {
|
|
return this.visible
|
|
},
|
|
set(value) {
|
|
this.$emit('update:visible', value)
|
|
}
|
|
}
|
|
},
|
|
methods: {
|
|
/**
|
|
* 开始打印流程
|
|
*/
|
|
async startPrint() {
|
|
if (!this.zplCode || this.zplCode.trim() === '') {
|
|
this.$message.warning('没有可打印的内容')
|
|
return
|
|
}
|
|
|
|
this.printDialogVisible = true
|
|
},
|
|
|
|
/**
|
|
* 选择打印方式
|
|
*/
|
|
selectPrintMethod(method) {
|
|
this.printDialogVisible = false
|
|
|
|
switch (method) {
|
|
case 'server':
|
|
this.showServerPrintDialog()
|
|
break
|
|
case 'network':
|
|
this.showNetworkPrinterDialog()
|
|
break
|
|
default:
|
|
console.warn('未知的打印方式:', method)
|
|
}
|
|
},
|
|
|
|
/**
|
|
* 显示服务器打印对话框
|
|
*/
|
|
async showServerPrintDialog() {
|
|
try {
|
|
// 获取用户可用的打印机列表
|
|
const { data } = await getUserLabelPrinters({
|
|
userId: localStorage.getItem('userName'),
|
|
username: localStorage.getItem('userName'),
|
|
site: this.$store.state.user.site
|
|
})
|
|
|
|
if (!data.rows || data.rows.length === 0) {
|
|
this.$confirm(
|
|
'您还没有配置打印机,是否前往配置?',
|
|
'未找到打印机',
|
|
{
|
|
confirmButtonText: '去配置',
|
|
cancelButtonText: '取消',
|
|
type: 'warning'
|
|
}
|
|
).then(() => {
|
|
this.$message.info('请联系管理员配置打印机')
|
|
})
|
|
return
|
|
}
|
|
|
|
// 显示打印机选择和份数设置对话框
|
|
this.showPrinterSelectionDialog(data.rows)
|
|
|
|
} catch (error) {
|
|
console.error('获取打印机列表失败:', error)
|
|
this.$message.error('获取打印机列表失败,请稍后重试')
|
|
}
|
|
},
|
|
|
|
/**
|
|
* 显示打印机选择对话框
|
|
*/
|
|
showPrinterSelectionDialog(printers) {
|
|
this.availablePrinters = printers
|
|
this.selectedPrinter = printers.length > 0 ? printers[0].printerName : ''
|
|
this.printCopies = 1
|
|
this.printerSelectionVisible = true
|
|
},
|
|
|
|
/**
|
|
* 确认打印
|
|
*/
|
|
confirmPrint() {
|
|
if (!this.selectedPrinter) {
|
|
this.$message.warning('请选择打印机')
|
|
return
|
|
}
|
|
|
|
this.printerSelectionVisible = false
|
|
this.printViaServer(this.selectedPrinter, this.printCopies)
|
|
},
|
|
|
|
/**
|
|
* 通过服务器打印
|
|
*/
|
|
async printViaServer(printerName, copies) {
|
|
this.printLoading = true
|
|
this.$emit('print-start')
|
|
|
|
try {
|
|
const printRequest = {
|
|
reportId: this.reportId,
|
|
zplCode: this.zplCode,
|
|
printerName: printerName,
|
|
copies: copies,
|
|
paperSize: this.paperSize,
|
|
orientation: this.orientation,
|
|
dpi: this.dpi,
|
|
userId: localStorage.getItem('userName'),
|
|
username: localStorage.getItem('userName'),
|
|
site: this.$store.state.user.site
|
|
}
|
|
|
|
const { data } = await printLabel(printRequest)
|
|
|
|
if (data.code === 200) {
|
|
this.$message.success(`打印任务已发送!打印机: ${printerName}, 份数: ${copies}`)
|
|
this.$emit('print-success', { printerName, copies })
|
|
} else {
|
|
throw new Error(data.msg || '打印失败')
|
|
}
|
|
|
|
} catch (error) {
|
|
console.error('服务器打印失败:', error)
|
|
this.$message.error(`打印失败: ${error.message || error}`)
|
|
this.$emit('print-error', error)
|
|
} finally {
|
|
this.printLoading = false
|
|
this.$emit('print-end')
|
|
}
|
|
},
|
|
|
|
/**
|
|
* 显示网络打印机对话框
|
|
*/
|
|
showNetworkPrinterDialog() {
|
|
this.$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)
|
|
this.printToNetworkPrinter(value)
|
|
}).catch(() => {
|
|
this.$message.info('已取消打印')
|
|
})
|
|
},
|
|
|
|
/**
|
|
* 直接网络打印
|
|
*/
|
|
async printToNetworkPrinter(printerIP) {
|
|
/*this.printLoading = true
|
|
this.$emit('print-start')
|
|
|
|
try {
|
|
|
|
|
|
} catch (error) {
|
|
console.error('网络打印失败:', error)
|
|
this.$message.error(`网络打印失败: ${error.message}`)
|
|
this.$emit('print-error', error)
|
|
} finally {
|
|
this.printLoading = false
|
|
this.$emit('print-end')
|
|
}*/
|
|
// 直接发送到网络打印机
|
|
//this.$emit('print-start')
|
|
await fetch(`http://${printerIP}:9100`, {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'text/plain',
|
|
},
|
|
body: this.zplCode,
|
|
mode: 'no-cors'
|
|
})
|
|
this.$message.success(`打印任务已发送到 ${printerIP}`)
|
|
//this.$emit('print-success', { printerIP })
|
|
console.log('网络打印成功:', {
|
|
printerIP,
|
|
zplCode: this.zplCode,
|
|
paperSize: this.paperSize,
|
|
orientation: this.orientation,
|
|
dpi: this.dpi
|
|
})
|
|
//this.$emit('print-end')
|
|
}
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<style scoped>
|
|
/* 打印对话框样式 */
|
|
.print-options {
|
|
padding: 10px 0;
|
|
}
|
|
|
|
.option-description {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 8px;
|
|
margin-bottom: 20px;
|
|
padding: 12px;
|
|
background: #f0f9ff;
|
|
border: 1px solid #e0f2fe;
|
|
border-radius: 8px;
|
|
color: #0369a1;
|
|
font-size: 14px;
|
|
}
|
|
|
|
.option-description i {
|
|
font-size: 16px;
|
|
color: #0284c7;
|
|
}
|
|
|
|
.print-methods {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 12px;
|
|
}
|
|
|
|
.print-method {
|
|
display: flex;
|
|
align-items: center;
|
|
padding: 16px;
|
|
border: 2px solid #e5e7eb;
|
|
border-radius: 12px;
|
|
cursor: pointer;
|
|
transition: all 0.3s ease;
|
|
background: #ffffff;
|
|
position: relative;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.print-method:hover {
|
|
border-color: #3b82f6;
|
|
box-shadow: 0 4px 12px rgba(59, 130, 246, 0.15);
|
|
transform: translateY(-2px);
|
|
}
|
|
|
|
.print-method.recommended {
|
|
border-color: #10b981;
|
|
background: linear-gradient(135deg, #f0fdf4 0%, #ffffff 100%);
|
|
}
|
|
|
|
.print-method.recommended:hover {
|
|
border-color: #059669;
|
|
box-shadow: 0 4px 12px rgba(16, 185, 129, 0.2);
|
|
}
|
|
|
|
.method-icon {
|
|
flex-shrink: 0;
|
|
width: 48px;
|
|
height: 48px;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
border-radius: 12px;
|
|
margin-right: 16px;
|
|
background: #f3f4f6;
|
|
color: #6b7280;
|
|
font-size: 20px;
|
|
transition: all 0.3s ease;
|
|
}
|
|
|
|
.print-method:hover .method-icon {
|
|
background: #3b82f6;
|
|
color: white;
|
|
transform: scale(1.1);
|
|
}
|
|
|
|
.print-method.recommended .method-icon {
|
|
background: #10b981;
|
|
color: white;
|
|
}
|
|
|
|
.print-method.recommended:hover .method-icon {
|
|
background: #059669;
|
|
}
|
|
|
|
.method-content {
|
|
flex: 1;
|
|
position: relative;
|
|
}
|
|
|
|
.method-content h4 {
|
|
margin: 0 0 6px 0;
|
|
font-size: 16px;
|
|
font-weight: 600;
|
|
color: #1f2937;
|
|
line-height: 1.2;
|
|
}
|
|
|
|
.method-content p {
|
|
margin: 0;
|
|
font-size: 13px;
|
|
color: #6b7280;
|
|
line-height: 1.4;
|
|
}
|
|
|
|
.method-badge {
|
|
position: absolute;
|
|
top: -2px;
|
|
right: 0;
|
|
background: #10b981;
|
|
color: white;
|
|
font-size: 11px;
|
|
font-weight: 600;
|
|
padding: 2px 8px;
|
|
border-radius: 12px;
|
|
text-transform: uppercase;
|
|
letter-spacing: 0.5px;
|
|
}
|
|
|
|
.method-arrow {
|
|
flex-shrink: 0;
|
|
margin-left: 12px;
|
|
color: #9ca3af;
|
|
font-size: 16px;
|
|
transition: all 0.3s ease;
|
|
}
|
|
|
|
.print-method:hover .method-arrow {
|
|
color: #3b82f6;
|
|
transform: translateX(4px);
|
|
}
|
|
|
|
.print-method.recommended:hover .method-arrow {
|
|
color: #10b981;
|
|
}
|
|
|
|
.dialog-footer {
|
|
text-align: center;
|
|
padding-top: 10px;
|
|
}
|
|
|
|
/* 打印机选择对话框样式 */
|
|
.printer-selection-content {
|
|
padding: 10px 0;
|
|
}
|
|
|
|
.form-item {
|
|
margin-bottom: 20px;
|
|
}
|
|
|
|
.form-label {
|
|
display: block;
|
|
margin-bottom: 8px;
|
|
font-weight: 600;
|
|
color: #303133;
|
|
font-size: 14px;
|
|
}
|
|
|
|
.form-hint {
|
|
margin-top: 6px;
|
|
font-size: 12px;
|
|
color: #909399;
|
|
line-height: 1.4;
|
|
}
|
|
|
|
/* 响应式设计 */
|
|
@media (max-width: 600px) {
|
|
.print-method {
|
|
padding: 12px;
|
|
}
|
|
|
|
.method-icon {
|
|
width: 40px;
|
|
height: 40px;
|
|
margin-right: 12px;
|
|
font-size: 18px;
|
|
}
|
|
|
|
.method-content h4 {
|
|
font-size: 15px;
|
|
}
|
|
|
|
.method-content p {
|
|
font-size: 12px;
|
|
}
|
|
|
|
.printer-selection-content {
|
|
padding: 5px 0;
|
|
}
|
|
|
|
.form-label {
|
|
font-size: 13px;
|
|
}
|
|
}
|
|
</style>
|