pda-cli/src/pages/saleship/salepickscandetail.vue
xuan 9272ed0e23 feat(scanner): 多厂商PDA扫码器兼容方案及扫码功能重构
- 采用策略模式及配置表驱动方式支持多品牌扫码器广播注册
- 实现扫码广播的统一注册和注销管理,支持并发多个扫码广播接收器
- 重构扫码处理逻辑,统一处理扫码结果,支持条码和二维码识别
- 移除原有单一品牌扫码注册,整合商米、新大陆等扫码头支持
- 调整扫码相关页面代码,集成scanMixin,实现扫码广播注册和注销自动化
- 优化扫码结果处理,支持删除模式及整缸扫描状态区分
- 修正多处界面文本格式与代码风格,提高代码一致性和可维护性
- 升级manifest版本号至1.1.3,标记此功能更新
2026-01-04 13:57:28 +08:00

554 lines
15 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<view class="wrap">
<u-form ref="uForm">
<u-form-item>
<text class="title" style="width: 200px">单号{{ BillNo }}</text>
<text class="title" style="width: 200px">日期{{ BillDate }}</text>
</u-form-item>
<u-form-item>
<text class="title" style="width: 200px">客户名称{{ CustomerName }}</text>
<text class="title" style="width: 200px"> {{ SaleUserName }}</text>
</u-form-item>
<u-form-item>
<text class="title" style="width: 200px">仓库名称{{ StoreName }}{{ ToStoreName }}</text>
</u-form-item>
<u-form-item>
<text class="title" style="width: 200px">备注内容{{ BillRemark }}</text>
</u-form-item>
<u-form-item label-width="130" label="条码资料:">
<input type="text" v-model="QRBarCode" maxlength="-1" style="width: 170px" @confirm="SalePickBillDetailScan" />
<checkbox-group @change="handleAllCrockNoChange">
<checkbox :checked="AllCrockNoScanStatus">整缸</checkbox>
</checkbox-group>
<checkbox-group @change="handleBarCodeDelChange">
<checkbox :checked="BarCodeDelStatus">删除</checkbox>
</checkbox-group>
</u-form-item>
</u-form>
<u-form ref="uForm">
<u-form-item>
<text class="title" style="width: 400px">成品名称{{ FabricGoodsNo }}{{ FabricGoodsName }}</text>
</u-form-item>
<u-form-item>
<text class="title" style="width: 400px">色号颜色{{ GoodsCodeNo }}{{ GoodsCodeName }}</text>
</u-form-item>
<u-form-item>
<text class="title" style="width: 200px">成品缸号{{ CrockNo }}</text>
<text class="title" style="width: 200px">成品卷号{{ GoodsBillNo }}</text>
</u-form-item>
<u-form-item>
<text class="title">{{ BillDataMessage }}</text>
</u-form-item>
<u-form-item>
<text class="title" style="width: 130px">配布条数{{ BillSumRoll }}</text>
<text class="title" style="width: 130px">数量{{ BillSumQty }}</text>
<text class="title" style="width: 120px">米数{{ BillSumMQty }}</text>
</u-form-item>
<u-form-item>
<text class="title" style="width: 130px">已配条数{{ BillScanRoll }}</text>
<text class="title" style="width: 130px">数量{{ BillScanQty }}</text>
<text class="title" style="width: 120px">米数{{ BillScanMQty }}</text>
</u-form-item>
<view class="submitView">
<u-button type="primary" class="submitBtn" :ripple="true" :loading="submitLoading" ripple-bg-color="#909399"
@click="submitBtnFun">
{{ pageType ? "保存" : "提交" }}
</u-button>
</view>
</u-form>
<view class="u-demo-area">
<u-toast ref="uToast"></u-toast>
<wyb-table ref="table" :headers="headersMaster" :contents="GoodsDetailList" />
</view>
</view>
</template>
<script>
import util, {
parFabricGoodsBarCode2D,
parYarnGoodsBarCode2D,
playSuccessAudio,
playErrorAudio,
} from "../../common/util";
import wybTable from "@/components/wyb-table/wyb-table.vue";
import scanMixin from "@/common/scanMixin.js";
let that = "";
export default {
mixins: [scanMixin],
data() {
return {
SaleBillNo: "", // 单号
BillMasterID: 0, // 订单ID
borderColor: "#e4e7ed",
align: "center",
index: 0,
pageType: "",
submitLoading: false,
actionSheetShow: false,
QRBarCode: "",
BillNo: "",
BillDate: "",
BillTypeID: 0,
BillRemark: "",
CustomerName: "",
StoreNameID: 0,
StoreName: "",
ToStoreName: "",
SaleUserName: "",
BillTypeName: "",
FabricGoodsNo: "",
FabricGoodsName: "",
GoodsCodeNo: "",
GoodsCodeName: "",
CrockNo: "",
GoodsBillNo: "",
BillSumRoll: 0,
BillSumQty: 0,
BillSumMQty: 0,
BillScanRoll: 0,
BillScanQty: 0,
BillScanMQty: 0,
AllCrockNoScanStatus: false,
BarCodeDelStatus: false,
GoodsDetailList: [],
BillDataMessage: "",
headersMaster: [
{
label: "成品编号",
key: "product_code",
},
{
label: "色号",
key: "product_color_code",
},
{
label: "颜色",
key: "product_color_name",
},
{
label: "缸号",
key: "dye_factory_dyelot_number",
},
{
label: "配布条数",
key: "push_roll",
},
{
label: "配布数量",
key: "push_weight",
},
{
label: "配布长度",
key: "push_length",
},
{
label: "已配条数",
key: "arrange_roll",
},
{
label: "已配数量",
key: "arrange_weight",
},
{
label: "成品等级",
key: "product_level_name",
},
{
label: "成品备注",
key: "product_remark",
},
],
scanningInput: "", // 用于累积扫码输入
lastKeyTime: 0, // 用于判断扫码速度
// scanReceiver 和 isPageActive 由 scanMixin 提供
};
},
onLoad(e) {
that = this;
if (e.billid) {
that.BillMasterID = e.billid;
}
if (e.order_no) {
that.SaleBillNo = e.order_no;
}
this.SalePickDetail();
// #ifdef APP-PLUS
this.isPageActive = true;
// this.registerScanBroadcast();
// #endif
},
onUnload() {
this.isPageActive = false;
// #ifdef APP-PLUS
this.unregisterScanBroadcast();
// #endif
},
onHide() {
this.isPageActive = false;
// #ifdef APP-PLUS
this.unregisterScanBroadcast();
// #endif
},
onShow() {
this.isPageActive = true;
// #ifdef APP-PLUS
this.registerScanBroadcast((scanResult) => {
console.log("配布单详情-扫码结果:", scanResult);
this.QRBarCode = scanResult;
this.$nextTick(() => {
this.handleScans();
});
});
// #endif
},
methods: {
playSuccess() {
util.playSuccessAudio();
},
playError() {
util.playErrorAudio();
},
handleAllCrockNoChange() {
if (this.AllCrockNoScanStatus) {
this.AllCrockNoScanStatus = false;
} else {
this.AllCrockNoScanStatus = true;
this.BarCodeDelStatus = false;
}
},
handleBarCodeDelChange() {
if (this.BarCodeDelStatus) {
this.BarCodeDelStatus = false;
} else {
this.BarCodeDelStatus = true;
this.AllCrockNoScanStatus = false;
}
},
SalePickDetail: function () {
// 获取成品配布单详情
this.$u.api.getFpmArrangeOrder({
id: this.BillMasterID,
order_no: this.SaleBillNo
}).then(res => {
this.triggered = false;
var aResultData = res;
this.BillMasterID = aResultData.id; // 重写订单ID
this.BillNo = aResultData.order_no; // 重写单号
this.BillDate = this.$u.timeFormat(
aResultData.arrange_time,
"yyyy-mm-dd"
);
this.CustomerName = aResultData.biz_unit_name;
this.StoreNameID = aResultData.warehouse_id;
this.StoreName = aResultData.warehouse_name;
this.SaleUserName = aResultData.sale_user_name;
this.BillTypeName = aResultData.out_order_type_name;
this.BillRemark = aResultData.internal_remark;
this.BillSumRoll = aResultData.push_roll / 100 + "匹";
this.BillSumQty = aResultData.push_weight / 10000 + "Kg";
this.BillSumMQty = aResultData.push_length / 10000 + "米";
this.BillScanRoll = aResultData.total_roll / 100 + "匹";
this.BillScanQty = aResultData.total_weight / 10000 + "Kg";
this.BillScanMQty = aResultData.total_length / 10000 + "米";
let aResultDataList = res.item_data;
for (var i = 0; i < aResultDataList.length; i++) {
aResultDataList[i].push_roll = aResultDataList[i].push_roll / 100;
aResultDataList[i].push_weight = aResultDataList[i].push_weight / 10000;
aResultDataList[i].push_length = aResultDataList[i].push_length / 10000;
aResultDataList[i].arrange_roll = aResultDataList[i].arrange_roll / 100;
aResultDataList[i].arrange_weight = aResultDataList[i].arrange_weight / 10000;
}
this.GoodsDetailList = aResultDataList;
}).catch(error => {
this.triggered = false;
this.showError(error.msg);
});
},
// 添加通用错误提示方法
showError(message) {
this.playError();
uni.showModal({
title: '提示',
content: message,
showCancel: false
});
},
// 添加成功提示方法
showSuccess(message) {
this.playSuccess();
uni.showToast({
title: message,
icon: 'success'
});
},
handleScans() {
// 删除模式判断
let aBarCodeDelStatus = 1; // 1=正常扫码3=删除模式
if (this.BarCodeDelStatus) {
aBarCodeDelStatus = 3;
}
// 整缸扫描判断
let aAllCrockNoScanStatus = 2; // 0=普通扫描1=整缸扫描
if (this.AllCrockNoScanStatus) {
aAllCrockNoScanStatus = "1";
}
// 数据清理:去除空格、换行符等
let cleanCode = this.QRBarCode.replace(/\s+/g, '').replace(/[\r\n]/g, '');
console.log("this.QRBarCode ---->>" + cleanCode);
// 初始化条码和二维码变量
let aQRBarCode = "";
let aBarCode = "";
if (cleanCode.startsWith("66^") || cleanCode.startsWith("99^") || /[\u4E00-\u9FA5]/.test(cleanCode)) {
aQRBarCode = cleanCode;
} else {
aBarCode = cleanCode;
}
if (aQRBarCode == "" && aBarCode == "") {
this.QRBarCode = "";
this.showError('请扫描二维码或者条码');
return;
}
console.log('请求参数', aBarCodeDelStatus);
console.log('请求参数', aBarCode);
console.log('请求参数', aQRBarCode);
console.log('请求参数', this.BillMasterID);
console.log('请求参数 SaleBillNo', this.SaleBillNo);
console.log('请求参数 token', uni.getStorageSync("userToken").Token);
// 发送请求
util.request({
url: "/product/fpmArrangeOrder/updateFpmArrangeOrder",
method: "PUT",
header: {
Platform: 2,
Authorization: uni.getStorageSync("userToken").Token,
},
data: {
arrange_type: aBarCodeDelStatus, // 1=正常扫码3=删除模式
bar_code: aBarCode, // 条码(如果是条形码就使用这个)
qr_code: aQRBarCode, // 二维码(如果是二维码就使用这个)
id: parseInt(this.BillMasterID), // 订单ID
// order_no: this.SaleBillNo, // 单号
},
success: (res) => {
console.log('API响应:', res);
if (res.data.code == 0 && res.data.msg == "success") {
var aResultData = res.data.data;
this.playSuccess();
this.FabricGoodsNo = aResultData.product_code;
this.FabricGoodsName = aResultData.product_name;
this.GoodsCodeNo = aResultData.product_color_code;
this.GoodsCodeName = aResultData.product_color_name;
this.CrockNo = aResultData.dyelot_number;
this.GoodsBillNo = aResultData.volume_number;
this.QRBarCode = "";
if (aBarCodeDelStatus == 1) {
this.showSuccess("扫描成功!");
} else {
this.showSuccess("删除成功!");
}
this.SalePickDetail();
} else {
this.showError("扫描出错," + res.data.msg);
this.QRBarCode = "";
}
},
fail: (error) => {
console.error('API请求失败:', error);
this.QRBarCode = "";
this.showError("连接服务器出错,请检查后台服务是否启动!");
},
});
},
SalePickBillDetailScan() {
// 聚焦输入框触发的方法
this.handleScans();
},
// 提交按钮方法
submitBtnFun: function () {
if (this.BillMasterID == 0) {
this.playError();
this.BillDataMessage = "单号为空,不能提交";
return;
}
// 获取配布总匹数和已配匹数进行比较
const totalRoll = parseFloat(this.BillSumRoll.replace('匹', '')); // 配布总匹数
const arrangedRoll = parseFloat(this.BillScanRoll.replace('匹', '')); // 已配匹数
if (arrangedRoll < totalRoll) {
// 如果已配匹数小于总匹数,显示确认弹窗
uni.showModal({
title: '提示',
content: '配布匹数不足,是否确定提交',
cancelText: '取消',
confirmText: '确定',
success: (res) => {
if (res.confirm) {
// 用户点击确定,继续提交
this.submitOrder();
}
}
});
} else {
// 匹数足够,直接提交
this.submitOrder();
}
},
// 新增提交订单的方法
submitOrder: function () {
this.submitLoading = true
this.$u.api.outFpmArrangeOrder({
id: parseInt(this.BillMasterID)
}).then(res => {
this.submitLoading = false
console.log('outFpmArrangeOrder res', res)
if (res) {
this.BillDataMessage = "成功生成出仓单!";
this.playSuccess();
} else {
this.playError();
this.BillDataMessage = "提交生成出仓单出错!" + res.msg;
return;
}
}).catch(error => {
this.submitLoading = false
this.playError();
this.BillDataMessage = "连接服务器出错,请检查后台服务是否启动!";
});
},
},
};
</script>
<style>
page {
background-color: #f8f8f8;
padding-bottom: 260rpx;
}
.u-radio {
width: 200rpx !important;
}
.submitView {
width: 100%;
padding: 16rpx 0 26rpx;
background-color: #ffffff;
position: fixed;
bottom: 0;
left: 0;
border-top: 1rpx solid #f1f1f1;
display: flex;
align-items: center;
justify-content: center;
z-index: 100;
}
.submitBtn {
width: 666rpx;
}
.productBox {
background-color: #ffffff;
margin-top: 32rpx;
padding: 26rpx 0;
}
.tjcpName {
width: 686rpx;
height: 40rpx;
font-size: 16px;
font-weight: bold;
border-left: 6rpx solid #007aff;
padding-left: 12rpx;
margin-left: 26rpx;
margin-top: 26rpx;
}
.cpInput {
width: 150rpx !important;
margin-right: 12rpx;
}
.cpInput>input {
box-sizing: border-box;
border: 1rpx solid #dddddd;
width: 100%;
height: 60rpx;
border-radius: 10rpx;
padding: 0 10rpx;
}
.cpInput1 {
width: 200rpx !important;
margin-right: 12rpx;
}
.cpInput1>input {
box-sizing: border-box;
border: 1rpx solid #dddddd;
width: 100%;
height: 60rpx;
border-radius: 10rpx;
padding: 0 10rpx;
}
.clearIcon {
position: absolute;
right: 6rpx;
top: 6rpx;
}
.greenPrice {
font-size: 16px;
color: #19be6b !important;
font-weight: bold;
}
.disFlex {
display: flex;
align-items: center;
margin-bottom: 8rpx;
}
.inputName {
color: #adadad;
font-size: 16px;
}
.addHKQS {
display: flex;
align-items: center;
padding: 16rpx 26rpx;
font-size: 15px;
font-weight: bold;
width: 100%;
display: flex;
align-items: center;
justify-content: center;
}
</style>