<template>
|
<view class="container">
|
<!-- <view class="title">注塑生产报工</view> -->
|
|
<!-- 头 -->
|
<view class="head">
|
<view class="head-left">
|
<view class="head-top">
|
<view class="ry">
|
<view class="ryxx">
|
|
<input class="input-box" type="number" v-model="personCode"
|
@keypress.enter="fetchPersonInfo" placeholder="人员编码">
|
<text v-if="!personCode" class="error-star">*</text>
|
</input>
|
</view>
|
<button @click="fetchPersonInfo" class="confirm-btn">确认</button>
|
|
</view>
|
<view class="cx">
|
<picker mode="selector" :range="lineOptions" v-model="selectedLine" @change="updateLine">
|
<view class=" picker2">
|
{{ lineCode ? lineCode : '选择产线' }}
|
<text v-if="!lineCode" class="error-star">*</text>
|
</view>
|
</picker>
|
</view>
|
</view>
|
<view class="head-but">
|
<!-- 工单信息 -->
|
<view class="form-group">
|
<label for="orderSelect">工单信息:</label>
|
<picker mode="selector" :range="orderOptions" v-model="selectedOrder"
|
@change="loadOrderDetails">
|
<view class="picker">{{ selectedOrder ? selectedOrder : '请选择工单' }}
|
<text v-if="!selectedOrder" class="error-star">*</text>
|
</view>
|
|
</picker>
|
</view>
|
</view>
|
</view>
|
<view class="head-right">
|
|
<text class="capacity-title">当日产能</text>
|
<view class="capacity-content">
|
<text>{{ dailyCapacity || 0 }}</text> <!-- 默认值为0 -->
|
</view>
|
</view>
|
</view>
|
<!-- 新增的人员信息和产线信息展示区域 -->
|
<view class="xzxx">
|
<view class="person-info">
|
<label>人员信息:</label>
|
<text>{{ selectedPerson ? selectedPerson : '暂无人员信息' }}</text>
|
</view>
|
<view class="line-info">
|
<label>产线信息:</label>
|
<text>{{ selectedLine ? selectedLine : '暂无产线信息' }}</text>
|
</view>
|
</view>
|
<!-- 工单详情 -->
|
<view class="order-details">
|
<view class="order-details-row">
|
<view class="order-details-column">
|
<text>需求单据:</text>
|
<text>{{ orderDetails.requirementDoc }}</text>
|
</view>
|
<view class="order-details-column">
|
<text>推荐包装数:</text>
|
<text>{{ orderDetails.bzsl }}</text>
|
</view>
|
</view>
|
<view class="order-details-row">
|
<view class="order-details-column">
|
<text>物料编码:</text>
|
<text>{{ orderDetails.itemNo }}</text>
|
</view>
|
<view class="order-details-column">
|
<text>实际开工时间:</text>
|
<text>{{ orderDetails.productionOrder }}</text>
|
</view>
|
</view>
|
<view class="order-details-row">
|
<view class="order-details-column">
|
<text>物料名称:</text>
|
<text>{{ orderDetails.itemname }}</text>
|
</view>
|
<view class="order-details-column">
|
<text>已生产数:</text>
|
<text>{{ orderDetails.producedQuantity }}</text>
|
</view>
|
</view>
|
<view class="order-details-row">
|
<view class="order-details-column">
|
<text>规格型号:</text>
|
<text>{{ orderDetails.itemmodel }}</text>
|
</view>
|
<view class="order-details-column">
|
<text>订单数量:</text>
|
<text>{{ orderDetails.orderQuantity }}</text>
|
</view>
|
</view>
|
</view>
|
<!-- 报工模块 -->
|
<view class="baogong">
|
|
|
<!-- <view class="baogong-right">
|
<view :class="['capacity-content2', checkFirstPass ? 'green-text' : 'red-text']">
|
<text :style="{ color: checkFirstPass ? 'green' : 'red' }">{{ checkFirstPass ? '首检合格' : '首检不合格' }}</text>
|
</view>
|
<view :class="['capacity-content2', checkXJ ? 'green-text' : 'red-text']">
|
<text :style="{ color: checkXJ ? 'green' : 'red' }">{{ checkXJ ? '巡检合格' : '巡检不合格' }}</text>
|
</view>
|
<view :class="['capacity-content2', checkedInspection ? 'green-text' : 'red-text']">
|
<text :style="{ color: checkedInspection ? 'green' : 'red' }">{{ checkedInspection ? '设备已点检√' : '设备未点检X' }}</text>
|
</view>
|
<view class="capacity-content2">
|
<text :style="{ color: checkedMaintenance ? 'green' : 'red' }">{{ checkedMaintenance ? '设备已保养√' : '设备未保养X' }}</text>
|
</view>
|
</view> -->
|
<view class="baogong-right">
|
<!-- 首检状态 -->
|
<view
|
:class="['capacity-content2', checkFirstPass === null ? 'black-text' : (checkFirstPass ? 'green-text' : 'red-text')]">
|
<text :style="{ color: checkFirstPass === null ? 'black' : (checkFirstPass ? 'green' : 'red') }">
|
{{ checkFirstPass === null ? '首检未做' : (checkFirstPass ? '首检合格' : '首检不合格') }}
|
</text>
|
</view>
|
|
<!-- 巡检状态 -->
|
<view
|
:class="['capacity-content2', checkXJ === null ? 'black-text' : (checkXJ ? 'green-text' : 'red-text')]">
|
<text :style="{ color: checkXJ === null ? 'black' : (checkXJ ? 'green' : 'red') }">
|
{{ checkXJ === null ? '巡检未做' : (checkXJ ? '巡检合格' : '巡检不合格') }}
|
</text>
|
</view>
|
|
<!-- 设备点检状态 -->
|
<view
|
:class="['capacity-content2', checkedInspection === null ? 'black-text' : (checkedInspection ? 'green-text' : 'red-text')]">
|
<text
|
:style="{ color: checkedInspection === null ? 'black' : (checkedInspection ? 'green' : 'red') }">
|
{{ checkedInspection === null ? '设备未点检' : (checkedInspection ? '设备已点检√' : '设备未点检X') }}
|
</text>
|
</view>
|
|
<!-- 设备保养状态 -->
|
<view
|
:class="['capacity-content2', checkedMaintenance === null ? 'black-text' : (checkedMaintenance ? 'green-text' : 'red-text')]">
|
<text
|
:style="{ color: checkedMaintenance === null ? 'black' : (checkedMaintenance ? 'green' : 'red') }">
|
{{ checkedMaintenance === null ? '设备未保养' : (checkedMaintenance ? '设备已保养√' : '设备未保养X') }}
|
</text>
|
</view>
|
</view>
|
|
|
<view class="baogong-left">
|
<view class="right-column">
|
<text class="capacity-title"> 报工数量</text>
|
<view class="capacity-contencapacity-contentt">
|
<input class="capacity-content" type="number" v-model="reportedQuantity" placeholder="报工数量" />
|
<text v-if="!reportedQuantity" class="error-star">*</text>
|
</view>
|
</view>
|
|
<view class="print-button">
|
<button @click="printBarcode" :disabled="isButtonDisabled"
|
class="uni-btn1">{{ isButtonDisabled ? '请稍后...' : '确认打印' }}</button>
|
|
</view>
|
|
<view class="history-record">
|
<button @click="viewHistory" class="lsjl">历史记录</button <!-- 弹出窗口显示历史记录 -->
|
<view v-if="showHistoryPopup" class="history-popup">
|
<!-- 弹窗头部 -->
|
<view class="popup-header">
|
<text class="popup-title">历史打印信息</text>
|
<!-- 关闭按钮 -->
|
<button class="close-btn" @click="closePopup">×</button>
|
</view>
|
|
<!-- 弹窗内容 -->
|
<view class="popup-content">
|
<!-- 表头 -->
|
<view class="history-header">
|
<view class="header-item" id="tm">打印条码</view>
|
<view class="header-item" id="sl">打印数量</view>
|
<view class="header-item" id="sj">打印时间</view>
|
<view class="header-item" id="ry">打印人</view>
|
</view>
|
|
<!-- 表格内容 -->
|
<scroll-view scroll-y="true" class="history-scroll">
|
<view v-for="(record, index) in historyList" :key="index" class="history-record">
|
<view class="record-item">{{ record.itemBarcode }}</view>
|
<view class="record-item">{{ record.quantity }}</view>
|
<view class="record-item">{{ record.printDate }}</view>
|
<view class="record-item">{{ record.printedBy }}</view>
|
</view>
|
</scroll-view>
|
</view>
|
</view>
|
|
<!-- <button @click="reprintLast" :disabled="isButtonDisabled2" class="uni-btn">{{ isButtonDisabled2 ? '请稍后...' : '补打上一张' }}</button>
|
--></view>
|
</view>
|
|
</view>
|
<!-- 新增的左右布局模块 -->
|
<view class="usb-printer-section">
|
<!-- 左边的按钮组 -->
|
<view class="button-group">
|
<!-- <button @click="refreshStatus()" class="refreshStatus">刷新</button> -->
|
<!-- <button @click="usbConnect()" class="qrdy">USB连接打印机</button> -->
|
<!-- <button @click="isConnect()" class="bd">获取连接状态</button> -->
|
<view>
|
<!-- 使用 Flexbox 布局将两个状态文本放在同一行 -->
|
<view class="status-container">
|
<view :class="[networkState.includes('无网络') ? 'error' : 'normal', 'status-item']">
|
{{ networkState }}
|
</view>
|
<view :class="[deviceState.includes('失败') ? 'error' : 'normal', 'status-item']">
|
{{ deviceState }}
|
</view>
|
</view>
|
<button @click="reprintLast" :disabled="isButtonDisabled2" class="uni-btn">{{ isButtonDisabled2 ? '请稍后...' : '补打上一张' }}</button>
|
|
<!-- 按钮放在状态文本的下方 -->
|
<!-- <button @click="manualCheck" class="check-button">手动检测</button> -->
|
<view class="version" v-if="version">
|
版本号:{{ version }}
|
</view>
|
</view>
|
|
<!-- <button @click="createLabel()" class="dycs">打印测试</button> -->
|
</view>
|
|
<!-- 右边的圆形按钮 -->
|
<view class="circle-button">
|
<button @click="sendForFirstInspection" class="round-btn">首检送检</button>
|
</view>
|
</view>
|
|
</view>
|
</template>
|
|
<script>
|
// import JsBarcode from 'jsbarcode'; // 引入 JsBarcode 库
|
// import printTemplate from '../../print.js'; // 导入路径向上两级
|
// import util from '@/components/kk-printer/utils/util.js';
|
// import * as blesdk from '@/components/kk-printer/utils/bluetoolth.js';
|
// import kkPrinter from '@/components/kk-printer/index.vue';
|
//import CustomToast from '../../CustomToast/CustomToast.vue';
|
|
let tsc = require('../../components/gprint/tsc.js')
|
let esc = require('../../components/gprint/esc.js')
|
let UsbModule = uni.requireNativePlugin("gp-usb")
|
|
export default {
|
data() {
|
return {
|
showHistoryPopup: false, // 控制弹出框显示
|
selectedPerson: '',
|
selectedLine: '',
|
selectedOrder: '',
|
personOptions: [],
|
personList: [], // 存储从后端获取的人员数据
|
personIndex: -1,
|
personCode: '', //人员编码
|
lineCode: '', //产线编码
|
lineOptions: [], // 存储产线数据
|
lineList: [], // 存储从后端获取的产线数据
|
orderOptions: [], // 存储工单数据
|
orderList: [], // 存储从后端获取的工单数据
|
historyRecords: [], // 用于弹窗中显示的历史打印记录
|
dailyList: [],
|
version: '1.0.0', // 默认值,如果无法获取则显示此值
|
orderDetails: {
|
requirementDoc: '', // 需求单据
|
productionOrder: '', // 生产订单
|
orderQuantity: '', // 订单数量
|
producedQuantity: '', // 已生产数
|
bzsl: '', // 推荐包装数
|
itemId: '', // 物料ID
|
itemNo: '', // 物料编码
|
itemname: '', // 物料名称
|
itemmodel: '' // 规格型号
|
},
|
lastRequestData: null, // 用于保存最后一次打印的 requestData
|
bgs: null,
|
reportedQuantity: '',
|
dailyCapacity: '0', // 每日产能
|
checkedInspection: null, // 默认为未点检
|
checkedMaintenance: null, // 默认为未维护
|
checkXJ: null,
|
checkFirstPass: null,
|
|
printData: {
|
STRP1: "001",
|
STRP2: "供应商A",
|
STRP3: "物料编码12345",
|
STRP4: "物料名称ABC",
|
STRP5: "100",
|
STRP6: "2024-09-11",
|
STRP7: "规格型号描述",
|
STRP8: "条码内容",
|
STRP13: "需求单据123"
|
},
|
historyList: [], // 存储历史打印记录
|
personName: '', // 用于显示选中的人员名称
|
personId: 0,
|
materialInfo: {}, // 存储物料信息
|
sendData: '',
|
isButtonDisabled: false, // 控制按钮状态
|
isButtonDisabled2: false, // 控制按钮状态
|
networkState: "检测中...",
|
deviceState: "检测中...",
|
networkCheckInterval: null,
|
usbCheckInterval: null,
|
refreshTimer: null, // 存储定时器ID
|
networkState: "检测中...",
|
deviceState: "检测中...",
|
networkModalVisible: false, // 控制网络弹窗是否已显示
|
usbModalVisible: false ,// 控制 USB 弹窗是否已显示
|
updateChecked: false,
|
};
|
},
|
// components:{
|
// kkPrinter
|
// },
|
onReady() {
|
setTimeout(() => {
|
this.checkUsbStatus(); // 延迟检测 USB 状态,避免初始化未完成
|
}, 1000);
|
},
|
|
mounted() {
|
this.startUsbCheck(); // 定时检查 USB 连接状态
|
this.startRandomRefresh(); // 进入页面开始随机刷新
|
this.loadPersons(); // 在组件挂载时加载人员信息
|
this.loadLines(); // 在组件挂载时加载产线信息
|
console.log("页面加载,开始检测 USB 和网络...");
|
console.log("UsbModule:", UsbModule); // 打印 UsbModule 是否可用
|
console.log("UsbModule.isUsbConnect:", UsbModule?.isUsbConnect); // 打印方法是否存在
|
if (typeof plus !== 'undefined') {
|
this.version = plus.runtime.version;
|
}
|
|
this.checkForUpdate(); // 启动时检查版本更新
|
//this.startAutoUpdateCheck(); // 开始定时检查版本更新
|
this.listenNetworkStatus(); // 实时监听网络变化
|
|
this.manualCheck(); // 进入页面先检测一次
|
this.startNetworkCheck(); // 定时检查网络状态
|
|
this.usbConnect();
|
|
|
},
|
methods: {
|
// 开启自动更新检测
|
startAutoUpdateCheck() {
|
this.updateCheckInterval = setInterval(() => {
|
this.checkForUpdate(); // 每隔一段时间检查更新
|
}, 1 * 60 * 1000); // 10 分钟自动检测一次
|
},
|
beforeDestroy() {
|
this.stopAutoUpdateCheck(); // 页面销毁时停止定时器,防止内存泄漏
|
},
|
checkForUpdate() {
|
if (this.updateChecked) return;
|
uni.request({
|
url: "http://192.168.0.107:10086/update.json", // 你的服务器 JSON 文件地址
|
success: (res) => {
|
let newVersion = res.data.version;
|
let currentVersion = plus.runtime.version; // 获取当前 APK 版本号
|
console.log("当前版本:", currentVersion, "最新版本:", newVersion);
|
|
if (newVersion > currentVersion) {
|
// uni.showModal({
|
// title: "发现新版本",
|
// content: "是否下载最新版本?",
|
// success: (modalRes) => {
|
// if (modalRes.confirm) {
|
// this.downloadNewApk(res.data.apkUrl);
|
// }
|
// }
|
// });
|
this.downloadNewApk(res.data.apkUrl);
|
this.updateChecked = true; // 标记更新已检查过
|
// // 如果有新版本,开始下载
|
//download(res.data.apkUrl);
|
}
|
},
|
fail: (err) => {
|
console.error("更新检查失败:", err);
|
}
|
});
|
},
|
|
|
downloadNewApk(apkUrl) {
|
uni.showToast({
|
title: "开始下载更新...",
|
icon: "none",
|
duration: 2000
|
});
|
|
uni.downloadFile({
|
url: apkUrl,
|
success: (res) => {
|
if (res.statusCode === 200) {
|
plus.runtime.install(res.tempFilePath, {
|
force: true
|
}, function() {
|
console.log("安装成功,重启应用");
|
//plus.runtime.restart();
|
//plus.runtime.quit();
|
// uni.navigateBack()
|
}, function(e) {
|
console.error("安装失败:", e);
|
});
|
}
|
},
|
fail: (err) => {
|
console.error("下载失败:", err);
|
uni.showToast({
|
title: "下载失败,请检查网络",
|
icon: "none",
|
duration: 2000
|
});
|
}
|
});
|
},
|
// 启动随机刷新
|
startRandomRefresh() {
|
const randomInterval = Math.floor(Math.random() * (30000 - 10000 + 1)) + 10000; // 10~30秒随机时间
|
console.log(`下次刷新将在 ${randomInterval / 1000} 秒后执行`);
|
|
this.refreshTimer = setTimeout(() => {
|
this.refreshStatus(); // 执行刷新
|
this.startRandomRefresh(); // 递归调用,确保持续刷新
|
}, randomInterval);
|
},
|
// 1. 实时监听网络变化
|
listenNetworkStatus() {
|
uni.onNetworkStatusChange((res) => {
|
this.networkState = res.isConnected ? "网络连接正常" : "无网络连接";
|
console.log("网络状态变更:", this.networkState);
|
uni.showToast({
|
title: `网络状态: ${this.networkState}`,
|
duration: 1500
|
});
|
});
|
},
|
|
// 2. 每 5 秒检查网络状态
|
checkNetworkStatus() {
|
uni.getNetworkType({
|
success: (res) => {
|
this.networkState = res.networkType !== "none" ? "网络连接正常" : "无网络连接";
|
console.log("网络检测结果:", this.networkState);
|
if (this.networkState == "无网络连接") {
|
uni.showToast({
|
title: ` ${this.networkState}`,
|
duration: 1500,
|
icon: "none"
|
});
|
// uni.showModal({
|
// title: ` ${this.networkState}`,
|
// content: "请检查网络 连接连接",
|
// showCancel: false,
|
// success: () => {
|
// this.modalVisible = false;
|
|
// }
|
// });
|
}
|
|
}
|
});
|
},
|
|
startNetworkCheck() {
|
this.networkCheckInterval = setInterval(() => {
|
this.checkNetworkStatus();
|
}, 5000);
|
},
|
|
// 3. 每 5 秒检查 USB 连接状态
|
checkUsbStatus() {
|
try {
|
if (!UsbModule || !UsbModule.isUsbConnect) {
|
throw new Error("UsbModule 未定义或方法不存在");
|
}
|
|
let res = UsbModule.isUsbConnect();
|
this.deviceState = res ? "打印机 连接正常" : "打印机 连接失败";
|
console.log("打印机 检测结果:", this.deviceState);
|
if (this.deviceState == "打印机 连接失败") {
|
|
uni.showToast({
|
title: ` ${this.deviceState}`,
|
duration: 1500,
|
icon: "none"
|
});
|
this.usbConnect();
|
// uni.showModal({
|
// title: ` ${this.deviceState}`,
|
// content: "请检查USB 连接连接",
|
// showCancel: false,
|
// success: () => {
|
// this.modalVisible = false;
|
// this.usbConnect();
|
// }
|
// });
|
|
}
|
|
} catch (error) {
|
|
console.error("打印机 检测错误:", error);
|
this.deviceState = "打印机 检测失败";
|
uni.showToast({
|
title: "打印机 检测失败,请检查插件",
|
duration: 2000,
|
icon: "none"
|
});
|
// uni.showModal({
|
// title: ` ${this.deviceState}`,
|
// content: "请检查USB 连接连接",
|
// showCancel: false,
|
// success: () => {
|
// this.modalVisible = false;
|
// this.usbConnect();
|
// }
|
// });
|
this.usbConnect();
|
|
}
|
},
|
|
startUsbCheck() {
|
this.usbCheckInterval = setInterval(() => {
|
this.checkUsbStatus();
|
console.log("定时启动成功")
|
}, 5000);
|
},
|
|
// 4. 手动触发检测
|
manualCheck() {
|
console.log("手动检测执行...");
|
this.checkNetworkStatus();
|
this.checkUsbStatus();
|
},
|
|
|
|
|
senUSBData() {
|
if (this.sendData == null) {
|
uni.showToast({
|
title: "请先生成指令",
|
duration: 1500
|
})
|
return
|
}
|
var hexStr = ''
|
var data = Array.from(this.sendData)
|
for (var i = 0; i < data.length; i++) {
|
var str = Number(data[i]).toString(16)
|
str = str.length == 1 ? "0" + str : str
|
hexStr += str
|
}
|
//console.log(hexStr)
|
var printNum = 1 // 打印次数
|
var hexPrintData = ''
|
for (var n = 0; n < printNum; n++) {
|
hexPrintData += hexStr
|
}
|
let res = UsbModule.write(hexPrintData)
|
uni.showToast({
|
title: res.msg,
|
duration: 1500
|
})
|
this.result = '发送长度:' + hexPrintData.length + ";返回结果:" + JSON.stringify(res)
|
},
|
usbConnect() {
|
console.log("111", UsbModule)
|
let res = UsbModule.initUsbDevice();
|
if (res) {
|
this.deviceState = "打印机 连接正常"
|
} else {
|
this.deviceState = "打印机 连接失败"
|
}
|
uni.showToast({
|
title: this.deviceState,
|
duration: 1500
|
})
|
},
|
isConnect() {
|
let res = UsbModule.isUsbConnect();
|
if (res) {
|
this.deviceState = "链接状态正常"
|
} else {
|
this.deviceState = "链接状态失败"
|
}
|
uni.showToast({
|
title: this.deviceState,
|
duration: 1500
|
})
|
},
|
disConnect() {
|
let res = UsbModule.disUsbConnect();
|
if (res) {
|
this.deviceState = ""
|
}
|
uni.showToast({
|
title: "断开连接成功",
|
duration: 1500
|
})
|
},
|
|
createLabel() {
|
var command = tsc.jpPrinter.createNew()
|
command.setSize(40, 30)
|
command.setGap(2)
|
command.setCls()
|
command.setText(50, 10, "TSS24.BF2", 1, 1, "打印测试") // 文本
|
command.setQR(50, 50, "L", 5, "A", "www.poscom.cn") // 二维码
|
command.setBar(50, 180, "128", 64, 1, 2, 4, "200902125410") // 条码
|
command.setPagePrint()
|
this.sendData = command.getData();
|
uni.showToast({
|
title: '标签指令生成成功',
|
duration: 1500
|
});
|
},
|
// onPrint(opt){
|
// let strCmd =blesdk.CreatCPCLPage(560,500,1,0);
|
// strCmd += blesdk.addCPCLLine(0,210,560,210,3);
|
// strCmd += blesdk.addCPCLText(10,0,'4','3',0,'8.14');
|
// strCmd += blesdk.addCPCLBarCode(270,0,'128',80,0,1,1,'00051');
|
// strCmd += blesdk.addCPCLText(290,80,'7','2',0,'00051');
|
// strCmd += blesdk.addCPCLText(40,110,'3','0',0,'CHICKEN FEET (BONELESS)-Copy-Copy');
|
// strCmd += blesdk.addCPCLSETMAG(2,2);
|
// strCmd += blesdk.addCPCLText(40,150,'55','0',0,'无骨鸡爪 一盒(约1.5磅)');
|
// strCmd += blesdk.addCPCLSETMAG(0,0);
|
// strCmd += blesdk.addCPCLText(350,180,'7','2',0,'2019-08-12');
|
|
// strCmd += blesdk.addCPCLLocation(2);
|
// strCmd += blesdk.addCPCLQRCode(0,220,'M', 2, 6, 'qr code test');
|
// strCmd += blesdk.addCPCLPrint();
|
// this.bufferData = strCmd;
|
// },
|
// 加载人员信息
|
fetchPersonInfo() {
|
console.log('Fetching person info for:', this.personCode); // 检查事件是否触发
|
|
if (this.personCode.trim()) {
|
uni.request({
|
url: `http://192.168.0.107:44380/api/persons/${encodeURIComponent(this.personCode)}`, // 修改后的请求路径
|
method: 'GET',
|
header: {
|
'Content-Type': 'application/json'
|
},
|
success: (res) => {
|
if (res.statusCode === 200) {
|
console.log(res.data.personnelName);
|
this.selectedPerson = res.data.personnelName; // 设置人员信息
|
console.log('Person info loaded:', this.selectedPerson);
|
} else {
|
console.error('Failed to fetch person info:', res);
|
}
|
},
|
fail: (err) => {
|
uni.showToast({
|
title: res,
|
icon: 'none',
|
duration: 2000
|
});
|
}
|
});
|
}
|
},
|
|
|
// 加载产线信息
|
fetchLineInfo() {
|
console.log('Fetching line info for:', this.lineCode); // 检查事件是否触发
|
|
if (this.lineCode.trim()) {
|
uni.request({
|
url: `http://192.168.0.107:44380/api/lines/${encodeURIComponent(this.lineCode.trim())}`, // 修改后的请求路径
|
method: 'GET',
|
header: {
|
'Content-Type': 'application/json'
|
},
|
success: (res) => {
|
if (res.statusCode === 200) {
|
console.log('Line info loaded:', res.data.lineNo);
|
this.selectedLine = res.data.lineName; // 设置产线信息
|
console.log('Line info loaded:', this.selectedLine);
|
// 选择完产线后加载对应的工单信息
|
this.loadOrders(this.lineCode);
|
// 选择完产线后加载对应的每日产能信息
|
this.loadDailyCapacity(this.lineCode);
|
} else {
|
console.error('Failed to fetch line info:', res);
|
}
|
},
|
fail: (err) => {
|
uni.showToast({
|
title: res,
|
icon: 'none',
|
duration: 2000
|
});
|
}
|
});
|
}
|
},
|
|
viewHistory() {
|
this.fetchHistoryRecords(this.selectedOrder);
|
this.showHistoryPopup = true;
|
|
},
|
// 关闭弹窗
|
closePopup() {
|
this.showHistoryPopup = false;
|
},
|
// 获取历史打印记录
|
fetchHistoryRecords(orderNo) {
|
uni.request({
|
url: `http://192.168.0.107:44380/api/print/printHistory?orderNo=${encodeURIComponent(orderNo)}`,
|
method: 'GET',
|
header: {
|
'Content-Type': 'application/json'
|
},
|
success: (res) => {
|
if (res.statusCode === 200) {
|
// 正确解析后端返回的数据
|
console.log('123', res.data.historyRecords);
|
//获取最新条码
|
this.lastRequestData = res.data.historyRecords[0].itemBarcode;
|
this.oldbgs = res.data.historyRecords[0].quantity;
|
console.log(this.lastRequestData);
|
// 将后端数据映射到前端使用的格式
|
this.historyList = (res.data.historyRecords || []).map(record => ({
|
itemBarcode: record.itemBarcode || '未知条码', // 确保解析字段
|
quantity: record.quantity || '未知数量', // 打印数量字段
|
printDate: record.printDate || '未知时间', // 打印时间
|
printedBy: record.printedBy || '未知用户' // 打印人
|
}));
|
console.log('History records loaded:', this.historyList);
|
} else {
|
console.error('Failed to fetch history records:', res);
|
}
|
},
|
fail: (err) => {
|
console.error('Error fetching history records:', err);
|
}
|
});
|
},
|
// 加载人员信息
|
loadPersons() {
|
uni.request({
|
url: "http://192.168.0.107:44380/api/persons", // 替换为你的 ASP.NET Core API 地址
|
method: 'GET',
|
header: {
|
'Content-Type': 'application/json'
|
},
|
success: (res) => {
|
if (res.statusCode === 200) {
|
// 过滤掉有空值或无效数据的项
|
// this.personOptions = res.data.filter(person => person.personName && person.personName.trim());
|
|
|
this.personList = res.data.filter(person =>
|
person.personName && person.personName.trim().length > 0
|
);
|
this.personOptions = this.personList.map(it => it.personName);
|
this.personIndex = -1;
|
} else {
|
console.error('Failed to fetch persons:', res);
|
}
|
},
|
fail: (err) => {
|
console.error('Error fetching persons:', err);
|
}
|
});
|
},
|
// 更新选中的人员名称
|
updatePersonName(e) {
|
this.personIndex = e.detail.value;
|
|
if (this.personIndex == -1) {
|
return;
|
}
|
|
this.selectedPerson = this.personList[this.personIndex].personName;
|
this.personId = this.personList[this.personIndex].personId;
|
console.log(this.personId + " :" + this.selectedPerson);
|
},
|
//加载产线信息
|
loadLines() {
|
uni.request({
|
url: "http://192.168.0.107:44380/api/lines", // 替换为你的 API 地址
|
method: 'GET',
|
header: {
|
'Content-Type': 'application/json'
|
},
|
success: (res) => {
|
if (res.statusCode === 200) {
|
this.lineList = res.data.filter(line =>
|
line.lineName && line.lineName.trim().length > 0
|
);
|
this.lineOptions = this.lineList.map(it => it.lineName);
|
console.log('Line options loaded:', this.lineOptions);
|
} else {
|
console.error('Failed to fetch lines:', res);
|
}
|
},
|
fail: (err) => {
|
console.error('Error fetching lines:', err);
|
}
|
});
|
},
|
// 更新选中的产线
|
updateLine(e) {
|
const selectedIndex = e.detail.value; //数组下标
|
this.selectedLine = this.lineOptions[selectedIndex];
|
this.lineCode = this.lineList[selectedIndex].lineNo; // 保存选中的产线编号
|
console.log('Selected line:', this.selectedLine);
|
console.log('Selected lineNo:', this.lineNo);
|
this.selectedOrder = null;
|
// 选择完产线后加载对应的工单信息
|
this.loadOrders(this.lineCode);
|
// 选择完产线后加载对应的每日产能信息
|
this.loadDailyCapacity(this.lineCode);
|
},
|
// 加载每日产能信息
|
loadDailyCapacity(lineNo) {
|
uni.request({
|
url: `http://192.168.0.107:44380/api/capacity?lineNo=${encodeURIComponent(lineNo)}`, // 假设你有一个获取每日产能的API
|
method: 'GET',
|
header: {
|
'Content-Type': 'application/json'
|
},
|
success: (res) => {
|
if (res.statusCode === 200 && Array.isArray(res.data) && res.data.length > 0) {
|
// 取出返回数组中的第一个对象的 daily 值
|
console.log(res.data);
|
this.dailyCapacity = res.data[0].daily; // 直接保存每日产能
|
this.checkedInspection = res.data[0].is_DJ == 1;
|
this.checkedMaintenance = res.data[0].is_WH == 1;
|
this.checkXJ = null;
|
this.checkFirstPass = null;
|
console.log('Daily capacity loaded:', this.dailyCapacity);
|
} else {
|
this.dailyCapacity = '暂无数据'; // 或者设置为其他默认值
|
this.checkedInspection = null; // 重置点检状态
|
this.checkedMaintenance = null; // 重置保养状态
|
this.checkXJ = null;
|
this.checkFirstPass = null;
|
|
console.error('Failed to fetch daily capacity or no data:', res);
|
}
|
},
|
|
fail: (err) => {
|
console.error('Error fetching daily capacity:', err);
|
}
|
});
|
},
|
// 加载工单信息
|
loadOrders(lineNo) {
|
uni.request({
|
url: `http://192.168.0.107:44380/api/orders?lineNo=${encodeURIComponent(lineNo)}`, // 使用存储的lineNo
|
method: 'GET',
|
header: {
|
'Content-Type': 'application/json'
|
},
|
success: (res) => {
|
if (res.statusCode === 200) {
|
this.orderList = res.data.filter(order =>
|
order.orderNo && order.orderNo.trim().length > 0
|
);
|
this.orderOptions = this.orderList.map(it => it.orderNo);
|
|
console.log('Order options loaded:', this.orderOptions);
|
} else {
|
console.error('Failed to fetch orders:', res);
|
}
|
},
|
fail: (err) => {
|
console.error('Error fetching orders:', err);
|
}
|
});
|
},
|
// 更新选中的工单
|
loadOrderDetails(e) {
|
const selectedIndex = e.detail.value; // 获取选择的索引
|
this.selectedOrder = this.orderOptions[selectedIndex]; // 获取选中的工单编号
|
this.orderNo = this.orderList[selectedIndex].orderNo; // 保存选中的工单编号
|
console.log('tiaoma', this.selectedOrder);
|
console.log('Selected orderNo:', this.orderNo);
|
this.orderDetails = {
|
requirementDoc: '', // 需求单据
|
productionOrder: '', // 生产订单
|
orderQuantity: '', // 订单数量
|
bzsl: '', // 推荐包装数
|
producedQuantity: '', // 已生产数
|
itemId: '', // 物料ID
|
itemNo: '', // 物料编码
|
itemname: '', // 物料名称
|
itemmodel: '', // 规格型号
|
|
|
};
|
//20250213 修改历史打印记录为null
|
lastRequestData: null;
|
console.log('lastRequestData:', this.lastRequestData);
|
// 调用开工工单方法
|
this.startProduction();
|
// 调用 API 获取工单详情
|
uni.request({
|
url: `http://192.168.0.107:44380/api/orderDetails?orderNo=${encodeURIComponent(this.orderNo)}`, // 使用存储的orderNo
|
method: 'GET',
|
header: {
|
'Content-Type': 'application/json'
|
},
|
success: (res) => {
|
console.log('gongdanxinx', res.data);
|
if (res.statusCode === 200) {
|
this.orderDetails = {
|
requirementDoc: res.data.requirementDoc, // 需求单据
|
productionOrder: res.data.productionOrder, // 生产订单
|
orderQuantity: res.data.orderQuantity, // 订单数量
|
bzsl: res.data.bzsl, // 推荐包装数
|
producedQuantity: res.data.producedQuantity, // 已生产数
|
itemId: res.data.itemId, // 物料ID
|
itemNo: res.data.itemNO, // 物料编码
|
itemname: res.data.itemname, // 物料名称
|
itemmodel: res.data.itemmodel, // 规格型号
|
|
|
};
|
// 根据 sj 和 xj 的值来设置首检和巡检状态
|
// 根据 sj 和 xj 的值来设置首检和巡检状态
|
if (res.data.sj === 1) {
|
this.checkFirstPass = true; // 首检合格
|
} else if (res.data.sj === 2) {
|
this.checkFirstPass = false; // 首检不合格
|
} else {
|
this.checkFirstPass = null; // 首检未做
|
}
|
|
if (res.data.xj === 1) {
|
this.checkXJ = true; // 巡检合格
|
} else if (res.data.xj === 2) {
|
this.checkXJ = false; // 巡检不合格
|
} else {
|
this.checkXJ = null; // 巡检未做
|
}
|
|
|
console.log('Order details loaded:', this.orderDetails);
|
|
} else {
|
console.error('Failed to fetch order details:', res);
|
}
|
},
|
fail: (err) => {
|
console.error('Error fetching order details:', err);
|
}
|
});
|
// 获取历史打印记录
|
console.log('12355', this.orderNo);
|
this.historyList = [];
|
this.fetchHistoryRecords(this.orderNo);
|
|
|
},
|
//刷新
|
refreshStatus() {
|
if (!this.lineCode) {
|
console.warn("未选择产线:设备点检和保养状态设置为未做");
|
this.checkedInspection = 0;
|
this.checkedMaintenance = 0;
|
}
|
|
if (!this.selectedOrder) {
|
console.warn("未选择工单:首检和巡检状态设置为未做");
|
this.checkFirstPass = null;
|
this.checkXJ = null;
|
}
|
console.log(this.lineCode);
|
console.log(this.selectedOrder);
|
uni.request({
|
url: `http://192.168.0.107:44380/api/refresh`,
|
method: 'POST',
|
header: {
|
'Content-Type': 'application/json'
|
},
|
data: {
|
lineNo: this.lineCode,
|
orderNo: this.selectedOrder || "N/A" // 未选择工单时使用占位符
|
},
|
success: (res) => {
|
if (res.statusCode === 200 && res.data) {
|
console.log("刷新成功:", res.data);
|
|
// 解析后端返回的数字状态
|
this.checkFirstPass = this.mapStatus(res.data.checkFirstPass); // 映射首检状态
|
this.checkXJ = this.mapStatus(res.data.checkXJ); // 映射巡检状态
|
this.checkedInspection = res.data.checkedInspection === 1; // 点检:1=true, 2=false
|
this.checkedMaintenance = res.data.checkedMaintenance === 1; // 保养:1=true, 2=false
|
console.log("刷新成功:首检", this.checkFirstPass);
|
console.log("刷新成功:巡检", this.checkXJ);
|
|
|
uni.showToast({
|
title: '刷新成功',
|
icon: 'success'
|
});
|
} else {
|
console.error("刷新失败:", res);
|
uni.showToast({
|
title: '刷新失败,数据异常',
|
icon: 'none'
|
});
|
}
|
},
|
fail: (err) => {
|
console.error("刷新接口请求失败:", err);
|
uni.showToast({
|
title: '刷新失败,网络异常',
|
icon: 'none'
|
});
|
}
|
});
|
},
|
mapStatus(status) {
|
if (status === 3) {
|
return null; // 未做
|
} else if (status === 1) {
|
return true; // 合格
|
} else if (status === 2) {
|
return false; // 不合格
|
}
|
return null; // 默认未做
|
},
|
|
//开工工单
|
startProduction() {
|
if (!this.selectedOrder) {
|
uni.showToast({
|
title: '请先选择工单',
|
icon: 'none'
|
});
|
return;
|
}
|
|
uni.request({
|
url: 'http://192.168.0.107:44380/api/Inspection/startProduction',
|
method: 'POST',
|
header: {
|
'Content-Type': 'application/json'
|
},
|
data: {
|
orderNo: this.selectedOrder, // 传入工单号
|
UserId: this.selectedPerson,
|
},
|
success: (res) => {
|
if (res.statusCode === 200) {
|
uni.showToast({
|
title: res.data.message,
|
icon: 'success'
|
});
|
} else {
|
uni.showToast({
|
title: res.data.message || '开工失败',
|
icon: 'none'
|
});
|
}
|
},
|
fail: (err) => {
|
console.error('开工请求失败:', err);
|
uni.showToast({
|
title: '开工请求失败',
|
icon: 'none'
|
});
|
}
|
});
|
},
|
|
// 格式化日期函数
|
formatDate(date) {
|
const year = date.getFullYear();
|
const month = String(date.getMonth() + 1).padStart(2, '0');
|
const day = String(date.getDate()).padStart(2, '0');
|
const hours = String(date.getHours()).padStart(2, '0');
|
const minutes = String(date.getMinutes()).padStart(2, '0');
|
const seconds = String(date.getSeconds()).padStart(2, '0');
|
const milliseconds = String(date.getMilliseconds()).padStart(3, '0'); // 毫秒
|
return `${year}${month}${day}${hours}${minutes}${seconds}${milliseconds}`;
|
},
|
formatDate2(date) {
|
const year = date.getFullYear();
|
const month = String(date.getMonth() + 1).padStart(2, '0');
|
const day = String(date.getDate()).padStart(2, '0');
|
const hours = String(date.getHours()).padStart(2, '0');
|
const minutes = String(date.getMinutes()).padStart(2, '0');
|
const seconds = String(date.getSeconds()).padStart(2, '0');
|
const milliseconds = String(date.getMilliseconds()).padStart(3, '0'); // 毫秒
|
|
//return `${year}/${month}/${day} ${hours}:${minutes}:${seconds}`; // 使用统一的格式:YYYY/MM/DD HH:mm:ss
|
return `${year}${month}${day}${hours}${minutes}${seconds}${milliseconds}`;
|
|
},
|
// 首检送检功能
|
sendForFirstInspection() {
|
const orderNumber = this.selectedOrder; // 从组件状态中获取工单号
|
console.log('Sending for first inspection with order number:', orderNumber);
|
console.log('Sending for first inspection with personCode:', this.personCode);
|
|
if (orderNumber.trim()) {
|
const requestData = {
|
ReleaseNo: orderNumber, // 使用传入的工单号
|
UserId: this.personCode, // 确保这里有对应的用户ID
|
|
};
|
console.log(requestData);
|
|
uni.request({
|
url: 'http://192.168.0.107:44380/api/Inspection/firstinspection', // 确保请求路径正确
|
method: 'POST',
|
header: {
|
'Content-Type': 'application/json'
|
},
|
data: requestData, // 发送请求数据
|
success: (res) => {
|
if (res.statusCode === 200) {
|
console.log('First inspection submitted successfully:', res.data);
|
uni.showToast({
|
title: '首检送检成功',
|
icon: 'success',
|
duration: 2000
|
});
|
} else {
|
console.error('Failed to send for first inspection:', res);
|
console.error('res.data.message:', res.data.message);
|
uni.showToast({
|
title: res.data.message,
|
icon: 'none',
|
duration: 2000
|
});
|
}
|
},
|
fail: (err) => {
|
console.error('Request failed:', err);
|
uni.showToast({
|
title: '网络错误',
|
icon: 'none',
|
duration: 2000
|
});
|
}
|
});
|
} else {
|
uni.showToast({
|
title: '工单号不能为空',
|
icon: 'none',
|
duration: 2000
|
});
|
}
|
},
|
|
|
// 提交报工信息的方法
|
printBarcode() {
|
// **先检查 USB 连接状态**
|
if (!UsbModule || !UsbModule.isUsbConnect || !UsbModule.isUsbConnect()) {
|
uni.showModal({
|
title: ` ${this.networkState}`,
|
content: "请检查打印机连接",
|
showCancel: false,
|
success: () => {
|
this.modalVisible = false;
|
|
}
|
});
|
return; // **USB 连接失败,直接返回,防止执行打印**
|
}
|
|
uni.request({
|
url: `http://192.168.0.107:44380/api/persons/${encodeURIComponent(this.personCode)}`, // 修改后的请求路径
|
method: 'GET',
|
header: {
|
'Content-Type': 'application/json'
|
},
|
success: (res) => {
|
if (res.statusCode === 200) {
|
console.log(res.data.personnelName);
|
this.selectedPerson = res.data.personnelName; // 设置人员信息
|
console.log('Person info loaded:', this.selectedPerson);
|
} else {
|
console.error('Failed to fetch person info:', res);
|
}
|
},
|
fail: (err) => {
|
uni.showToast({
|
title: res,
|
icon: 'none',
|
duration: 2000
|
});
|
}
|
});
|
|
// 禁用按钮5秒
|
this.isButtonDisabled = true;
|
setTimeout(() => {
|
this.isButtonDisabled = false;
|
}, 5000);
|
// 校验报工数
|
if (this.reportedQuantity <= 0 ||
|
Number(this.reportedQuantity) + Number(this.orderDetails.producedQuantity) > Number(this
|
.orderDetails.orderQuantity)) {
|
uni.showToast({
|
title: '报工数无效或超出订单数量,请检查。',
|
icon: 'none',
|
duration: 2000
|
});
|
// 显示自定义的红色背景、白色字体的提示框
|
// this.$refs.customToast.showToast('报工数无效或超出订单数量,请检查。');
|
|
|
return;
|
}
|
|
// 格式化当前时间为"年月日时分秒"格式
|
const currentTime = new Date();
|
const formattedTime = this.formatDate(currentTime);
|
// 构造请求数据
|
const requestData = {
|
orderNo: this.selectedOrder,
|
p_person: this.personCode,
|
//reportedQuantity: this.reportedQuantity,
|
itemId: this.orderDetails.itemId,
|
uniqueValue: `${this.orderDetails.itemNo}-${formattedTime}`, // 使用格式化后的时间
|
//itemCode: this.orderDetails.itemNo, // 假设物料编码为itemId
|
//itemSpec: '规格型号', // 这里可改成实际数据
|
quantity: Number(this.reportedQuantity) // 确保是整数
|
|
};
|
this.logPrintEvent("打印前", "打印条码前",requestData.uniqueValue);
|
// 将 requestData 保存到 lastRequestData 中
|
this.lastRequestData = requestData;
|
console.log(requestData);
|
console.log(this.selectedPerson);
|
try {
|
// 调用后端 API
|
uni.request({
|
url: "http://192.168.0.107:44380/api/print",
|
method: 'POST',
|
header: {
|
'Content-Type': 'application/json'
|
},
|
data: requestData,
|
success: (response) => {
|
if (response.statusCode === 200) {
|
uni.showToast({
|
title: '数据提交成功',
|
icon: 'success',
|
duration: 2000
|
});
|
const currentTime = new Date();
|
const formattedTime2 = this.formatDate2(currentTime);
|
this.lastRequestData = requestData.uniqueValue;
|
// 将打印的条码记录添加到历史记录中
|
this.historyList.push({
|
itemBarcode: requestData.uniqueValue,
|
printDate: formattedTime2.toLocaleString(),
|
printedBy: this.selectedPerson
|
});
|
//显示生产数添加
|
this.orderDetails.producedQuantity = Number(this.orderDetails
|
.producedQuantity) + Number(this.reportedQuantity);
|
//显示报工数添加
|
this.dailyCapacity = Number(this.dailyCapacity) + Number(this
|
.reportedQuantity);
|
this.logPrintEvent("打印前", "报工成功", requestData.uniqueValue);
|
|
} else {
|
console.log(response.data.message);
|
uni.showToast({
|
title: response.data.message,
|
icon: 'none',
|
duration: 2000
|
});
|
console.error("Print failed:", response);
|
this.logPrintEvent("打印前", "异常且返回", requestData.uniqueValue);
|
//打印条码
|
return;
|
}
|
// **先记录 "打印前" 事件**
|
this.logPrintEvent("打印前", "打印", requestData.uniqueValue);
|
//打印条码
|
console.log('tiaoma', requestData.uniqueValue);
|
console.log('gd', this.orderDetails.productionOrder);
|
console.log('tiaoma', this.selectedOrder);
|
console.log('gys', this.orderDetails.requirementDoc);
|
console.log('wlbm', this.orderDetails.itemNo);
|
console.log('wlmc', this.orderDetails.itemname);
|
console.log('ggxh', this.orderDetails.itemmodel);
|
console.log('sl', this.reportedQuantity);
|
|
// 打印内容样式设置
|
const command = tsc.jpPrinter.createNew();
|
|
// 设置宽度 100mm 和高度 80mm(换算后大约 799x639 像素)
|
command.setSize(100, 80);
|
|
//command.setBackFeed(2.5);
|
|
// 外框线条
|
command.setCls();
|
command.setBox(10, 10, 789, 629); // 外框,距离页面边缘 10px
|
|
// 第一部分:条码、工单号、供应商信息 + 大二维码
|
command.setBar(20, 40, "128", 100, 1, 0, 2, requestData.uniqueValue); // 条码
|
command.setText(20, 40, "TSS24.BF2", 1, 1, "物料条码: ");
|
command.setText(150, 40, "TSS24.BF2", 1, 1, requestData.uniqueValue);
|
|
// 工单号
|
command.setText(20, 100, "TSS24.BF2", 1, 1, "工单号: ");
|
command.setText(150, 100, "TSS24.BF2", 1, 1, this.selectedOrder);
|
|
// 供应商信息
|
command.setText(20, 160, "TSS24.BF2", 1, 1, "需求单据号: ");
|
command.setText(150, 160, "TSS24.BF2", 1, 1, this.orderDetails.requirementDoc);
|
|
// 右侧大二维码
|
command.setQR(550, 100, "L", 6, "A", requestData.uniqueValue); // 大二维码
|
|
// 第二部分:物料编码
|
command.setText(20, 220, "TSS24.BF2", 1, 1, "物料编码: ");
|
command.setText(150, 220, "TSS24.BF2", 1, 1, this.orderDetails.itemNo);
|
|
|
// 第三部分:物料名称
|
command.setText(20, 280, "TSS24.BF2", 1, 1, "物料名称: ");
|
command.setText(150, 280, "TSS24.BF2", 1, 1, this.orderDetails.itemname);
|
|
// 第四部分:数量与需求单据号
|
command.setText(20, 340, "TSS24.BF2", 1, 1, "数量: ");
|
command.setText(120, 340, "TSS24.BF2", 1, 1, this.reportedQuantity);
|
command.setText(200, 340, "TSS24.BF2", 1, 1, "打印人: ");
|
command.setText(290, 340, "TSS24.BF2", 1, 1, this.selectedPerson);
|
|
|
|
// command.setText(290, 340, "FONT 3", 1, 1, this.selectedPerson);
|
// command.setText(290, 340, "TSS24.BF2", 1, 1, encodeURI(this.selectedPerson));
|
command.setText(400, 340, "TSS24.BF2", 1, 1, "打印时间: ");
|
command.setText(530, 340, "TSS24.BF2", 1, 1, this.formatDate2(new Date()));
|
// 第五部分:左侧二维码 + 规格型号
|
command.setQR(20, 400, "L", 5, "A", requestData.uniqueValue); // 左侧二维码
|
command.setText(200, 400, "TSS24.BF2", 1, 1, "规格型号: ");
|
command.setText(200, 440, "TSS24.BF2", 1, 1, this.orderDetails.itemmodel);
|
|
|
command.setText(200, 535, "TSS24.BF2", 1, 1, "慈溪市夏蒙电器有限公司丨注塑车间");
|
command.setText(201, 536, "TSS24.BF2", 1, 1, "慈溪市夏蒙电器有限公司丨注塑车间");
|
// 打印指令
|
command.setPagePrint();
|
|
// command.setFeed(30);
|
this.sendData = command.getData();
|
|
// 1. 执行发送
|
let printResult = this.senUSBData();
|
|
// 2. 判断发送是否成功
|
if (printResult.success) {
|
// ✅ 发送成功,记录打印日志
|
this.logPrintEvent("打印后", "打印", requestData.uniqueValue);
|
} else {
|
// ❌ 发送失败,提示用户,不记录日志
|
uni.showToast({
|
title: "打印失败,未记录日志",
|
duration: 2000
|
});
|
}
|
|
this.oldbgs = this.reportedQuantity;
|
//从新刷新工单信息
|
loadOrderDetails();
|
//从新刷新历史记录
|
|
this.fetchHistoryRecords(this.orderNo);
|
|
},
|
fail: (err) => {
|
console.error("Error during print request:", err);
|
}
|
});
|
|
|
} catch (err) {
|
console.error('Error during print request:', err);
|
}
|
},
|
// splitTextByWidth(text, maxCharsPerLine) {
|
// const lines = [];
|
// while (text.length > maxCharsPerLine) {
|
// lines.push(text.slice(0, maxCharsPerLine)); // 截取最大长度
|
// text = text.slice(maxCharsPerLine); // 剩下的继续截取
|
// }
|
// lines.push(text); // 最后一行
|
// return lines;
|
// },
|
|
// 补打上一张记录
|
reprintLast() {
|
|
// 禁用按钮5秒
|
this.isButtonDisabled2 = true;
|
setTimeout(() => {
|
this.isButtonDisabled2 = false;
|
}, 5000);
|
// **先检查 USB 连接状态**
|
if (!UsbModule || !UsbModule.isUsbConnect || !UsbModule.isUsbConnect()) {
|
uni.showModal({
|
title: ` ${this.networkState}`,
|
content: "请检查打印机连接",
|
showCancel: false,
|
success: () => {
|
this.modalVisible = false;
|
}
|
});
|
//return; // **USB 连接失败,直接返回,防止执行打印**
|
}
|
uni.request({
|
url: `http://192.168.0.107:44380/api/persons/${encodeURIComponent(this.personCode)}`, // 修改后的请求路径
|
method: 'GET',
|
header: {
|
'Content-Type': 'application/json'
|
},
|
success: (res) => {
|
if (res.statusCode === 200) {
|
console.log(res.data.personnelName);
|
this.selectedPerson = res.data.personnelName; // 设置人员信息
|
console.log('Person info loaded:', this.selectedPerson);
|
} else {
|
console.error('Failed to fetch person info:', res);
|
}
|
},
|
fail: (err) => {
|
uni.showToast({
|
title: res,
|
icon: 'none',
|
duration: 2000
|
});
|
}
|
});
|
|
// 补打上一张记录
|
this.fetchHistoryRecords(this.orderNo);
|
if (!this.lastRequestData) {
|
uni.showToast({
|
title: '没有可补打的记录',
|
icon: 'none',
|
duration: 2000
|
});
|
return;
|
}
|
console.log("老条码", this.oldbgs);
|
// 重新打印上一张记录
|
// async reprintLast() {
|
// // 清空上次的数据,确保获取到最新数据
|
// this.lastRequestData = null;
|
// this.bgs = null;
|
|
// // 等待 fetchHistoryRecords 请求完成
|
// await this.fetchHistoryRecords(this.orderNo);
|
// console.log("刷新", this.lastRequestData);
|
// // 检查是否有历史记录,如果没有则提示
|
// if (!this.lastRequestData || this.bgs == null) {
|
// uni.showToast({
|
// title: '没有可补打的记录',
|
// icon: 'none',
|
// duration: 2000
|
// });
|
// return; // 退出,避免继续执行打印
|
// }
|
// **记录 "补打前" 事件**
|
this.logPrintEvent("打印前", "补打", this.lastRequestData);
|
// 打印内容样式设置
|
const command = tsc.jpPrinter.createNew();
|
|
// 设置宽度 100mm 和高度 80mm(换算后大约 799x639 像素)
|
command.setSize(100, 80);
|
//command.setBackFeed(2.5);
|
// 外框线条
|
command.setCls();
|
command.setBox(10, 10, 789, 629); // 外框,距离页面边缘 10px
|
|
// 第一部分:条码、工单号、供应商信息 + 大二维码
|
command.setBar(20, 40, "128", 100, 1, 0, 2, this.lastRequestData); // 条码
|
command.setText(20, 40, "TSS24.BF2", 1, 1, "物料条码: ");
|
command.setText(150, 40, "TSS24.BF2", 1, 1, this.lastRequestData);
|
|
// 工单号
|
command.setText(20, 100, "TSS24.BF2", 1, 1, "工单号: ");
|
command.setText(150, 100, "TSS24.BF2", 1, 1, this.selectedOrder);
|
|
// 供应商信息
|
command.setText(20, 160, "TSS24.BF2", 1, 1, "需求单据号: ");
|
command.setText(150, 160, "TSS24.BF2", 1, 1, this.orderDetails.requirementDoc);
|
|
// 右侧大二维码
|
command.setQR(550, 100, "L", 6, "A", this.lastRequestData); // 大二维码
|
|
// 第二部分:物料编码
|
command.setText(20, 220, "TSS24.BF2", 1, 1, "物料编码: ");
|
command.setText(150, 220, "TSS24.BF2", 1, 1, this.orderDetails.itemNo);
|
|
|
// 第三部分:物料名称
|
command.setText(20, 280, "TSS24.BF2", 1, 1, "物料名称: ");
|
command.setText(150, 280, "TSS24.BF2", 1, 1, this.orderDetails.itemname);
|
|
// 第四部分:数量与需求单据号
|
command.setText(20, 340, "TSS24.BF2", 1, 1, "数量: ");
|
command.setText(120, 340, "TSS24.BF2", 1, 1, this.oldbgs);
|
command.setText(200, 340, "TSS24.BF2", 1, 1, "打印人: ");
|
|
|
command.setText(290, 340, "TSS24.BF2", 1, 1, this.selectedPerson);
|
command.setText(400, 340, "TSS24.BF2", 1, 1, "打印时间: ");
|
command.setText(530, 340, "TSS24.BF2", 1, 1, this.formatDate2(new Date()));
|
// 第五部分:左侧二维码 + 规格型号
|
command.setQR(20, 400, "L", 5, "A", this.lastRequestData); // 左侧二维码
|
command.setText(200, 400, "TSS24.BF2", 1, 1, "规格型号: ");
|
command.setText(200, 440, "TSS24.BF2", 1, 1, this.orderDetails.itemmodel);
|
|
// command.setText(350, 510, "TSS24.BF2", 1, 1, "注塑车间");
|
// command.setText(351, 511, "TSS24.BF2", 1, 1, "注塑车间");
|
command.setText(200, 535, "TSS24.BF2", 1, 1, "慈溪市夏蒙电器有限公司丨注塑车间");
|
command.setText(201, 536, "TSS24.BF2", 1, 1, "慈溪市夏蒙电器有限公司丨注塑车间");
|
|
// 打印指令
|
command.setPagePrint();
|
command.setFeed(3);
|
this.sendData = command.getData();
|
// 1. 执行发送
|
let printResult = this.senUSBData();
|
|
// 2. 判断发送是否成功
|
if (printResult.success) {
|
// 发送成功,记录打印日志
|
this.logPrintEvent("打印后", "补打", this.lastRequestData);
|
} else {
|
// 发送失败,提示用户,不记录日志
|
uni.showToast({
|
title: "打印失败,未记录日志",
|
duration: 2000
|
});
|
}
|
F
|
// 发送数据
|
this.senUSBData();
|
// **记录 "补打后" 事件**
|
|
}
|
,
|
logPrintEvent(eventType, printType, barcodeValue) {
|
|
|
const requestData = {
|
barcode: barcodeValue, // 条码
|
worker: this.personCode, // 报工人
|
eventType: eventType, // "打印前" 或 "打印后"
|
printType: printType, // "打印" 或 "补打"
|
orderNo: this.selectedOrder, // 工单号
|
line: this.selectedLine ,
|
version:this.version// 线体
|
};
|
console.log(requestData);
|
uni.request({
|
url: "http://192.168.0.107:44380/api/LogPrintEvent/logEvent",
|
method: 'POST',
|
header: {
|
'Content-Type': 'application/json'
|
},
|
data: requestData,
|
success: (response) => {
|
if (response.statusCode === 200) {
|
console.log(`${eventType} - ${printType} 记录成功`);
|
} else {
|
console.error(`${eventType} - ${printType} 记录失败:`, response);
|
}
|
},
|
fail: (err) => {
|
console.error("请求失败:", err);
|
}
|
});
|
}
|
}
|
};
|
</script>
|
|
<style>
|
/* 头 */
|
.head {
|
display: flex;
|
/* 左右布局 */
|
background-color: #fff;
|
/* 主背景色 */
|
padding: 10px;
|
/* 整体内边距 */
|
gap: 10px;
|
/* 间隙 */
|
height: 280px;
|
|
}
|
|
.head-left {
|
display: flex;
|
height: 280x;
|
flex-direction: column;
|
width: 60%;
|
/* 左侧占40% */
|
background-color: #fff;
|
/* 左侧背景色 */
|
padding: 10px;
|
border-radius: 5px;
|
/* background-color: #0069d9; */
|
}
|
|
.head-top {
|
display: flex;
|
justify-content: space-between;
|
/* 左右对齐 */
|
background-color: #fff;
|
/* 上部背景色 */
|
/* padding: 10px; */
|
border-radius: 5px;
|
height: 100px;
|
/* 设置头部区域的固定高度 */
|
|
}
|
|
.ry {
|
width: 48%;
|
/* 设置为48%,保证两个输入框并排时不超出宽度 */
|
/* background-color: #aaffff; /* 控件背景色 */
|
|
border-radius: 3px;
|
display: flex;
|
margin-bottom: 10px;
|
height: 100px;
|
}
|
|
.cx {
|
width: 48%;
|
/* 设置为48%,保证两个输入框并排时不超出宽度 */
|
/* background-color: #ffff7f; /* 控件背景色 */
|
/* background-color: #8fdd83; */
|
border: 1px solid #ddd;
|
border-radius: 10px;
|
margin-bottom: 10px;
|
height: 100%;
|
/* 高度填充父容器 */
|
}
|
|
.ryxx {
|
width: 70%;
|
/* 确保输入框占满父元素 */
|
height: 100%;
|
/* 输入框高度填充父元素 */
|
display: flex;
|
font-size: 35px;
|
font-weight: bold;
|
border: 1px solid #ddd;
|
border-radius: 10px;
|
align-items: center;
|
/* 垂直居中对齐 */
|
|
}
|
|
.input-box {
|
font-size: 30px;
|
font-weight: bold;
|
}
|
|
.input-box2 {
|
width: 100%;
|
height: 100%;
|
font-size: 20px;
|
font-weight: bold;
|
background-color: #8fdd83;
|
/* 控件背景色 */
|
border: 1px solid #ddd;
|
border-radius: 10px;
|
margin-right: 0;
|
/* 去除右侧间距 */
|
|
}
|
|
.confirm-btn {
|
background-color: #ffffff;
|
/* 按钮背景色 */
|
border: 1px solid #ddd;
|
width: 40%;
|
border: none;
|
/* 无边框 */
|
border-radius: 10px;
|
/* 圆角 */
|
cursor: pointer;
|
/* 鼠标悬停时显示手型 */
|
font-size: 20px;
|
/* 字体大小 */
|
font-weight: bold;
|
height: 100%;
|
/* 按钮高度与输入框一致 */
|
display: flex;
|
align-items: center;
|
/* 垂直居中 */
|
justify-content: center;
|
/* 水平居中 */
|
border: 1px solid #ddd;
|
|
}
|
|
.confirm-btn:hover {
|
background-color: #45a049;
|
/* 鼠标悬停时变深 */
|
}
|
|
.head-but {
|
margin-top: 10px;
|
width: 100%;
|
height: 180px;
|
|
|
}
|
|
|
|
|
|
.head-right {
|
width: 40%;
|
/* 右侧占60% */
|
background-color: #8fdd83;
|
/* 右侧背景色 */
|
/* padding: 10px; */
|
height: 280px;
|
border-radius: 10px;
|
/* background-color: #333; */
|
}
|
|
.capacity-title {
|
font-size: 20px;
|
font-weight: bold;
|
|
height: 15%;
|
}
|
|
.picker {
|
width: 100%;
|
font-size: 35px;
|
height: 100px;
|
|
font-weight: bold;
|
display: flex;
|
align-items: center;
|
/* 垂直居中 */
|
justify-content: center;
|
/* 水平居中 */
|
}
|
|
.picker2 {
|
width: 100%;
|
font-size: 35px;
|
height: 100px;
|
font-weight: bold;
|
display: flex;
|
align-items: center;
|
/* 垂直居中 */
|
justify-content: center;
|
/* 水平居中 */
|
}
|
|
.error-star {
|
color: red;
|
margin-left: 5px;
|
/* 可以根据需要调整位置 */
|
font-size: 35px;
|
/* 也可以调整大小 */
|
}
|
|
.capacity-content {
|
font-weight: bold;
|
font-size: 100px;
|
height: 80%;
|
display: flex;
|
align-items: center;
|
/* 垂直居中 */
|
justify-content: center;
|
/* 水平居中 */
|
|
/* color: #fff; */
|
|
}
|
|
.form-group {
|
display: flex;
|
flex-direction: column;
|
/* 改为纵向排列 */
|
border: 1px solid #ddd;
|
border-radius: 10px;
|
font-size: 20px;
|
font-weight: bold;
|
height: 155px;
|
}
|
|
|
|
|
|
.label {
|
font-weight: bold;
|
}
|
|
.text {
|
margin-left: 5px;
|
}
|
|
/* 人员信息和产线信息 */
|
.xzxx {
|
|
padding: 10px;
|
background-color: #FFF;
|
/* 背景色 */
|
border-radius: 5px;
|
/* 圆角 */
|
display: flex;
|
/* 左右布局 */
|
}
|
|
.person-line-info {
|
display: flex;
|
/* 左右布局 */
|
justify-content: space-between;
|
/* 两边对齐 */
|
}
|
|
.person-info,
|
.line-info {
|
font-size: 20px;
|
font-weight: bold;
|
margin-left: 5px;
|
width: 48%;
|
/* 各占一半 */
|
background-color: #fff;
|
/* 背景色 */
|
padding: 10px;
|
border-radius: 5px;
|
}
|
|
.order-label {
|
margin-bottom: 10px;
|
/* 标签和选择器之间的间距 */
|
}
|
|
|
/* 工单信息 */
|
.order-details {
|
|
padding: 10px;
|
border: 1px solid #ddd;
|
/* 添加边框 */
|
border-radius: 4px;
|
/* 圆角 */
|
background-color: #FFF;
|
/* 淡灰色背景 */
|
}
|
|
.order-details text {
|
display: block;
|
/* 每条信息占一行 */
|
margin-bottom: 8px;
|
/* 每条信息之间增加间距 */
|
font-size: 18px;
|
/* 调整字体大小 */
|
color: #333;
|
/* 字体颜色 */
|
}
|
|
|
.order-details-row {
|
display: flex;
|
justify-content: space-between;
|
margin-bottom: 10px;
|
}
|
|
|
.order-details-row {
|
display: flex;
|
justify-content: space-between;
|
margin-bottom: 10px;
|
}
|
|
.order-details-column {
|
flex: 1;
|
display: flex;
|
flex-direction: row;
|
align-items: center;
|
justify-content: space-between;
|
padding: 0 10px;
|
}
|
|
.order-details-column text:first-child {
|
font-weight: bold;
|
margin-right: 10px;
|
}
|
|
/* 报工模块 */
|
.baogong {
|
display: flex;
|
/* 左右布局 */
|
|
background-color: #FFF;
|
padding: 10px;
|
border-radius: 5px;
|
}
|
|
.capacity-contencapacity-contentt {
|
display: flex;
|
/* 左右布局 */
|
}
|
|
.baogong-left {
|
width: 50%;
|
/* 左边占50% */
|
display: flex;
|
flex-direction: column;
|
gap: 10px;
|
/* 每个元素间的间隙 */
|
height: 300px;
|
justify-content: space-between;
|
/* 上中下均匀分布 */
|
margin-left: 5%;
|
|
}
|
|
.right-column {
|
border: 1px solid #ddd;
|
border-radius: 10px;
|
width: 100%;
|
height: 50%;
|
display: flex;
|
flex-direction: column;
|
justify-content: center;
|
/* 内容垂直居中 */
|
}
|
|
.print-button {
|
height: 20%;
|
/* 中间占20% */
|
}
|
|
.print-button button {
|
width: 100%;
|
height: 100%;
|
background-color: #3a8a1d;
|
color: white;
|
border: none;
|
border-radius: 10px;
|
font-size: 18px;
|
display: flex;
|
align-items: center;
|
/* 垂直居中 */
|
justify-content: center;
|
/* 水平居中 */
|
}
|
|
.history-record {
|
display: flex;
|
justify-content: space-between;
|
/* 按钮之间左右对齐 */
|
height: 20%;
|
width: 100%;
|
|
}
|
|
|
|
.uni-btn,
|
.lsjl {
|
font-size: 15px;
|
/* 设置字体大小 */
|
border: none;
|
/* 去掉边框 */
|
border-radius: 5px;
|
/* 圆角 */
|
padding: 10px 20px;
|
/* 内边距 */
|
cursor: pointer;
|
/* 鼠标悬停时显示为手指 */
|
}
|
|
.uni-btn:hover,
|
.lsjl:hover {
|
background-color: #ddd;
|
/* 悬停时的背景颜色 */
|
}
|
|
.baogong-right {
|
width: 45%;
|
/* 右边占50% */
|
display: flex;
|
height: 300px;
|
flex-direction: column;
|
gap: 10px;
|
/* 每个按钮间的间隙 */
|
|
|
}
|
|
.black-text text {
|
color: black;
|
}
|
|
.green-text text {
|
color: green;
|
}
|
|
.red-text text {
|
color: red;
|
}
|
|
|
.capacity-content2 {
|
width: 95%;
|
border-radius: 5px;
|
/* border: 1px solid #ddd; */
|
background-color: #fff;
|
border-radius: 8px;
|
text-align: center;
|
height: 60px;
|
margin-top: 25px;
|
}
|
|
.capacity-content2 text {
|
font-size: 30px;
|
color: white;
|
}
|
|
/* USB 打印机和首检送检按钮的左右布局 */
|
.usb-printer-section {
|
display: flex;
|
/* 左右布局 */
|
justify-content: space-between;
|
/* 左右两块对齐 */
|
margin-top: 20px;
|
/* 与上面的内容保持距离 */
|
padding: 10px;
|
background-color: #fff;
|
/* 背景色 */
|
border-radius: 5px;
|
/* 圆角 */
|
}
|
|
/* 左边的按钮组 */
|
.button-group {
|
width: 48%;
|
/* 左边占一半 */
|
}
|
|
|
|
.button-group button {
|
width: 100%;
|
/* 按钮宽度占满父元素 */
|
padding: 10px;
|
/* 按钮内边距 */
|
margin-bottom: 10px;
|
/* 按钮间距 */
|
/* background-color: #ddd; */
|
/* color: white; */
|
border: none;
|
/* 去除边框 */
|
border-radius: 8px;
|
/* 圆角按钮 */
|
font-size: 16px;
|
/* 字体大小 */
|
cursor: pointer;
|
/* 鼠标悬浮时显示手型 */
|
}
|
|
.button-group button:hover {
|
background-color: #ddd;
|
/* 悬浮时颜色稍微变深 */
|
}
|
|
/* 右边的圆形按钮 */
|
.circle-button {
|
width: 48%;
|
/* 右边占一半 */
|
display: flex;
|
justify-content: center;
|
align-items: center;
|
/* 垂直居中 */
|
}
|
|
.round-btn {
|
width: 200px;
|
/* 固定宽度 */
|
height: 200px;
|
/* 固定高度,保证按钮是圆形 */
|
background-color: #8fdd83;
|
/* 蓝色背景 */
|
/* color: white;*/
|
border: none;
|
border-radius: 50%;
|
/* 圆形按钮 */
|
font-size: 25px;
|
cursor: pointer;
|
/* 使按钮内的文字居中 */
|
display: flex;
|
/* 使用 flexbox */
|
justify-content: center;
|
/* 水平居中 */
|
align-items: center;
|
/* 垂直居中 */
|
}
|
|
.round-btn:hover {
|
background-color: #0069d9;
|
/* 悬浮时颜色稍微变深 */
|
}
|
|
/* 弹出框样式 */
|
.history-popup {
|
position: fixed;
|
top: 50%;
|
left: 50%;
|
transform: translate(-50%, -50%);
|
width: 80%;
|
height: 70%;
|
background-color: #fff;
|
border-radius: 8px;
|
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.2);
|
z-index: 1000;
|
display: flex;
|
flex-direction: column;
|
}
|
|
.popup-header {
|
display: flex;
|
justify-content: space-between;
|
align-items: center;
|
padding: 10px;
|
border-bottom: 1px solid #ccc;
|
}
|
|
.popup-title {
|
font-size: 18px;
|
font-weight: bold;
|
}
|
|
.close-btn {
|
background-color: red;
|
color: white;
|
border: none;
|
border-radius: 50%;
|
width: 25px;
|
height: 25px;
|
text-align: center;
|
line-height: 25px;
|
cursor: pointer;
|
display: flex;
|
/* 使用 flexbox */
|
justify-content: center;
|
/* 水平居中 */
|
align-items: center;
|
/* 垂直居中 */
|
|
}
|
|
|
.popup-content {
|
flex: 1;
|
padding: 10px;
|
overflow-y: auto;
|
}
|
|
/* 表头样式 */
|
.history-header {
|
display: flex;
|
justify-content: space-between;
|
font-weight: bold;
|
border-bottom: 1px solid #ccc;
|
padding-bottom: 5px;
|
margin-bottom: 5px;
|
}
|
|
/* 表头和表格内容的每列样式 */
|
.header-item,
|
.record-item {
|
flex: 1;
|
/* 每列占据相同的宽度 */
|
text-align: center;
|
/* 内容居中 */
|
padding: 5px;
|
word-wrap: break-word;
|
/* 允许内容换行 */
|
overflow: hidden;
|
/* 防止内容溢出 */
|
text-overflow: ellipsis;
|
/* 溢出时显示省略号 */
|
}
|
|
/* 表格内容行样式 */
|
.history-record {
|
display: flex;
|
justify-content: space-between;
|
border-bottom: 1px solid #eee;
|
padding: 5px 0;
|
font-size: 14px;
|
}
|
|
/* 滚动区域 */
|
.history-scroll {
|
max-height: 300px;
|
/* 根据需要调整滚动区域的高度 */
|
overflow-y: auto;
|
}
|
|
|
|
.record-item {
|
flex: 1;
|
text-align: center;
|
}
|
|
.status-container {
|
display: flex;
|
|
justify-content: space-between;
|
/* 使两个状态项之间有适当间距 */
|
margin-bottom: 10px;
|
/* 给按钮留出一些空间 */
|
}
|
|
.status-item {
|
flex: 1;
|
/* 让每个状态项占据相等的空间 */
|
padding: 10px;
|
/* 内边距 */
|
margin-right: 10px;
|
/* 在两个状态项之间添加一些间距 */
|
|
color: white;
|
/* 文字颜色 */
|
border: none;
|
/* 去除边框 */
|
border-radius: 8px;
|
/* 圆角 */
|
font-size: 20px;
|
/* 字体大小 */
|
display: flex;
|
align-items: center;
|
/* 垂直居中对齐 */
|
justify-content: center;
|
/* 水平居中对齐 */
|
transition: background-color 0.3s ease;
|
/* 添加平滑过渡效果 */
|
}
|
|
.status-item:last-child {
|
margin-right: 0;
|
/* 移除最后一个状态项的右边距 */
|
}
|
|
.normal {
|
color: green;
|
}
|
|
.error {
|
color: red;
|
}
|
|
.check-button {
|
width: 100%;
|
/* 使按钮宽度与容器宽度一致 */
|
box-sizing: border-box;
|
/* 确保内边距和边框包含在宽度内 */
|
}
|
</style>
|