Merge branch 'Dev' of http://101.37.171.70:10101/r/~jhz/STUWMS into Dev
| | |
| | | "name" : "智云LMES", |
| | | "appid" : "__UNI__B002F49", |
| | | "description" : "", |
| | | "versionName" : "3.020", |
| | | "versionCode" : 320, |
| | | "versionName" : "3.022", |
| | | "versionCode" : 322, |
| | | "transformPx" : false, |
| | | /* 5+App特有相关 */ |
| | | "app-plus" : { |
| | |
| | | <view class="bill-main-area"> |
| | | <!-- 主表页签 --> |
| | | <view class="bill-main-tabs"> |
| | | <view :class="mainTabSelected == 1 ? 'selected' : ''" @tap="mainTabSelected = 1">基本信息</view> |
| | | <view :class="mainTabSelected == 2 ? 'selected' : ''" @tap="mainTabSelected = 2">扫描信息</view> |
| | | <view :class="mainTabSelected == 3 ? 'selected' : ''" @tap="mainTabSelected = 3">制单信息</view> |
| | | <view :class="mainTabSelected == 4 ? 'selected' : ''" @tap="mainTabSelected = 4">其他信息</view> |
| | | <view class="tabs-left"> |
| | | <view :class="mainTabSelected == 1 ? 'selected' : ''" @tap="mainTabSelected = 1">基本信息</view> |
| | | <view :class="mainTabSelected == 2 ? 'selected' : ''" @tap="mainTabSelected = 2">扫描信息</view> |
| | | <view :class="mainTabSelected == 3 ? 'selected' : ''" @tap="mainTabSelected = 3">制单信息</view> |
| | | <view :class="mainTabSelected == 4 ? 'selected' : ''" @tap="mainTabSelected = 4">其他信息</view> |
| | | </view> |
| | | <view class="mode-switch-right"> |
| | | <text class="mode-text">{{ directInputMode ? '直接输入' : '双击累加' }}</text> |
| | | <switch :checked="directInputMode" @change="onModeSwitchChange" color="#3a78ff" style="transform: scale(0.7);" /> |
| | | </view> |
| | | </view> |
| | | <!-- 主表内容 --> |
| | | <view class="bill-main-contents"> |
| | |
| | | |
| | | <BillListPopupVue ref="billList" :HBillType="hform.HBillType" :HSourceBillType="hform.HSourceBillType" |
| | | :HStockOrgID="hform.HStockOrgID" @BillSelectComplete="HandleBillSelectComplete"></BillListPopupVue> |
| | | |
| | | <!-- 直接输入数量弹窗 --> |
| | | <uni-popup ref="inputQtyPopup" type="center"> |
| | | <view class="input-qty-popup"> |
| | | <view class="popup-title">输入不良数量</view> |
| | | <view class="popup-content"> |
| | | <view class="popup-info"> |
| | | <text class="popup-label">不良原因:</text> |
| | | <text class="popup-value">{{ currentItem && currentItem.不良原因名称 || '' }}</text> |
| | | </view> |
| | | <view class="popup-info"> |
| | | <text class="popup-label">当前数量:</text> |
| | | <text class="popup-value">{{ currentItem && currentItem.num || 0 }}</text> |
| | | </view> |
| | | <view class="popup-input-row"> |
| | | <text class="popup-label">输入数量:</text> |
| | | <input class="popup-input" type="number" v-model="inputQtyValue" placeholder="请输入数量" /> |
| | | </view> |
| | | </view> |
| | | <view class="popup-buttons"> |
| | | <button class="btn-c" size="mini" @tap="cancelInputQty">取消</button> |
| | | <view style="flex: 1;"></view> |
| | | <button class="btn-a" size="mini" @tap="confirmInputQty">确认</button> |
| | | </view> |
| | | </view> |
| | | </uni-popup> |
| | | </view> |
| | | </template> |
| | | |
| | |
| | | //上一次点击时间 |
| | | lastClickTime: 0, |
| | | operationType: 1, |
| | | |
| | | // 直接输入模式开关 |
| | | directInputMode: true, |
| | | // 弹窗相关 |
| | | currentItem: null, |
| | | inputQtyValue: '', |
| | | |
| | | mainTabSelected: 1, |
| | | subTabSelected: 0, |
| | | |
| | |
| | | }, |
| | | //不良原因单击 |
| | | reasonClick(item) { |
| | | // 直接输入模式下,单击直接弹出输入框 |
| | | if (this.directInputMode) { |
| | | this.showDirectInputDialog(item); |
| | | return; |
| | | } |
| | | const now = Date.now(); |
| | | if (now - this.lastClickTime < 300) { |
| | | // 双击逻辑 |
| | |
| | | this.handleSingleClick(item); |
| | | this.lastClickTime = now; |
| | | } |
| | | }, |
| | | // 模式切换 |
| | | onModeSwitchChange(e) { |
| | | this.directInputMode = e.detail.value; |
| | | }, |
| | | // 显示直接输入数量的弹窗 |
| | | showDirectInputDialog(item) { |
| | | this.currentItem = item; |
| | | this.inputQtyValue = String(item.num || 0); |
| | | this.$refs.inputQtyPopup.open(); |
| | | }, |
| | | // 取消输入 |
| | | cancelInputQty() { |
| | | this.$refs.inputQtyPopup.close(); |
| | | this.currentItem = null; |
| | | this.inputQtyValue = ''; |
| | | }, |
| | | // 确认输入 |
| | | confirmInputQty() { |
| | | const inputQty = parseInt(this.inputQtyValue); |
| | | if (isNaN(inputQty) || inputQty < 0) { |
| | | uni.showToast({ |
| | | title: '请输入有效数量', |
| | | icon: 'none' |
| | | }); |
| | | return; |
| | | } |
| | | this.submitBarCodeWithQty(this.currentItem, inputQty); |
| | | this.$refs.inputQtyPopup.close(); |
| | | this.currentItem = null; |
| | | this.inputQtyValue = ''; |
| | | }, |
| | | handleSingleClick(item) { |
| | | console.log('单击:', item.不良原因名称); |
| | |
| | | } |
| | | }) |
| | | this.HBadReasonList = data; |
| | | |
| | | this.getHisReportList();//获取历史记录 |
| | | } else { |
| | | CommonUtils.showTips({ |
| | | title: '温馨提示', |
| | |
| | | this.hform.HProcName= data[0].当前工序 |
| | | this.hform.HDeptID= data[0].HWorkShopID |
| | | this.getGy_BadReasonList(); |
| | | |
| | | } else { |
| | | CommonUtils.showTips({ |
| | | title: '温馨提示', |
| | |
| | | url: "/Sc_QualityReportBill/get_BarCodeDetail", |
| | | data: { |
| | | HInterID: this.hform.HInterID, |
| | | |
| | | |
| | | }, |
| | | }); |
| | | |
| | | |
| | | let { |
| | | data, |
| | | Message, |
| | | count |
| | | } = res.data; |
| | | |
| | | |
| | | if (count == 1) { |
| | | console.log("data: ", data); |
| | | this.HisReportList = data; |
| | | |
| | | // 统计各不良原因的数量并更新到 HBadReasonList |
| | | this.updateBadReasonNumFromHisReport(); |
| | | |
| | | } else { |
| | | this.HisReportList = []; |
| | | this.clearBadReasonNum(); |
| | | CommonUtils.showTips({ |
| | | title: "温馨提示", |
| | | message: `获取历史扫码记录失败: ${Message}`, |
| | |
| | | message: `获取历史扫码记录失败: ${err}`, |
| | | }); |
| | | } |
| | | }, |
| | | // 从 HisReportList 统计更新 HBadReasonList 的 num |
| | | updateBadReasonNumFromHisReport() { |
| | | // 先清空所有 num |
| | | this.HBadReasonList.forEach(item => { |
| | | this.$set(item, 'num', 0); |
| | | }); |
| | | |
| | | // 统计 HisReportList 中各不良原因的数量 |
| | | if (this.HisReportList && this.HisReportList.length > 0) { |
| | | this.HisReportList.forEach(hisItem => { |
| | | // 根据 HBadReasonID 匹配 |
| | | const matchedItem = this.HBadReasonList.find( |
| | | badItem => badItem.不良原因代码 == hisItem.HBadReasonNumber |
| | | ); |
| | | if (matchedItem) { |
| | | const currentNum = matchedItem.num || 0; |
| | | this.$set(matchedItem, 'num', currentNum + hisItem.HBadReasonHQty||1); |
| | | } |
| | | }); |
| | | } |
| | | }, |
| | | // 清空 HBadReasonList 的 num |
| | | clearBadReasonNum() { |
| | | this.HBadReasonList.forEach(item => { |
| | | this.$set(item, 'num', 0); |
| | | }); |
| | | }, |
| | | //删除历史记录 |
| | | delReason(item) { |
| | |
| | | title: "保存成功", |
| | | message: `保存成功`, |
| | | }); |
| | | if(!item.num){ |
| | | this.$set(item, 'num', 1); |
| | | }else{ |
| | | this.$set(item, 'num', item.num+1); |
| | | } |
| | | console.log(item.num) |
| | | //this.$set(item, 'num', newValue); |
| | | // 刷新历史记录,num会自动从HisReportList统计更新 |
| | | this.getHisReportList(); |
| | | this.hasCheckQty=true; |
| | | } else { |
| | | CommonUtils.showTips({ |
| | | title: "温馨提示", |
| | | message: `不良原因保存错误: ${Message}`, |
| | | }); |
| | | } |
| | | } catch (err) { |
| | | CommonUtils.showTips({ |
| | | title: "温馨提示", |
| | | message: `不良原因保存错误: ${err}`, |
| | | }); |
| | | } |
| | | }, |
| | | //提交不良原因扫码记录缓存(直接输入数量) |
| | | async submitBarCodeWithQty(item, qty){ |
| | | if(!this.checkSubmitValidate()){ |
| | | return |
| | | } |
| | | try { |
| | | let oMainObject = { |
| | | HInterID:this.hform.HInterID |
| | | ,HBillNo:this.hform.HBillNo |
| | | ,HBillType:this.hform.HBillType |
| | | ,HDate:new Date() |
| | | ,HICMOBillNo:this.hform.HICMOBillNo |
| | | ,HICMOInterID:this.hform.HICMOInterID |
| | | ,HICMOEntryID:this.hform.HICMOEntryID |
| | | ,HProcExchBillNo:this.hform.HProcExchBillNo |
| | | ,HProcExchInterID:this.hform.HProcExchInterID |
| | | ,HProcExchEntryID:this.hform.HProcExchEntryID |
| | | ,HProcID:this.hform.HProcID |
| | | ,HMaterID:this.hform.HMaterID |
| | | ,HSourceID:this.hform.HSourceID |
| | | ,HGroupID:this.hform.HGroupID |
| | | ,HDeptID:this.hform.HDeptID |
| | | ,HCheckManID:this.hform.HEmpID |
| | | ,HBadReasonID:item.HItemID |
| | | ,HBarCode:item.不良原因代码 |
| | | ,HMaker:this.hform.HMaker |
| | | ,HMakeDate:this.hform.HMakeDate |
| | | ,HReportType:1 |
| | | ,HSourceBillType:this.hform.HSourceBillType |
| | | ,HSourceBillNo:this.hform.HSourceBillNo |
| | | ,HSourceInterID:this.hform.HMainSourceInterID |
| | | ,HSourceEntryID:this.hform.HMainSourceEntryID |
| | | ,HBadReasonHQty:qty |
| | | ,HQty:this.hform.HCheckQty |
| | | } |
| | | var sMainStr = JSON.stringify(oMainObject); |
| | | var oMain = sMainStr + ';' + this.operationType; |
| | | |
| | | let res = await CommonUtils.doRequest2Sync({ |
| | | url: "/Sc_QualityReportBill/set_SaveBarCode", |
| | | data: { |
| | | oMain: oMain, |
| | | }, |
| | | method: "POST", |
| | | }); |
| | | |
| | | if (!res) { |
| | | return; |
| | | } |
| | | |
| | | let { |
| | | count, |
| | | Message, |
| | | data |
| | | } = res.data; |
| | | if (count == 1) { |
| | | CommonUtils.showTips({ |
| | | title: "保存成功", |
| | | message: `保存成功,数量: ${qty}`, |
| | | }); |
| | | // 刷新历史记录,num会自动从HisReportList统计更新 |
| | | this.getHisReportList(); |
| | | this.hasCheckQty = true; |
| | | } else { |
| | | CommonUtils.showTips({ |
| | | title: "温馨提示", |
| | |
| | | padding: 0; |
| | | } |
| | | |
| | | .bill-main-tabs, |
| | | .bill-main-tabs { |
| | | box-sizing: border-box; |
| | | width: 100%; |
| | | display: flex; |
| | | flex-direction: row; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | border-bottom: 1px solid #ddd; |
| | | padding: 20rpx 10rpx; |
| | | |
| | | .tabs-left { |
| | | display: flex; |
| | | flex-direction: row; |
| | | flex-wrap: nowrap; |
| | | gap: 20rpx; |
| | | flex-shrink: 0; |
| | | overflow-x: auto; |
| | | white-space: nowrap; |
| | | |
| | | view { |
| | | width: auto; |
| | | font-size: 30rpx; |
| | | color: #555; |
| | | text-align: center; |
| | | padding: 16rpx 0; |
| | | } |
| | | |
| | | .selected { |
| | | color: #3a78ff; |
| | | font-weight: bold; |
| | | border-bottom: 3px solid #3a78ff; |
| | | } |
| | | } |
| | | |
| | | .mode-switch-right { |
| | | display: flex; |
| | | flex-direction: row; |
| | | align-items: center; |
| | | gap: 10rpx; |
| | | flex-shrink: 0; |
| | | padding-right: 10rpx; |
| | | |
| | | .mode-text { |
| | | font-size: 24rpx; |
| | | color: #666; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .bill-sub-tabs { |
| | | box-sizing: border-box; |
| | | width: 100%; |
| | |
| | | } |
| | | } |
| | | |
| | | /* 直接输入数量弹窗样式 */ |
| | | .input-qty-popup { |
| | | background-color: #fff; |
| | | border-radius: 20rpx; |
| | | padding: 30rpx; |
| | | width: 600rpx; |
| | | box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.15); |
| | | |
| | | .popup-title { |
| | | font-size: 32rpx; |
| | | font-weight: bold; |
| | | color: #333; |
| | | text-align: center; |
| | | padding-bottom: 20rpx; |
| | | border-bottom: 1px solid #eee; |
| | | } |
| | | |
| | | .popup-content { |
| | | padding: 20rpx 0; |
| | | |
| | | .popup-info { |
| | | display: flex; |
| | | align-items: center; |
| | | padding: 10rpx 0; |
| | | |
| | | .popup-label { |
| | | font-size: 28rpx; |
| | | color: #666; |
| | | width: 180rpx; |
| | | } |
| | | |
| | | .popup-value { |
| | | font-size: 28rpx; |
| | | color: #333; |
| | | } |
| | | } |
| | | |
| | | .popup-input-row { |
| | | display: flex; |
| | | align-items: center; |
| | | padding: 15rpx 0; |
| | | margin-top: 10rpx; |
| | | |
| | | .popup-label { |
| | | font-size: 28rpx; |
| | | color: #666; |
| | | width: 180rpx; |
| | | } |
| | | |
| | | .popup-input { |
| | | flex: 1; |
| | | height: 60rpx; |
| | | border: 1px solid #acacac; |
| | | border-radius: 10rpx; |
| | | padding: 0 15rpx; |
| | | font-size: 28rpx; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .popup-buttons { |
| | | display: flex; |
| | | flex-direction: row; |
| | | gap: 10rpx; |
| | | padding-top: 20rpx; |
| | | border-top: 1px solid #eee; |
| | | |
| | | button { |
| | | border-radius: 50rpx; |
| | | width: 150rpx; |
| | | height: 60rpx; |
| | | line-height: 60rpx; |
| | | font-size: 28rpx; |
| | | } |
| | | |
| | | .btn-a { |
| | | background-color: #3a78ff; |
| | | color: #fff; |
| | | } |
| | | |
| | | .btn-c { |
| | | background-color: #acacac; |
| | | color: #fff; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .bill-main-content, |
| | | .bill-sub-content { |
| | | box-sizing: border-box; |
| | |
| | | HStatus: 1, |
| | | HSampleSchemeID: "", |
| | | HUnitID: 0, |
| | | HInspectVal: "", |
| | | HInspectVal: "0", |
| | | HTargetVal: "", |
| | | HUpLimit: "", |
| | | HDownLimit: "", |
| | | HInspectValQ:0, |
| | | HUpOffSet: "", |
| | | HDownOffSet: "", |
| | | HSampleDamageQty: 0, |
| | |
| | | HUpLimit: data["上限值"] || 0, |
| | | HDownLimit: data["下限值"] || 0, |
| | | HSampleDamageQty: data["样本破坏数"] || 0, |
| | | HInspectValQ: 0 |
| | | }); |
| | | await this.$nextTick(); |
| | | this.$refs.listPopup.exit(); |
| | |
| | | HStatus: 0, |
| | | HSampleSchemeID: data[i]["HSampleSchemeID"], |
| | | HUnitID: data[i]["HUnitID"], |
| | | HInspectVal: "", |
| | | HInspectVal: "0", |
| | | HTargetVal: "", |
| | | HUpLimit: data[i].上限值, |
| | | HDownLimit: data[i].下限值, |
| | |
| | | HStatus: 1, |
| | | HSampleSchemeID: "", |
| | | HUnitID: 0, |
| | | HInspectVal: "", |
| | | HInspectVal: "0", |
| | | HTargetVal: "", |
| | | HUpLimit: "", |
| | | HDownLimit: "", |
| | |
| | | HAQL: "", |
| | | HSamplingType: "", |
| | | HInspectResultToSee: "", |
| | | HInspectValQ: "", |
| | | HInspectValQ: "0", |
| | | isFocus: false, |
| | | }; |
| | | if (resource) { |
| | |
| | | HStatus: 0, |
| | | HSampleSchemeID: data[i]["HSampleSchemeID"], |
| | | HUnitID: data[i]["HUnitID"], |
| | | HInspectVal: "", |
| | | HInspectVal: "0", |
| | | HTargetVal: "", |
| | | HUpLimit: data[i].上限值, |
| | | HDownLimit: data[i].下限值, |
| | |
| | | HStatus: 1, |
| | | HSampleSchemeID: "", |
| | | HUnitID: 0, |
| | | HInspectVal: "", |
| | | HInspectVal: "0", |
| | | HTargetVal: "", |
| | | HUpLimit: "", |
| | | HDownLimit: "", |
| | |
| | | HStatus: 0, |
| | | HSampleSchemeID: data[i]["HSampleSchemeID"], |
| | | HUnitID: data[i]["HUnitID"], |
| | | HInspectVal: "", |
| | | HInspectVal: "0", |
| | | HTargetVal: "", |
| | | HUpLimit: data[i].上限值, |
| | | HDownLimit: data[i].下限值, |
| | |
| | | |
| | | // 在全局定义一个变量来标识是否已经初始化 |
| | | var isPrinterInitialized = false; |
| | | |
| | | import { |
| | | getUserInfo |
| | | } from "@/utils/auth.js"; |
| | | import { |
| | | CommonUtils |
| | | } from "@/utils/common.js" |
| | | import { |
| | | PrinterWS |
| | | } from "@/utils/Print_HK.js" |
| | | export default { |
| | | data() { |
| | | return { |
| | |
| | | barCodeSplitInfo: [], //拆码信息 |
| | | cantGenerate: true, // 生成按钮初始禁用 |
| | | cantPrint: true, // 打印按钮初始禁用 |
| | | cantPrint_HK: true, // 打印按钮初始禁用 |
| | | cantSplit: false, // 拆码按钮初始可用 |
| | | HBarCodeFocus: false, |
| | | isPrinting: false, |
| | | printInfo: "" //打印 |
| | | printInfo: "" ,//打印, |
| | | socketTask: null, // 存放 uni-app WebSocket 实例 |
| | | wsConnected: false, |
| | | wsReconnectTimer: null, |
| | | wsHeartbeatTimer: null, |
| | | }; |
| | | }, |
| | | methods: { |
| | |
| | | printer.setConcentration({ //设置打印浓度。font_level 取值范围:1~39。 |
| | | level: 39 |
| | | }); |
| | | |
| | | }, |
| | | printerLabel() { |
| | | const formatDate = new Date().toISOString().split('T')[0]; |
| | |
| | | printer.printGoToNextMark(); |
| | | console.log('测试打印QR结束'); |
| | | }, |
| | | printerLabel_HK() { |
| | | printerLabel_HK() { |
| | | //设置打印内容 |
| | | |
| | | var HPrintData = "SIZE 58 mm,40 mm" + '\r\n';//设置标签纸张大小; |
| | | HPrintData += "CLS" + '\r\n';//清除图像缓存区 |
| | | const formatDate = new Date().toISOString().split('T')[0]; |
| | | var HPrintData = "SIZE 58 mm,40 mm" + '\r\n'+ '\r\n'; //设置标签纸张大小; |
| | | HPrintData += "CLS" + '\r\n'+ '\r\n'; //清除图像缓存区 |
| | | //TEXT X, Y, “font”, rotation, x-multiplication, y-multiplication, [alignment,] |
| | | //X:文本X坐标; Y:文本Y坐标; font:字体名称; rotation:文字旋转角度(0:不旋转,90:90 度,180:180 度,270:270 度); x-multiplication:水平方向放大; y-multiplication:垂直方向放大; alignment:指定文本对齐方式(0:默认(居左),1:居左,2:居中,3:居右); content:需要打印的文本内容。 |
| | | HPrintData += 'TEXT 50, 50, "4",0,1,1,1' + '供应商名称:' + this.barCodeInfo['供应商'] + '\r\n'; |
| | | HPrintData += 'TEXT 50, 50, "4",0,1,1,1' + '物料代码:' + this.barCodeInfo['物料代码'] + '\r\n'; |
| | | HPrintData += 'TEXT 50, 50, "4",0,1,1,1' + '物料简称:' + this.barCodeInfo['物料简称'] + '\r\n'; |
| | | HPrintData += 'TEXT 50, 50, "4",0,1,1,1' + '数量:' + this.barCodeInfo['剩余数量'] + '\r\n'; |
| | | HPrintData += 'TEXT 50, 50, "4",0,1,1,1' + '工号:' + this.barCodeInfo['工号'] + '\r\n'; |
| | | HPrintData += 'TEXT 50, 50, "4",0,1,1,1' + '生产日期:' + this.barCodeInfo['生产日期'] + '\r\n'; |
| | | HPrintData += 'TEXT 50, 50, "4",0,1,1,1' + '流水号:' + this.barCodeInfo['流水号'] + '\r\n'; |
| | | HPrintData += 'TEXT 50, 50, "4",0,1,1,1' + '打印日期:' + formatDate + '\r\n'; |
| | | HPrintData += this.barCodeInfo['条码编号']; |
| | | printer.sendCommand_HK(HPrintData); |
| | | HPrintData += 'TEXT 50, 50, "4",0,1,1,1,' + '"供应商名称:' + this.barCodeInfo['供应商'] + '"' + '\r\n' + '\r\n'; |
| | | HPrintData += 'TEXT 50, 50, "4",0,1,1,1,' + '"物料代码:' + this.barCodeInfo['物料代码'] + '"' + '\r\n' + '\r\n'; |
| | | HPrintData += 'TEXT 50, 50, "4",0,1,1,1,' + '"物料简称:' + this.barCodeInfo['物料简称'] + '"' + '\r\n' + '\r\n'; |
| | | HPrintData += 'TEXT 50, 50, "4",0,1,1,1,' + '"数量:' + this.barCodeInfo['剩余数量'] + '"' + '\r\n' + '\r\n'; |
| | | HPrintData += 'TEXT 50, 50, "4",0,1,1,1,' + '"工号:' + this.barCodeInfo['工号'] + '"' + '\r\n' + '\r\n'; |
| | | HPrintData += 'TEXT 50, 50, "4",0,1,1,1,' + '"生产日期:' + this.barCodeInfo['生产日期'] + '"' + '\r\n' + '\r\n'; |
| | | HPrintData += 'TEXT 50, 50, "4",0,1,1,1,' + '"流水号:' + this.barCodeInfo['流水号'] + '"' + '\r\n' + '\r\n'; |
| | | HPrintData += 'TEXT 50, 50, "4",0,1,1,1,' + '"打印日期:' + formatDate + '"' + '\r\n' + '\r\n'; |
| | | //HPrintData += this.barCodeInfo['条码编号']; |
| | | HPrintData += 'PRINT 1' + '\r\n' + '\r\n'; |
| | | |
| | | |
| | | var HPrintData2 = "SIZE 58 mm,40 mm" + '\r\n'+ '\r\n'; //设置标签纸张大小; |
| | | HPrintData2 += "CLS" + '\r\n'+ '\r\n'; //清除图像缓存区 |
| | | HPrintData2 += 'TEXT 50, 50, "4",0,1,1,1,"DEMO FOR TEXT"' + '\r\n'+ '\r\n'; |
| | | HPrintData2 += 'QRCODE 0, 92, M, 4, A, 0, M1,S0,"ABCD1234"' + '\r\n'+ '\r\n'; |
| | | HPrintData2 += 'PRINT 1' + '\r\n' + '\r\n'; |
| | | |
| | | |
| | | this.sendCommand_HK(HPrintData2); |
| | | }, |
| | | // 发送打印命令 |
| | | sendCommand_HK(commandData) { |
| | | if (this.ws.readyState === WebSocket.OPEN) { |
| | | // this.ws.send(JSON.stringify(commandData)); |
| | | this.ws.send(commandData); |
| | | |
| | | } else { |
| | | console.error('WebSocket 未连接'); |
| | | async sendCommand_HK(commandData) { |
| | | // 检查 WebSocket 是否已连接 |
| | | if (!this.socketTask) { |
| | | console.error('WebSocket 未初始化'); |
| | | uni.showToast({ |
| | | title: '打印机未连接', |
| | | icon: 'none' |
| | | }); |
| | | return false; |
| | | } |
| | | |
| | | if (this.socketTask.readyState === 1) { |
| | | console.log("打印内容:" + '\r\n' + commandData); |
| | | this.socketTask.send({ |
| | | data: commandData, |
| | | success: () => { |
| | | console.log('命令发送成功'); |
| | | }, |
| | | fail: (err) => { |
| | | console.error('命令发送失败:', err); |
| | | } |
| | | }); |
| | | return true; |
| | | } else { |
| | | console.error('WebSocket 未连接,当前状态:', this.socketTask.readyState); |
| | | uni.showToast({ |
| | | title: '打印机连接中,请稍后重试', |
| | | icon: 'none' |
| | | }); |
| | | return false; |
| | | } |
| | | }, |
| | | // 初始化连接 |
| | | async connect() { |
| | | return new Promise((resolve, reject) => { |
| | | // 关闭现有连接 |
| | | if (this.socketTask) { |
| | | try { |
| | | this.socketTask.close(); |
| | | } catch(e) {} |
| | | this.socketTask = null; |
| | | } |
| | | |
| | | // 根据实际环境配置 - 注意:在真实PDA上可能需要具体IP |
| | | // 先尝试使用 127.0.0.1,如果不行再尝试实际IP 'ws://localhost:40002' |
| | | const wsUrl = 'ws://192.168.2.141:40001'; |
| | | |
| | | console.log('准备连接 WebSocket:', wsUrl); |
| | | |
| | | this.socketTask = uni.connectSocket({ |
| | | url: wsUrl, |
| | | success: () => { |
| | | console.log('WebSocket 连接创建成功'); |
| | | }, |
| | | fail: (err) => { |
| | | console.error('WebSocket 连接失败:', err); |
| | | reject(err); |
| | | } |
| | | }); |
| | | |
| | | // 设置超时 |
| | | const timeoutId = setTimeout(() => { |
| | | console.log('连接超时'); |
| | | if (this.socketTask && this.socketTask.close) { |
| | | this.socketTask.close(); |
| | | } |
| | | reject(new Error('连接超时(5秒)')); |
| | | }, 5000); |
| | | |
| | | console.log("this.socketTask内容:" + JSON.stringify(this.socketTask)); |
| | | // 监听打开事件 |
| | | this.socketTask.onOpen(() => { |
| | | clearTimeout(timeoutId); |
| | | console.log("WebSocket 连接成功,readyState:", this.socketTask.readyState); |
| | | this.wsConnected = true; |
| | | resolve(); |
| | | }); |
| | | |
| | | // 监听错误事件 - 这里会收到详细的错误信息 |
| | | this.socketTask.onError((err) => { |
| | | clearTimeout(timeoutId); |
| | | console.error("WebSocket 错误详情:", JSON.stringify(err)); |
| | | console.error("WebSocket readyState:", this.socketTask.readyState); |
| | | this.wsConnected = false; |
| | | reject(new Error('WebSocket 连接失败: ' + JSON.stringify(err))); |
| | | }); |
| | | |
| | | // 监听关闭事件 |
| | | this.socketTask.onClose((res) => { |
| | | clearTimeout(timeoutId); |
| | | console.log("WebSocket 连接关闭,code:", res.code, "reason:", res.reason); |
| | | console.log("关闭时的 readyState:", this.socketTask.readyState); |
| | | this.wsConnected = false; |
| | | |
| | | // 如果是非正常关闭,提示用户 |
| | | if (res.code !== 1000) { |
| | | console.warn('非正常关闭,错误码:', res.code); |
| | | } |
| | | }); |
| | | |
| | | // 监听消息 |
| | | this.socketTask.onMessage((res) => { |
| | | console.log("收到打印机消息:", res.data); |
| | | }); |
| | | }); |
| | | }, |
| | | // 添加心跳检测,保持连接 |
| | | startHeartbeat() { |
| | | if (this.wsHeartbeatTimer) { |
| | | clearInterval(this.wsHeartbeatTimer); |
| | | } |
| | | |
| | | this.wsHeartbeatTimer = setInterval(() => { |
| | | if (this.socketTask && this.socketTask.readyState === 1) { |
| | | // 发送心跳包 |
| | | this.socketTask.send({ |
| | | data: 'ping', |
| | | fail: (err) => { |
| | | console.log('心跳发送失败:', err); |
| | | this.wsConnected = false; |
| | | } |
| | | }); |
| | | } else if (this.socketTask && this.socketTask.readyState !== 1) { |
| | | console.log('WebSocket 状态异常,readyState:', this.socketTask?.readyState); |
| | | this.wsConnected = false; |
| | | } |
| | | }, 30000); // 每30秒发送一次心跳 |
| | | }, |
| | | // 添加连接状态检查方法 |
| | | checkConnection() { |
| | | return new Promise((resolve) => { |
| | | if (!this.socketTask) { |
| | | resolve(false); |
| | | return; |
| | | } |
| | | |
| | | if (this.socketTask.readyState === 1) { |
| | | // 已连接,发送测试消息确认 |
| | | this.socketTask.send({ |
| | | data: 'test', |
| | | success: () => { |
| | | resolve(true); |
| | | }, |
| | | fail: () => { |
| | | resolve(false); |
| | | } |
| | | }); |
| | | } else { |
| | | console.log('连接状态:', this.socketTask.readyState); |
| | | resolve(false); |
| | | } |
| | | }); |
| | | }, |
| | | // 测试打印机服务 |
| | | async testPrinterService() { |
| | | console.log('开始测试打印机服务...'); |
| | | |
| | | // 尝试不同的地址 |
| | | const testUrls = [ |
| | | 'ws://127.0.0.1:40002', |
| | | 'ws://localhost:40002', |
| | | 'ws://192.168.2.141:40001', |
| | | 'ws://192.168.2.141:40002', |
| | | // 如果有具体IP,可以添加 |
| | | // 'ws://192.168.1.100:40002' |
| | | ]; |
| | | |
| | | for (const url of testUrls) { |
| | | console.log(`测试地址: ${url}`); |
| | | try { |
| | | const result = await this.testConnect(url); |
| | | if (result) { |
| | | console.log(`成功连接到: ${url}`); |
| | | uni.showToast({ |
| | | title: `找到打印机: ${url}`, |
| | | icon: 'success' |
| | | }); |
| | | return true; |
| | | } |
| | | } catch (e) { |
| | | console.log(`连接失败: ${url}`, e); |
| | | } |
| | | } |
| | | |
| | | console.log('所有地址测试失败'); |
| | | uni.showToast({ |
| | | title: '未找到打印机服务', |
| | | icon: 'none', |
| | | duration: 3000 |
| | | }); |
| | | return false; |
| | | }, |
| | | |
| | | // 测试单个连接 |
| | | testConnect(url) { |
| | | return new Promise((resolve) => { |
| | | const socket = uni.connectSocket({ |
| | | url: url, |
| | | success: () => { |
| | | console.log(`测试连接创建成功: ${url}`); |
| | | } |
| | | }); |
| | | |
| | | const timeout = setTimeout(() => { |
| | | if (socket) { |
| | | socket.close(); |
| | | } |
| | | resolve(false); |
| | | }, 2000); |
| | | |
| | | socket.onOpen(() => { |
| | | clearTimeout(timeout); |
| | | socket.close(); |
| | | resolve(true); |
| | | }); |
| | | |
| | | socket.onError((err) => { |
| | | clearTimeout(timeout); |
| | | console.log(`测试连接错误: ${url}`, err); |
| | | resolve(false); |
| | | }); |
| | | }); |
| | | }, |
| | | doRequest(url, data, resFunction, errFunction, method) { |
| | | uni.showLoading({ |
| | |
| | | async searchbarCodeInfoMeta() { |
| | | this.cantGenerate = true |
| | | this.cantPrint = true |
| | | this.cantPrint_HK = true |
| | | this.cantSplit = false // 拆码前确保拆码按钮可用 |
| | | if (CommonUtils.isEmpty(this.barCodeInfoMeta.barCodeNo) === true) { |
| | | return uni.showToast({ |
| | |
| | | this.cantSplit = true; |
| | | this.cantGenerate = false; |
| | | this.cantPrint = true; |
| | | this.cantPrint_HK = true; |
| | | //生成 |
| | | this.SaveBarCodeCreate(); |
| | | } else { |
| | |
| | | // 生成成功,禁用生成按钮,放开打印按钮 |
| | | this.cantGenerate = true; |
| | | this.cantPrint = false; |
| | | this.cantPrint_HK = false; |
| | | this.cantSplit = true; |
| | | this.barCodeInfoMeta.barCodeNo = ""; //清空输入框 |
| | | uni.showToast({ |
| | |
| | | CommonUtils.playSound(0); |
| | | } |
| | | }, |
| | | |
| | | |
| | | //海康打印按钮 |
| | | async PrintHBarCode() { |
| | | // 防止重复点击 |
| | | async PrintHBarCode_HK() { |
| | | if (this.isPrinting) { |
| | | uni.showToast({ |
| | | title: '打印中,请稍候...', |
| | | icon: 'none' |
| | | }); |
| | | return; |
| | | uni.showToast({ |
| | | title: '打印中,请稍候...', |
| | | icon: 'none' |
| | | }); |
| | | return; |
| | | } |
| | | |
| | | // 先检查打印机服务是否可用 |
| | | uni.showLoading({ |
| | | title: '检查打印机...', |
| | | mask: true |
| | | }); |
| | | |
| | | this.isPrinting = true; |
| | | |
| | | |
| | | try { |
| | | this.printerLabel_HK(); //打印 |
| | | // 检查当前连接状态 |
| | | const isConnected = await this.checkConnection(); |
| | | |
| | | if (!isConnected) { |
| | | uni.showLoading({ |
| | | title: '连接打印机...', |
| | | mask: true |
| | | }); |
| | | await this.connect(); |
| | | this.startHeartbeat(); // 启动心跳 |
| | | } |
| | | |
| | | uni.hideLoading(); |
| | | |
| | | // 确认连接成功 |
| | | if (this.socketTask && this.socketTask.readyState === 1) { |
| | | this.isPrinting = true; |
| | | this.printerLabel_HK(); |
| | | |
| | | // 延迟重置打印状态 |
| | | setTimeout(() => { |
| | | this.isPrinting = false; |
| | | }, 3000); |
| | | } else { |
| | | throw new Error(`打印机未连接,状态: ${this.socketTask?.readyState}`); |
| | | } |
| | | |
| | | } catch (error) { |
| | | uni.hideLoading(); |
| | | console.error('打印失败:', error); |
| | | this.isPrinting = false; |
| | | |
| | | uni.showToast({ |
| | | title: error.message || '打印失败', |
| | | icon: 'error', |
| | | duration: 2000 |
| | | this.wsConnected = false; |
| | | |
| | | uni.showModal({ |
| | | title: '打印失败', |
| | | content: error.message || '请检查:\n1. 打印机服务是否启动\n2. 打印机地址是否正确\n3. 网络是否通畅', |
| | | confirmText: '重试', |
| | | cancelText: '取消', |
| | | success: (res) => { |
| | | if (res.confirm) { |
| | | setTimeout(() => { |
| | | this.PrintHBarCode_HK(); |
| | | }, 1000); |
| | | } |
| | | } |
| | | }); |
| | | CommonUtils.playSound(0); |
| | | } |
| | | }, |
| | | |
| | | |
| | | toScanCode() { |
| | | var mpaasScanModule = uni.requireNativePlugin("Mpaas-Scan-Module") |
| | | mpaasScanModule.mpaasScan({ |
| | |
| | | this.cantSplit = false; // 拆码按钮可用 |
| | | this.cantGenerate = true; // 生成按钮禁用 |
| | | this.cantPrint = true; // 打印按钮禁用 |
| | | this.cantPrint_HK = true; // 打印按钮禁用 |
| | | } |
| | | }, |
| | | onLoad() { |
| | |
| | | } |
| | | //初始化打印 |
| | | this.initPrinter(); |
| | | |
| | | // 预连接海康打印机(可选,不阻塞页面) |
| | | this.connect().catch(err => { |
| | | console.warn('海康打印机预连接失败:', err); |
| | | }); |
| | | // 测试打印机服务(可选) |
| | | setTimeout(() => { |
| | | this.testPrinterService(); |
| | | }, 1000); |
| | | }, |
| | | onReady() { |
| | | |
| | | }, |
| | | onUnload() { |
| | | // 调用同步方法 |
| | | |
| | | // 清理定时器 |
| | | if (this.wsHeartbeatTimer) { |
| | | clearInterval(this.wsHeartbeatTimer); |
| | | this.wsHeartbeatTimer = null; |
| | | } |
| | | |
| | | if (this.wsReconnectTimer) { |
| | | clearTimeout(this.wsReconnectTimer); |
| | | this.wsReconnectTimer = null; |
| | | } |
| | | |
| | | // 关闭 WebSocket 连接 |
| | | if (this.socketTask) { |
| | | this.socketTask.close({ |
| | | code: 1000, |
| | | reason: '页面卸载' |
| | | }); |
| | | this.socketTask = null; |
| | | } |
| | | |
| | | this.wsConnected = false; |
| | | } |
| | | } |
| | | </script> |
| New file |
| | |
| | | class PrinterWS { |
| | | constructor(url) { |
| | | this.ws = uni.connectSocket({ |
| | | url: 'ws://localhost:40002', // 支持 wss(加密) / ws(非加密) |
| | | success: () => { |
| | | console.log('WebSocket 连接创建成功'); |
| | | } |
| | | }); |
| | | this.url = url; |
| | | //this.connect(); |
| | | } |
| | | |
| | | // 初始化连接 |
| | | connect(url) { |
| | | this.url = url; |
| | | this.ws = new WebSocket(this.url); |
| | | this.ws.onopen = () => { |
| | | console.log('WebSocket 连接已建立'); |
| | | }; |
| | | this.ws.onmessage = (event) => { |
| | | try { |
| | | const response = event.data; |
| | | var consoleInfo = document.getElementById("console").value; |
| | | consoleInfo = consoleInfo +"\n" + response; |
| | | document.getElementById("console").value = consoleInfo; |
| | | // alert(response); |
| | | } catch(error) { |
| | | console.error('消息解析失败:', error); |
| | | } |
| | | }; |
| | | this.ws.onerror = (error) => { |
| | | alert('WebSocket 错误:', error); |
| | | }; |
| | | this.ws.onclose = () => { |
| | | alert('WebSocket 连接已关闭'); |
| | | }; |
| | | } |
| | | } |
| | | |
| | | // 导出单例 |
| | | export default new PrinterWS(); |