1074 lines
30 KiB
Vue
1074 lines
30 KiB
Vue
<template>
|
||
<div class="app-container">
|
||
<el-row :gutter="20">
|
||
<!-- 左侧区域 -->
|
||
<el-col :span="8">
|
||
<!-- 表单区域 -->
|
||
<div class="form-container">
|
||
<div class="section-header">
|
||
<h3>生成条码</h3>
|
||
</div>
|
||
<el-form ref="form" :model="form" :rules="rules" label-width="80px">
|
||
<el-row :gutter="20">
|
||
<el-col
|
||
v-for="field in formFields"
|
||
:key="field.prop"
|
||
:span="24"
|
||
>
|
||
<el-form-item :label="field.label" :prop="field.prop">
|
||
<el-input
|
||
v-model="form[field.prop]"
|
||
:placeholder="field.placeholder"
|
||
:disabled="loading"
|
||
:readonly="field.readonly"
|
||
@click.native="field.prop === 'spare4' && openProductSelect()"
|
||
/>
|
||
</el-form-item>
|
||
</el-col>
|
||
</el-row>
|
||
<el-form-item class="form-actions">
|
||
<el-button
|
||
type="warning"
|
||
@click="handlePreview"
|
||
:loading="previewLoading"
|
||
icon="el-icon-view"
|
||
>
|
||
预览
|
||
</el-button>
|
||
<el-button
|
||
@click="resetForm"
|
||
icon="el-icon-refresh"
|
||
>
|
||
重置
|
||
</el-button>
|
||
</el-form-item>
|
||
</el-form>
|
||
</div>
|
||
</el-col>
|
||
|
||
<!-- 打印专用区域(修改隐藏方式,避免display:none导致二维码渲染失败) -->
|
||
<vue-easy-print ref="easyPrint2" class="print-container">
|
||
<div v-for="(item, index) in previewDataList" :key="index" style="page-break-after:always">
|
||
<div class="preview-box">
|
||
<div class="preview-content">
|
||
<div class="preview-row">
|
||
<span class="preview-label">MODEL:</span>
|
||
<span class="preview-value">{{ item.model }}</span>
|
||
</div>
|
||
<div class="preview-row">
|
||
<span class="preview-label">SERIAL:</span>
|
||
<span class="preview-value">{{ item.serial }}</span>
|
||
</div>
|
||
<div class="preview-row">
|
||
<span class="preview-label">COLOR:</span>
|
||
<span class="preview-value">{{ item.color }}</span>
|
||
</div>
|
||
<div class="preview-row">
|
||
<div class="preview-col">
|
||
<span class="preview-label">V:</span>
|
||
<span class="preview-value">{{ item.v }}</span>
|
||
</div>
|
||
<div class="preview-col">
|
||
<span class="preview-label">Hz:</span>
|
||
<span class="preview-value">{{ item.hz }}</span>
|
||
</div>
|
||
<div class="preview-col">
|
||
<span class="preview-label">PH:</span>
|
||
<span class="preview-value">{{ item.ph }}</span>
|
||
</div>
|
||
</div>
|
||
<div class="preview-row">
|
||
<div class="preview-col">
|
||
<span class="preview-label">N.W.:</span>
|
||
<span class="preview-value">{{ item.nW }}</span>
|
||
</div>
|
||
<div class="preview-col">
|
||
<span class="preview-label">G.W.:</span>
|
||
<span class="preview-value">{{ item.gW }}</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="qrcode-container">
|
||
<vue-qr
|
||
:key="`qr-${index}-${item.serial}`"
|
||
:text="item.qrCode"
|
||
:size="100"
|
||
:margin="0"
|
||
:correctLevel="2"
|
||
:callback="onQrReady"
|
||
:qid="String(index)"
|
||
/>
|
||
<img v-if="item.qrDataUrl" :src="item.qrDataUrl" :width="100" :height="100" />
|
||
<div class="qrcode-label">{{ item.spare4 }}</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</vue-easy-print>
|
||
|
||
<!-- 右侧预览区域 -->
|
||
<el-col :span="16">
|
||
<!-- 预览弹框 -->
|
||
<el-dialog
|
||
title="标签预览"
|
||
:visible.sync="showPreview"
|
||
width="800px"
|
||
:close-on-click-modal="false"
|
||
append-to-body
|
||
>
|
||
<div class="preview-container">
|
||
<div class="label-content">
|
||
<div class="preview-box">
|
||
<div class="preview-content">
|
||
<div class="preview-row">
|
||
<span class="preview-label">MODEL:</span>
|
||
<span class="preview-value">{{ previewData.model }}</span>
|
||
</div>
|
||
<div class="preview-row">
|
||
<span class="preview-label">SERIAL:</span>
|
||
<span class="preview-value">{{ previewData.serial }}</span>
|
||
</div>
|
||
<div class="preview-row">
|
||
<span class="preview-label">COLOR:</span>
|
||
<span class="preview-value">{{ previewData.color }}</span>
|
||
</div>
|
||
<div class="preview-row">
|
||
<div class="preview-col">
|
||
<span class="preview-label">V:</span>
|
||
<span class="preview-value">{{ previewData.v }}</span>
|
||
</div>
|
||
<div class="preview-col">
|
||
<span class="preview-label">Hz:</span>
|
||
<span class="preview-value">{{ previewData.hz }}</span>
|
||
</div>
|
||
<div class="preview-col">
|
||
<span class="preview-label">PH:</span>
|
||
<span class="preview-value">{{ previewData.ph }}</span>
|
||
</div>
|
||
</div>
|
||
<div class="preview-row">
|
||
<div class="preview-col">
|
||
<span class="preview-label">N.W.:</span>
|
||
<span class="preview-value">{{ previewData.nW }}</span>
|
||
</div>
|
||
<div class="preview-col">
|
||
<span class="preview-label">G.W.:</span>
|
||
<span class="preview-value">{{ previewData.gW }}</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<!-- 二维码区域 -->
|
||
<div class="qrcode-container">
|
||
<vue-qr
|
||
:text="qrCodeValue(previewData)"
|
||
:size="200"
|
||
:margin="0"
|
||
:correctLevel="2"
|
||
error-correction-level="M"
|
||
/>
|
||
<div class="qrcode-label">{{ previewData.spare4 }}</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div slot="footer" class="dialog-footer">
|
||
<el-button @click="showPreview = false">关 闭</el-button>
|
||
<el-button type="primary" @click="submitForm" :loading="submitLoading">保存</el-button>
|
||
</div>
|
||
</el-dialog>
|
||
|
||
<!-- 历史数据区域 -->
|
||
<div class="list-container" style="padding-bottom: 60px;">
|
||
<div class="section-header" style="margin-bottom: 20px;">
|
||
<h3>打印数据</h3>
|
||
<!-- <div class="header-actions">
|
||
<el-button
|
||
type="info"
|
||
size="small"
|
||
@click="getProductCode"
|
||
:disabled="!hasSelection"
|
||
icon="el-icon-delete"
|
||
>
|
||
获取条码数据
|
||
</el-button>
|
||
</div>-->
|
||
<div class="header-actions">
|
||
<el-button
|
||
type="danger"
|
||
size="small"
|
||
@click="handleBatchDelete"
|
||
:disabled="!hasSelection"
|
||
icon="el-icon-delete"
|
||
>
|
||
批量删除
|
||
</el-button>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 搜索框区域 -->
|
||
<div class="search-box" style="margin-bottom: 20px; border: 1px solid #ebeef5; padding: 15px; background-color: #fff; border-radius: 4px;">
|
||
<div style="display: flex; align-items: center;">
|
||
<div style="font-weight: bold; margin-right: 10px; min-width: 60px;">订单号</div>
|
||
<el-input
|
||
v-model="queryParams.spare1"
|
||
placeholder="请输入订单号"
|
||
clearable
|
||
style="width: 240px; margin-right: 10px;"
|
||
@keyup.enter.native="handleQuery"
|
||
/>
|
||
<el-button type="primary" icon="el-icon-search" @click="handleQuery" style="margin-right: 10px;">搜索</el-button>
|
||
<el-button icon="el-icon-refresh" @click="resetQuery">重置</el-button>
|
||
<el-button icon="info" @click="handleErpData">获取订单数据</el-button>
|
||
</div>
|
||
</div>
|
||
|
||
<el-table
|
||
ref="table"
|
||
v-loading="loading"
|
||
:data="tableData"
|
||
@selection-change="handleSelectionChange"
|
||
stripe
|
||
border
|
||
style="width: 100%;margin-bottom: 40px;height: 575px;"
|
||
>
|
||
<el-table-column type="selection" width="55" align="center"/>
|
||
<el-table-column
|
||
v-for="column in tableColumns"
|
||
:key="column.prop"
|
||
:label="column.label"
|
||
:prop="column.prop"
|
||
:width="column.width"
|
||
:formatter="column.formatter"
|
||
show-overflow-tooltip
|
||
/>
|
||
<el-table-column label="操作" width="260" align="center" fixed="right">
|
||
<template slot-scope="scope">
|
||
<el-button size="mini" type="text" @click="handleEdit(scope.row)" icon="el-icon-edit">编辑</el-button>
|
||
<!-- <el-button size="mini" type="text" @click="handleErpData(scope.row)" icon="el-icon-edit">补全数据-->
|
||
<!-- </el-button>-->
|
||
<el-button size="mini" type="text" @click="handlePrint(scope.row)" icon="el-icon-printer">打印</el-button>
|
||
<el-button size="mini" type="text" @click="handleDelete(scope.row)" icon="el-icon-delete" class="danger-text">删除</el-button>
|
||
</template>
|
||
</el-table-column>
|
||
</el-table>
|
||
|
||
<pagination
|
||
v-show="total > 0"
|
||
:total="total"
|
||
:page.sync="queryParams.pageNum"
|
||
:limit.sync="queryParams.pageSize"
|
||
@pagination="getList"
|
||
/>
|
||
</div>
|
||
</el-col>
|
||
</el-row>
|
||
|
||
<!-- 物资选择弹框 -->
|
||
<el-dialog
|
||
title="选择物资"
|
||
:visible.sync="productSelectVisible"
|
||
width="800px"
|
||
append-to-body
|
||
>
|
||
<div class="search-container">
|
||
<el-form :model="productQueryParams" ref="queryForm" :inline="true">
|
||
<el-form-item label="品号" prop="productId">
|
||
<el-input
|
||
v-model="productQueryParams.productId"
|
||
placeholder="请输入品号"
|
||
clearable
|
||
size="small"
|
||
@keyup.enter.native="handleProductQuery"
|
||
/>
|
||
</el-form-item>
|
||
<el-form-item label="品名" prop="productName">
|
||
<el-input
|
||
v-model="productQueryParams.productName"
|
||
placeholder="请输入品名"
|
||
clearable
|
||
size="small"
|
||
@keyup.enter.native="handleProductQuery"
|
||
/>
|
||
</el-form-item>
|
||
<el-form-item>
|
||
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleProductQuery">搜索</el-button>
|
||
<el-button icon="el-icon-refresh" size="mini" @click="resetProductQuery">重置</el-button>
|
||
</el-form-item>
|
||
</el-form>
|
||
</div>
|
||
|
||
<el-table
|
||
v-loading="productTableLoading"
|
||
:data="productTableData"
|
||
@row-click="handleProductSelect"
|
||
highlight-current-row
|
||
style="width: 100%"
|
||
>
|
||
<el-table-column type="index" width="50" align="center" />
|
||
<el-table-column label="品号" align="center" prop="productId"/>
|
||
<el-table-column label="品名" align="center" prop="productName"/>
|
||
<el-table-column label="规格" align="center" prop="spec"/>
|
||
<el-table-column label="单位" align="center" prop="unit"/>
|
||
<el-table-column label="托盘尺寸" align="center" prop="spare10"/>
|
||
<el-table-column label="长" align="center" prop="spare36"/>
|
||
<el-table-column label="宽" align="center" prop="spare37"/>
|
||
<el-table-column label="高" align="center" prop="spare38"/>
|
||
</el-table>
|
||
<pagination
|
||
v-show="productTotal > 0"
|
||
:total="productTotal"
|
||
:page.sync="productQueryParams.pageNum"
|
||
:limit.sync="productQueryParams.pageSize"
|
||
@pagination="getProductList"
|
||
/>
|
||
</el-dialog>
|
||
</div>
|
||
</template>
|
||
|
||
<script>
|
||
import VueQr from 'vue-qr'
|
||
import VueEasyPrint from 'vue-easy-print'
|
||
import {
|
||
addBasProductCode,
|
||
delBasProductCode,
|
||
getErpProductCodeData,
|
||
listBasProductCode,
|
||
updateBasProductCode
|
||
} from "@/api/bas/BasProductCode"
|
||
import {listBasProduct} from "@/api/bas/BasProduct"
|
||
|
||
// 常量配置
|
||
const FORM_FIELDS = [
|
||
{ prop: 'spare4', label: '品号', placeholder: '点击选择品号', required: true, readonly: true },
|
||
{ prop: 'model', label: '型号', placeholder: '请输入型号', required: true },
|
||
{ prop: 'serial', label: '序列号', placeholder: '请输入序列号', required: true },
|
||
{ prop: 'color', label: '颜色', placeholder: '请输入颜色', required: true },
|
||
{ prop: 'v', label: '电压', placeholder: '请输入电压', required: true },
|
||
{ prop: 'hz', label: '功率', placeholder: '请输入功率' , required: true},
|
||
{ prop: 'ph', label: '相位', placeholder: '请输入相位' , required: true},
|
||
{ prop: 'nW', label: '净重', placeholder: '请输入净重', required: true },
|
||
{ prop: 'gW', label: '毛重', placeholder: '请输入毛重', required: true },
|
||
{ prop: 'spare1', label: '订单号', placeholder: '请输入订单号', required: true },
|
||
{ prop: 'spare2', label: '机型', placeholder: '请输入机型', required: true },
|
||
{prop: 'spare3', label: '分销', placeholder: '请输入分销', required: true},
|
||
{prop: 'spare5', label: '数量', placeholder: '请输入数量', required: true},
|
||
]
|
||
|
||
const TABLE_COLUMNS = [
|
||
{ prop: 'spare4', label: '品号', width: 140 },
|
||
{ prop: 'model', label: '型号', width: 120 },
|
||
{ prop: 'color', label: '颜色', width: 100 },
|
||
{ prop: 'serial', label: '序列号', width: 150 },
|
||
{ prop: 'v', label: '电压', width: 100 },
|
||
{ prop: 'hz', label: '功率', width: 100 },
|
||
{ prop: 'ph', label: '相位', width: 100 },
|
||
{ prop: 'nW', label: '净重', width: 100 },
|
||
{ prop: 'gW', label: '毛重', width: 100 },
|
||
{
|
||
prop: 'type',
|
||
label: '状态',
|
||
width: 100,
|
||
formatter: (row) => row.type === '1' ? '未打印' : '已打印'
|
||
},
|
||
{ prop: 'spare1', label: '订单号', width: 150 },
|
||
{ prop: 'spare2', label: '机型', width: 120 },
|
||
{prop: 'spare3', label: '分销', width: 100},
|
||
{prop: 'spare5', label: '数量', width: 100},
|
||
]
|
||
|
||
const DEFAULT_FORM = {
|
||
model: '',
|
||
color: '',
|
||
serial: '',
|
||
v: '',
|
||
hz: '',
|
||
ph: '',
|
||
nW: '',
|
||
gW: '',
|
||
type: '1',
|
||
spare1: '',
|
||
spare2: '',
|
||
spare3: '',
|
||
spare4: ''
|
||
}
|
||
|
||
const DEFAULT_PREVIEW_DATA = {
|
||
model: '',
|
||
color: '',
|
||
serial: '',
|
||
v: '',
|
||
hz: '',
|
||
ph: '',
|
||
nW: '',
|
||
gW: ''
|
||
}
|
||
|
||
export default {
|
||
name: 'BasProductCode',
|
||
components: {
|
||
VueQr,
|
||
VueEasyPrint
|
||
},
|
||
data() {
|
||
return {
|
||
// 表单对象
|
||
form: { ...DEFAULT_FORM },
|
||
// 表单校验规则
|
||
rules: this.generateRules(),
|
||
// 查询参数
|
||
queryParams: {
|
||
pageNum: 1,
|
||
pageSize: 10,
|
||
searchText: '',
|
||
spaer1:null
|
||
},
|
||
// 表格数据
|
||
tableData: [],
|
||
// 加载状态
|
||
loading: false,
|
||
previewLoading: false,
|
||
submitLoading: false,
|
||
// 总条数
|
||
total: 0,
|
||
// 预览数据
|
||
previewDataList: [],
|
||
previewData: {},
|
||
codeDataList: [],
|
||
// 选中数据
|
||
selectedRows: [],
|
||
// 是否显示预览
|
||
showPreview: false,
|
||
// 表单字段配置
|
||
formFields: FORM_FIELDS,
|
||
// 表格列配置
|
||
tableColumns: TABLE_COLUMNS,
|
||
// 物资选择弹框显示状态
|
||
productSelectVisible: false,
|
||
// 物资查询参数
|
||
productQueryParams: {
|
||
pageNum: 1,
|
||
pageSize: 10,
|
||
productId: undefined,
|
||
productName: undefined
|
||
},
|
||
// 物资表格数据
|
||
productTableData: [],
|
||
// 物资表格加载状态
|
||
productTableLoading: false,
|
||
// 物资总条数
|
||
productTotal: 0
|
||
}
|
||
},
|
||
computed: {
|
||
// 是否有选中项
|
||
hasSelection() {
|
||
return this.selectedRows.length > 0
|
||
}
|
||
},
|
||
created() {
|
||
this.init()
|
||
},
|
||
methods: {
|
||
// 初始化
|
||
async init() {
|
||
try {
|
||
await this.getList()
|
||
} catch (error) {
|
||
this.$message.error('初始化失败:' + error.message)
|
||
}
|
||
},
|
||
// 二维码内容
|
||
qrCodeValue(data) {
|
||
//console.log('二维码内容')
|
||
//console.log(data)
|
||
const text = `${data.spare1}@${data.model}@${data.spare2}@${data.spare3}@${data.serial}`
|
||
var bm = this.procode(text)
|
||
return "MODEL:" + data.model + " COLOR:" + data.color
|
||
+ " SERIAL:" + data.serial + " V:" + data.v
|
||
+ " Hz:" + data.hz + " PH:" + data.ph
|
||
+ " N.W.:" + data.nW + " G.W.:" + data.gW + " ITEM_CODE:" + data.spare4 + " @:" + bm + "@"
|
||
|
||
},
|
||
|
||
// 生成表单验证规则
|
||
generateRules() {
|
||
const rules = {}
|
||
FORM_FIELDS.forEach(field => {
|
||
if (field.required) {
|
||
rules[field.prop] = [
|
||
{ required: true, message: `请输入${field.label}`, trigger: 'blur' }
|
||
]
|
||
}
|
||
})
|
||
return rules
|
||
},
|
||
|
||
// 获取列表数据
|
||
async getList() {
|
||
this.loading = true
|
||
try {
|
||
const response = await listBasProductCode(this.queryParams)
|
||
this.tableData = response.rows || []
|
||
this.total = response.total || 0
|
||
} catch (error) {
|
||
this.$message.error('获取数据失败:' + error.message)
|
||
this.tableData = []
|
||
this.total = 0
|
||
} finally {
|
||
this.loading = false
|
||
}
|
||
},
|
||
|
||
// 查询按钮操作
|
||
handleQuery() {
|
||
this.queryParams.pageNum = 1
|
||
this.getList()
|
||
},
|
||
|
||
// 重置表单
|
||
resetForm() {
|
||
this.$refs.form.resetFields()
|
||
this.form = { ...DEFAULT_FORM }
|
||
this.previewData = { ...DEFAULT_PREVIEW_DATA }
|
||
this.showPreview = false
|
||
},
|
||
resetQuery(){
|
||
this.queryParams = {
|
||
pageNum: 1,
|
||
pageSize: 10,
|
||
searchText: '',
|
||
spare1:null
|
||
}
|
||
this.handleQuery()
|
||
},
|
||
|
||
// 预览按钮操作
|
||
async handlePreview() {
|
||
try {
|
||
await this.$refs.form.validate()
|
||
this.previewLoading = true
|
||
|
||
// 模拟预览加载
|
||
setTimeout(() => {
|
||
this.previewData = { ...this.form }
|
||
this.showPreview = true
|
||
this.previewLoading = false
|
||
this.$message.success('预览生成成功')
|
||
}, 300)
|
||
} catch (error) {
|
||
this.$message.warning('请完善必填信息')
|
||
}
|
||
},
|
||
|
||
// 表单提交
|
||
async submitForm() {
|
||
try {
|
||
await this.$refs.form.validate()
|
||
this.submitLoading = true
|
||
|
||
const apiCall = this.form.id != null
|
||
? updateBasProductCode(this.form)
|
||
: addBasProductCode(this.form)
|
||
|
||
await apiCall
|
||
|
||
const message = this.form.id != null ? '修改成功' : '新增成功'
|
||
this.$message.success(message)
|
||
|
||
await this.getList()
|
||
//await this.autoPrint()
|
||
|
||
} catch (error) {
|
||
this.$message.error('保存失败:' + error.message)
|
||
} finally {
|
||
this.submitLoading = false
|
||
}
|
||
},
|
||
|
||
// 新增按钮操作
|
||
handleAdd() {
|
||
this.resetForm()
|
||
},
|
||
|
||
// 编辑按钮操作
|
||
handleEdit(row) {
|
||
this.form = { ...row }
|
||
this.previewData = { ...row }
|
||
// this.showPreview = true
|
||
},
|
||
|
||
// 删除按钮操作
|
||
async handleDelete(row) {
|
||
try {
|
||
await this.$confirm(
|
||
`是否确认删除条码打印编号为"${row.id}"的数据项?`,
|
||
'警告',
|
||
{
|
||
confirmButtonText: '确定',
|
||
cancelButtonText: '取消',
|
||
type: 'warning'
|
||
}
|
||
)
|
||
|
||
await delBasProductCode(row.id)
|
||
this.$message.success('删除成功')
|
||
await this.getList()
|
||
|
||
} catch (error) {
|
||
if (error !== 'cancel') {
|
||
this.$message.error('删除失败:' + error.message)
|
||
}
|
||
}
|
||
},
|
||
handleErpData() {
|
||
console.log(1111)
|
||
console.log(this.queryParams)
|
||
if (!this.queryParams.spare1){
|
||
this.$message.error('请输入订单号')
|
||
return
|
||
}
|
||
|
||
const param = {
|
||
spare1: this.queryParams.spare1
|
||
}
|
||
getErpProductCodeData(param).then(response => {
|
||
if (response.code === 200) {
|
||
this.$message.success('获取成功')
|
||
} else {
|
||
this.$message.error('获取失败')
|
||
}
|
||
}).finally(
|
||
() => {
|
||
this.getList()
|
||
}
|
||
)
|
||
|
||
|
||
},
|
||
|
||
// 批量删除
|
||
handleBatchDelete() {
|
||
if (!this.hasSelection) {
|
||
this.$message.warning('请选择要删除的数据')
|
||
return
|
||
}
|
||
|
||
try {
|
||
this.$confirm(
|
||
`是否确认删除选中的${this.selectedRows.length}条数据?`,
|
||
'警告',
|
||
{
|
||
confirmButtonText: '确定',
|
||
cancelButtonText: '取消',
|
||
type: 'warning'
|
||
}
|
||
)
|
||
|
||
const ids = this.selectedRows.map(row => row.id)
|
||
delBasProductCode(ids.join(','))
|
||
|
||
this.$message.success('批量删除成功')
|
||
this.getList()
|
||
|
||
} catch (error) {
|
||
if (error !== 'cancel') {
|
||
this.$message.error('批量删除失败:' + error.message)
|
||
}
|
||
}
|
||
},
|
||
|
||
// 打印按钮操作 - 一次性打印多个标签
|
||
async handlePrint(row) {
|
||
try {
|
||
// 获取serial的后四位并确保是4位数字(前面补0)
|
||
const serialSuffix = row.serial.slice(-4);
|
||
const formattedSerial = serialSuffix.padStart(4, '0');
|
||
|
||
// 根据数量生成多个预览数据
|
||
const quantity = parseInt(row.spare5) || 1;
|
||
|
||
// 创建打印数据数组
|
||
this.previewDataList = [];
|
||
for (let i = 0; i < quantity; i++) {
|
||
// 创建新的预览数据副本
|
||
const newPreviewData = {...row};
|
||
|
||
// 如果需要序列号递增,可以这样处理:
|
||
const newSerialNum = parseInt(formattedSerial) + i;
|
||
newPreviewData.serial = `${row.serial.slice(0, -4)}${newSerialNum.toString().padStart(4, '0')}`;
|
||
newPreviewData.qrCode = this.qrCodeValue(newPreviewData);
|
||
newPreviewData.qrDataUrl = '';
|
||
this.previewDataList.push(newPreviewData);
|
||
}
|
||
|
||
// 等待DOM更新后执行打印(修复2:增加更长的延迟确保二维码渲染完成)
|
||
await this.$nextTick();
|
||
await this.delay(200);
|
||
this.$refs.easyPrint2.print();
|
||
|
||
} catch (error) {
|
||
this.$message.error('打印失败:' + error.message);
|
||
}
|
||
},
|
||
delay(ms) {
|
||
return new Promise(resolve => setTimeout(resolve, ms));
|
||
},
|
||
|
||
// 自动打印功能
|
||
async autoPrint() {
|
||
try {
|
||
this.previewData = { ...this.form }
|
||
this.showPreview = true
|
||
|
||
await this.$nextTick()
|
||
setTimeout(() => {
|
||
this.$refs.easyPrint2.print()
|
||
}, 500)
|
||
|
||
} catch (error) {
|
||
this.$message.error('自动打印失败:' + error.message)
|
||
}
|
||
},
|
||
|
||
// 多选框选中数据
|
||
handleSelectionChange(selection) {
|
||
this.selectedRows = selection
|
||
},
|
||
|
||
// 打开物资选择弹框
|
||
openProductSelect() {
|
||
this.productSelectVisible = true;
|
||
this.getProductList();
|
||
},
|
||
|
||
// 获取物资列表
|
||
async getProductList() {
|
||
this.productTableLoading = true;
|
||
try {
|
||
const response = await listBasProduct(this.productQueryParams);
|
||
this.productTableData = response.rows || [];
|
||
this.productTotal = response.total || 0;
|
||
} catch (error) {
|
||
this.$message.error('获取物资数据失败:' + error.message);
|
||
} finally {
|
||
this.productTableLoading = false;
|
||
}
|
||
},
|
||
|
||
// 物资查询按钮操作
|
||
handleProductQuery() {
|
||
this.productQueryParams.pageNum = 1;
|
||
this.getProductList();
|
||
},
|
||
|
||
// 重置物资查询表单
|
||
resetProductQuery() {
|
||
this.$refs.queryForm.resetFields();
|
||
this.productQueryParams = {
|
||
pageNum: 1,
|
||
pageSize: 10,
|
||
productId: undefined,
|
||
productName: undefined
|
||
};
|
||
this.getProductList();
|
||
},
|
||
|
||
// 选择物资
|
||
handleProductSelect(row) {
|
||
this.form.spare4 = row.productId;
|
||
this.productSelectVisible = false;
|
||
},
|
||
|
||
// 二维码编码方法
|
||
procode(text) {
|
||
const key = "0"
|
||
|
||
const mystr = text.split("@")
|
||
const text1 = `@${mystr[1]}@${mystr[2]}@${mystr[3]}@`
|
||
|
||
let str = key + text1
|
||
let str1 = ""
|
||
|
||
for (let i = 0; i < str.length; i++) {
|
||
// 获取字符的Unicode编码并转换为16进制
|
||
let str2 = str.charCodeAt(i).toString(16).toUpperCase()
|
||
// 补齐到4位
|
||
while (str2.length < 4) {
|
||
str2 = "0" + str2
|
||
}
|
||
str1 += str2
|
||
}
|
||
|
||
// 反转字符串
|
||
str1 = str1.split('').reverse().join('')
|
||
|
||
// 替换操作
|
||
str1 = str1.replace(/100/g, "Q")
|
||
str1 = str1.replace(/200/g, "R")
|
||
str1 = str1.replace(/300/g, "S")
|
||
str1 = str1.replace(/400/g, "T")
|
||
str1 = str1.replace(/500/g, "U")
|
||
str1 = str1.replace(/600/g, "V")
|
||
str1 = str1.replace(/700/g, "W")
|
||
str1 = str1.replace(/800/g, "X")
|
||
str1 = str1.replace(/900/g, "Y")
|
||
str1 = str1.replace(/00/g, "Z")
|
||
|
||
// 最终结果反转
|
||
const result = `${mystr[0]}$${str1}$${mystr[4]}`
|
||
return result.split('').reverse().join('')
|
||
}
|
||
}
|
||
}
|
||
</script>
|
||
|
||
<style scoped>
|
||
/* 基础布局 */
|
||
.app-container {
|
||
padding: 20px;
|
||
background-color: #f5f5f5;
|
||
}
|
||
|
||
.list-container {
|
||
background: #fff;
|
||
padding: 20px;
|
||
border-radius: 4px;
|
||
box-shadow: 0 2px 12px 0 rgba(0,0,0,0.1);
|
||
}
|
||
|
||
.section-header {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
margin-bottom: 20px;
|
||
}
|
||
|
||
.section-header h3 {
|
||
margin: 0;
|
||
font-size: 16px;
|
||
font-weight: 500;
|
||
}
|
||
|
||
.header-actions {
|
||
display: flex;
|
||
gap: 10px;
|
||
}
|
||
|
||
.el-table {
|
||
margin-bottom: 20px;
|
||
}
|
||
|
||
.el-table .danger-text {
|
||
color: #F56C6C;
|
||
}
|
||
|
||
.el-table .danger-text:hover {
|
||
color: #f78989;
|
||
}
|
||
|
||
/* 容器样式 */
|
||
.form-container,
|
||
.list-container,
|
||
.preview-container {
|
||
background-color: #fff;
|
||
border-radius: 8px;
|
||
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
|
||
overflow: hidden;
|
||
}
|
||
|
||
.form-container {
|
||
margin-bottom: 0;
|
||
}
|
||
|
||
.list-container .el-table {
|
||
height: 100%;
|
||
}
|
||
|
||
.preview-display {
|
||
height: 100%;
|
||
overflow: hidden;
|
||
}
|
||
|
||
/* 区域标题 */
|
||
.section-header {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
padding: 20px 20px 0;
|
||
margin-bottom: 20px;
|
||
}
|
||
|
||
.section-header h3 {
|
||
margin: 0;
|
||
font-size: 16px;
|
||
font-weight: 600;
|
||
color: #303133;
|
||
}
|
||
|
||
.header-actions {
|
||
display: flex;
|
||
gap: 10px;
|
||
}
|
||
|
||
/* 表单样式 */
|
||
.form-container .el-form {
|
||
padding: 0 20px 10px;
|
||
}
|
||
|
||
.form-actions {
|
||
text-align: center;
|
||
}
|
||
|
||
.form-actions .el-button {
|
||
margin: 0 10px;
|
||
}
|
||
|
||
/* 表格样式 */
|
||
.list-container .el-table {
|
||
margin: 0 20px;
|
||
}
|
||
|
||
.list-container .pagination {
|
||
margin: 20px;
|
||
text-align: center;
|
||
}
|
||
|
||
.danger-text {
|
||
color: #f56c6c !important;
|
||
}
|
||
|
||
.danger-text:hover {
|
||
color: #f78989 !important;
|
||
}
|
||
|
||
.empty-preview i {
|
||
font-size: 48px;
|
||
margin-bottom: 16px;
|
||
color: #000000;
|
||
}
|
||
|
||
.empty-preview p {
|
||
margin: 0;
|
||
}
|
||
|
||
.label-content {
|
||
border: 1px solid #e4e7ed;
|
||
border-radius: 0px;
|
||
overflow: hidden;
|
||
text-align: left;
|
||
}
|
||
|
||
.preview-box {
|
||
padding: 20px;
|
||
font-family: 'Arial', sans-serif;
|
||
position: relative;
|
||
background-color: #fff;
|
||
height: 350px;
|
||
width: 100%;
|
||
box-sizing: border-box;
|
||
}
|
||
|
||
.preview-row {
|
||
display: flex;
|
||
align-items: center;
|
||
margin-bottom: 15px;
|
||
min-height: 0;
|
||
padding-left: 5px;
|
||
}
|
||
|
||
.preview-col {
|
||
flex: 1;
|
||
display: flex;
|
||
align-items: center;
|
||
}
|
||
|
||
.preview-label {
|
||
margin-right: 15px;
|
||
min-width: 10px;
|
||
font-size: 15px;
|
||
font-weight: bold;
|
||
color: #000000;
|
||
}
|
||
|
||
.preview-value {
|
||
flex: 1;
|
||
font-size: 15px;
|
||
font-weight: bold;
|
||
color: #000000;
|
||
word-break: break-all;
|
||
}
|
||
|
||
.qrcode-label {
|
||
margin-top: 1px;
|
||
font-size: 10px;
|
||
font-weight: 600;
|
||
color: #000000;
|
||
text-align: center;
|
||
}
|
||
.qrcode-container {
|
||
display: inline-block;
|
||
}
|
||
.qrcode-container canvas {
|
||
display: none !important;
|
||
}
|
||
.qrcode-container img {
|
||
display: block !important;
|
||
}
|
||
|
||
/* 动画效果 */
|
||
.preview-display {
|
||
animation: fadeIn 0.3s ease-in-out;
|
||
}
|
||
|
||
@keyframes fadeIn {
|
||
from {
|
||
opacity: 0;
|
||
transform: translateY(10px);
|
||
}
|
||
to {
|
||
opacity: 1;
|
||
transform: translateY(0);
|
||
}
|
||
}
|
||
|
||
/* 加载状态 */
|
||
.el-button.is-loading {
|
||
pointer-events: none;
|
||
}
|
||
|
||
/* 打印样式 */
|
||
@media print {
|
||
@page {
|
||
size: auto
|
||
}
|
||
|
||
body {
|
||
margin: 0;
|
||
}
|
||
|
||
.preview-box {
|
||
border: none;
|
||
box-shadow: none;
|
||
position: relative;
|
||
}
|
||
|
||
.qrcode-container {
|
||
border: none;
|
||
position: absolute !important;
|
||
top: 10px !important;
|
||
right: 30px !important;
|
||
padding: 0;
|
||
background-color: transparent;
|
||
}
|
||
}
|
||
|
||
/* 修复4:修改打印容器的隐藏方式,使用定位而非display:none */
|
||
.print-container {
|
||
position: absolute;
|
||
visibility: visible;
|
||
z-index: -9999;
|
||
top: 0;
|
||
left: -9999px;
|
||
}
|
||
</style>
|