Files
FT517-WMS/ruoyi-ui/src/views/bas/BasProductCode/index.vue
2026-01-06 10:55:38 +08:00

1074 lines
30 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<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>