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.
 
 
 
 
 

616 lines
17 KiB

<template>
<div class="customer-css">
<el-dialog :title="titleCon" v-drag v-bind="$attrs" v-on="$listeners"
width="600px" class="material-dialog">
<div class="material-content">
<el-form :model="pageData" label-position="top" label-width="100px">
<!-- 材料信息卡片 -->
<div class="material-info-card">
<div class="info-header">
<i class="el-icon-document"></i>
<span>材料信息</span>
</div>
<div class="info-content">
<el-row :gutter="15">
<el-col :span="12">
<div class="info-row">
<label class="info-label">材料卷号:</label>
<span class="info-value">{{ pageData.rmRollNo || '-' }}</span>
</div>
</el-col>
<el-col :span="12">
<div class="info-row">
<label class="info-label">零部件编码:</label>
<span class="info-value">{{ pageData.partNo || '-' }}</span>
</div>
</el-col>
</el-row>
<el-row :gutter="15">
<el-col :span="24">
<div class="info-row">
<label class="info-label">零部件名称:</label>
<span class="info-value">{{ pageData.partDesc || '-' }}</span>
</div>
</el-col>
</el-row>
<el-row :gutter="15">
<el-col :span="12">
<div class="info-row">
<label class="info-label">规格型号:</label>
<span class="info-value">{{ pageData.spec || '-' }}</span>
</div>
</el-col>
</el-row>
</div>
</div>
<!-- 损耗设置区域 -->
<div class="return-settings">
<el-row :gutter="15">
<el-col :span="8">
<el-form-item label="上机数量" class="form-item-enhanced">
<el-input
v-model="displayOnMachineQty"
disabled
size="large"
style="width: 100%">
</el-input>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="暂存数量" class="form-item-enhanced">
<el-input class="inlineNumber numInput"
v-model="pageData.returnQty"
type="number"
placeholder="请输入暂存数量"
size="large"
@input="calculateRemainQty"
style="width: 100%">
</el-input>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="剩余数量" class="form-item-enhanced">
<el-input
v-model="displayRemainQty"
disabled
size="large"
:class="{'remain-negative': pageData.remainQty < 0}"
style="width: 100%">
</el-input>
</el-form-item>
</el-col>
</el-row>
<!-- 备注 -->
<el-row style="margin-bottom: 30px">
<el-col :span="24">
<el-form-item label="备注" >
<el-input
v-model="pageData.remark"
type="textarea"
:rows="3"
placeholder="请输入备注"
show-word-limit>
</el-input>
</el-form-item>
</el-col>
</el-row>
</div>
</el-form>
</div>
<span slot="footer" class="dialog-footer">
<button class="action-btn secondary" @click="submitMaterialLoss">
{{ buttons.confirmButton }}
</button>
<button class="action-btn secondary" @click="closeDialog">
{{ buttons.closeButton }}
</button>
</span>
</el-dialog>
</div>
</template>
<script>
import {
materialProcessLoss
} from '@/api/yieldReport/com_material_loss.js';
import getLodop from '@/utils/LodopFuncs.js'; // 打印控件
import labelPrintTemplates from '@/mixins/labelPrintTemplates.js'; // 打印模板mixin
var functionId = 'C10000019';
export default {
mixins: [labelPrintTemplates], // 添加打印模板mixin
data() {
return {
titleCon: '材料暂存',
scheduleData: {
site: this.$store.state.user.site,
username: this.$store.state.user.name,
seqNo: '',
orderNo: '',
itemNo: 0,
},
pageData: {
site: this.$store.state.user.site,
orderNo: '',
itemNo: '',
seqNo: '',
rollNo: '',
rmRollNo: '',
partNo: '',
partDesc: '',
spec: '',
onMachineQty: 0, // 上机数量(来自行数据的数量)
returnQty: 0, // 损耗数量
remainQty: 0, // 剩余数量
remark: '', // 备注
histSeqNo: '',
operatorId: '',
},
operatorData: {
site: this.$store.state.user.site,
username: this.$store.state.user.name,
operatorId: '',
operatorName: '',
},
buttons: {
confirmButton: '确定',
closeButton: '关闭',
},
}
},
computed: {
// 显示上机数量(如果为0或空则显示空字符串)
displayOnMachineQty() {
return this.pageData.onMachineQty || this.pageData.onMachineQty === 0 ? String(this.pageData.onMachineQty) : '';
},
// 显示剩余数量(如果为0或空则显示空字符串)
displayRemainQty() {
return this.pageData.remainQty || this.pageData.remainQty === 0 ? String(this.pageData.remainQty) : '';
}
},
methods: {
//初始化组件的参数
init(scheduleData, operatorData, materialRow) {
//初始化参数
this.scheduleData = scheduleData;
this.operatorData = JSON.parse(JSON.stringify(operatorData));
//设置材料信息
this.pageData.orderNo = scheduleData.orderNo;
this.pageData.itemNo = scheduleData.itemNo;
this.pageData.seqNo = scheduleData.seqNo;
this.pageData.rollNo = scheduleData.rollNo;
this.pageData.operatorId = operatorData.operatorId;
// 从行数据获取材料信息
this.pageData.rmRollNo = materialRow.rmRollNo || '';
this.pageData.partNo = materialRow.partNo || '';
this.pageData.partDesc = materialRow.partDesc || '';
this.pageData.spec = materialRow.spec || '';
this.pageData.histSeqNo = materialRow.histSeqNo || '';
// 获取上机数量(从行数据的 transQty 字段)
const transQty = parseFloat(materialRow.transQty);
this.pageData.onMachineQty = isNaN(transQty) ? 0 : transQty;
// 重置损耗数量、剩余数量和备注
this.pageData.returnQty = 0;
this.pageData.remainQty = this.pageData.onMachineQty;
this.pageData.remark = '';
this.titleCon = '材料暂存';
},
/*关闭modal*/
closeDialog(){
//刷新报工的页面
this.$emit('refreshPageData');
//关闭当前的页面
this.$emit('update:visible', false);
},
/*计算剩余数量*/
calculateRemainQty() {
const onMachineQty = parseFloat(this.pageData.onMachineQty) || 0;
const returnQty = parseFloat(this.pageData.returnQty) || 0;
this.pageData.remainQty = onMachineQty - returnQty;
},
/*提交损耗*/
submitMaterialLoss() {
// 如果没有填写损耗数量,默认为0
if (!this.pageData.returnQty || this.pageData.returnQty === '' || this.pageData.returnQty < 0) {
this.pageData.returnQty = 0;
}
// 计算剩余数量
this.calculateRemainQty();
// 验证剩余数量必须大于等于0
if (this.pageData.remainQty < 0) {
this.$message.warning('暂存数量不能大于上机数量!');
return false;
}
// 构建提交数据(只传损耗数量和备注,不传上机数量和剩余数量)
const submitData = {
site: this.pageData.site,
orderNo: this.pageData.orderNo,
itemNo: this.pageData.itemNo,
seqNo: this.pageData.seqNo,
rollNo: this.pageData.rmRollNo,
returnQty: this.pageData.returnQty,
histSeqNo: this.pageData.histSeqNo,
operatorId: this.pageData.operatorId,
remark: this.pageData.remark || '' // 备注(可选,默认为空字符串)
};
// 调用后端API(调用 MaterialProcessLoss 存储过程)
materialProcessLoss(submitData).then(({data}) => {
//判断是否存在异常
if(data.code == 500 || data.code == 400){
this.$message.error(data.msg || data.message);
} else if (data.code == 201) {
// code=201 表示需要打印标签
this.$message.success(data.msg || '操作成功');
// 获取打印参数并打印(存储过程返回的打印参数在printData中)
if (data.printData) {
// 将单个打印数据对象包装成数组
const printDataList = [data.printData];
this.executePrint(printDataList);
} else {
console.warn('未获取到打印参数');
}
//关闭当前的页面
this.closeDialog();
} else {
//先提示 后关闭
this.$message.success(data.msg || data.message || '操作成功');
//关闭当前的页面
this.closeDialog();
}
}).catch((error) => {
this.$message.error('操作失败:' + (error.message || '未知错误'));
});
},
/**
* 执行打印(直接使用存储过程返回的打印参数)
* @param {Array} printDataList - 存储过程返回的打印数据列表
*/
executePrint(printDataList) {
try {
// 1. 获取 LODOP 打印控件
const LODOP = getLodop();
if (!LODOP) {
this.$message.warning('无法连接到打印控件,跳过打印');
return;
}
// 2. 获取默认打印机
const printerCount = LODOP.GET_PRINTER_COUNT();
if (printerCount === 0) {
this.$message.warning('未检测到打印机,跳过打印');
return;
}
const defaultPrinterName = LODOP.GET_PRINTER_NAME(0);
// 3. 检查打印数据中的labelNo(标签模板编号)
if (!printDataList || printDataList.length === 0) {
console.warn('打印数据为空');
return;
}
// 获取第一条数据的labelNo
const labelNo = printDataList[0].labelNo;
if (!labelNo) {
console.warn('未找到标签模板编号');
return;
}
// 4. 执行模板打印
this.executePrintWithTemplate(LODOP, printDataList, labelNo, defaultPrinterName);
this.$message.success('标签打印任务已发送!');
} catch (error) {
console.error('打印失败:', error);
this.$message.warning('打印失败: ' + error.message);
}
},
/**
* 执行模板打印
* @param {Object} LODOP - 打印控件对象
* @param {Array} printDataList - 打印数据列表
* @param {String} labelNo - 标签模板编号 (A001/A002/A003)
* @param {String} printerName - 打印机名称
*/
executePrintWithTemplate(LODOP, printDataList, labelNo, printerName) {
LODOP.PRINT_INIT('材料暂存标签打印');
// 设置打印模式,隐藏水印
LODOP.SET_PRINT_MODE("PRINT_NOCOLLATE", true);
// 设置打印机
LODOP.SET_PRINTER_INDEX(printerName);
// 循环打印每个标签
for (let i = 0; i < printDataList.length; i++) {
const printData = printDataList[i];
const isNewPage = i > 0;
// 根据 labelNo 调用不同的打印方法(来自 labelPrintTemplates mixin)
if (labelNo === 'A001') {
this.printLabelA001(LODOP, printData, isNewPage);
} else if (labelNo === 'A002') {
this.printLabelA002(LODOP, printData, isNewPage);
} else if (labelNo === 'A003') {
this.printLabelA003(LODOP, printData, isNewPage);
} else {
console.warn(`未知的标签模板:${labelNo}`);
}
}
// 预览打印(避免水印)
LODOP.PREVIEW();
},
},
}
</script>
<style scoped lang="scss">
.numInput /deep/ .el-input__inner{
text-align: right;
}
/deep/ .inlineNumber input::-webkit-outer-spin-button,
/deep/ .inlineNumber input::-webkit-inner-spin-button {
-webkit-appearance: none;
}
/deep/ .inlineNumber input[type="number"]{
-moz-appearance: textfield;
padding-right: 5px !important;
}
// 材料暂存对话框样式
.material-dialog {
::v-deep .el-dialog {
border-radius: 8px;
overflow: hidden;
.el-dialog__header {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
padding: 18px 20px;
.el-dialog__title {
color: #fff;
font-size: 16px;
font-weight: 600;
}
.el-dialog__headerbtn {
.el-dialog__close {
color: #fff;
font-size: 18px;
&:hover {
color: #f0f0f0;
}
}
}
}
.el-dialog__body {
padding: 25px;
background-color: #f8f9fa;
}
.el-dialog__footer {
padding: 15px 20px;
background-color: #fff;
border-top: 1px solid #e9ecef;
}
}
}
.material-content {
.form-item-enhanced {
margin-bottom: 10px;
::v-deep .el-form-item__label {
color: #495057;
font-weight: 500;
font-size: 14px;
margin-bottom: 8px;
}
::v-deep .el-input {
.el-input__inner {
border-radius: 6px;
border: 1px solid #dee2e6;
transition: all 0.3s;
height: 42px;
line-height: 42px;
font-size: 15px;
&:focus {
border-color: #667eea;
box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1);
}
}
}
// 文本域样式
::v-deep .el-textarea {
.el-textarea__inner {
border-radius: 6px;
border: 1px solid #dee2e6;
transition: all 0.3s;
font-size: 14px;
padding: 8px 12px;
line-height: 1.5;
&:focus {
border-color: #667eea;
box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1);
}
}
}
// 剩余数量为负数时的红色警告样式
::v-deep .remain-negative {
.el-input__inner {
color: #f56c6c;
font-weight: 600;
border-color: #f56c6c;
background-color: #fef0f0;
}
}
}
}
// 物料信息卡片样式 - 白色框连起来
.material-info-card {
background: linear-gradient(135deg, #667eea15 0%, #764ba215 100%);
border-radius: 8px;
padding: 16px;
margin-bottom: 20px;
border: 1px solid #e3e8f0;
box-shadow: 0 2px 8px rgba(102, 126, 234, 0.08);
animation: fadeInDown 0.5s ease-out;
.info-header {
display: flex;
align-items: center;
margin-bottom: 12px;
padding-bottom: 10px;
border-bottom: 1px solid #dee2e6;
i {
font-size: 18px;
color: #667eea;
margin-right: 8px;
}
span {
font-size: 14px;
font-weight: 600;
color: #495057;
}
}
.info-content {
background-color: rgba(255, 255, 255, 0.8);
border-radius: 4px;
padding: 12px;
.info-row {
display: flex;
align-items: center;
padding: 4px 0;
&:not(:last-child) {
border-bottom: 1px dashed #e9ecef;
}
.info-label {
font-size: 13px;
color: #6c757d;
min-width: 90px;
font-weight: 500;
}
.info-value {
font-size: 13px;
color: #212529;
font-weight: 600;
flex: 1;
}
}
}
}
// 暂存设置区域
.return-settings {
background: #fff;
border-radius: 8px;
padding: 16px;
border: 1px solid #e3e8f0;
box-shadow: 0 2px 8px rgba(102, 126, 234, 0.05);
}
// 底部按钮样式
.dialog-footer {
display: flex;
justify-content: center;
gap: 12px;
padding: 0;
.action-btn {
min-width: 80px;
padding: 6px 16px;
border-radius: 16px;
font-size: 13px;
font-weight: 500;
cursor: pointer;
transition: all 0.2s ease;
display: inline-flex;
align-items: center;
justify-content: center;
gap: 4px;
i {
font-size: 13px;
}
&.primary {
background: #17B3A3;
border: none;
color: white;
&:hover {
background: #13998b;
box-shadow: 0 4px 12px rgba(23, 179, 163, 0.4);
transform: translateY(-1px);
}
&:active {
transform: translateY(0);
}
}
&.secondary {
background: white;
border: 1px solid #17B3A3;
color: #17B3A3;
&:hover {
background: #17B3A3;
color: white;
}
&:active {
transform: scale(0.98);
}
}
}
}
// 动画效果
@keyframes fadeInDown {
from {
opacity: 0;
transform: translateY(-10px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
</style>