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

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